Commit a WinAPI implementation of cen64_gl_*.

This commit is contained in:
Tyler J. Stachecki 2015-04-25 15:39:07 -04:00
parent 6eccdf4901
commit 6d4d8a442a
8 changed files with 589 additions and 0 deletions

35
os/winapi/gl_common.h Normal file
View file

@ -0,0 +1,35 @@
//
// os/winapi/gl_common.h: Common WinAPI/OpenGL header.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_COMMON
#define CEN64_OS_WINAPI_GL_COMMON
#include "common.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
enum cen64_gl_context_type {
CEN64_GL_CONTEXT_TYPE_RGBA = PFD_TYPE_RGBA,
CEN64_GL_CONTEXT_TYPE_COLOR_INDEX = PFD_TYPE_COLORINDEX
};
enum cen64_gl_drawable_type {
CEN64_GL_DRAWABLE_TYPE_WINDOW = PFD_DRAW_TO_WINDOW,
CEN64_GL_DRAWABLE_TYPE_BITMAP = PFD_DRAW_TO_BITMAP
};
enum cen64_gl_layer_type {
CEN64_GL_LAYER_TYPE_DEFAULT = PFD_MAIN_PLANE,
CEN64_GL_LAYER_TYPE_OVERLAY = PFD_OVERLAY_PLANE,
CEN64_GL_LAYER_TYPE_UNDERLAY = PFD_UNDERLAY_PLANE
};
#endif

101
os/winapi/gl_config.c Normal file
View file

@ -0,0 +1,101 @@
//
// os/winapi/gl_config.c: WinAPI/OpenGL framebuffer configuration.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#include "common.h"
#include "gl_common.h"
#include "gl_config.h"
#include "gl_hints.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
//
// Creates a matching cen64_gl_config from a cen64_gl_hints struct.
//
// On error, CEN64_GL_CONFIG_BAD is returned.
//
cen64_gl_config *cen64_gl_config_create(cen64_gl_display display,
cen64_gl_screen screen, const cen64_gl_hints *hints, int *matching) {
struct cen64_gl_config *config;
PIXELFORMATDESCRIPTOR pfd;
// Do *NOT* use this hDC HANDLE outside this function.
// It is the desktop window's hDC, and we shouldn't mess
// with it. The only thing it's used for is to match a
// PIXELFORMATDESCRIPTOR and expose success/failure.
HDC screen_hdc;
if ((config = malloc(sizeof(*config))) == NULL)
return CEN64_GL_CONFIG_BAD;
if ((screen_hdc = GetDC(screen)) == NULL) {
free(config);
return CEN64_GL_CONFIG_BAD;
}
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
// As of 04/25/15, the MSDN documention (still) just says
// to set this field to 1. So, uh, let's go with that.
pfd.nVersion = 1;
// Pack the structure using the provided hints->
pfd.dwFlags = PFD_SUPPORT_OPENGL;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.iPixelType |= (enum cen64_gl_context_type) hints->context_type;
pfd.dwFlags |= (enum cen64_gl_drawable_type) hints->drawable_type;
if (hints->double_buffered != -1)
pfd.dwFlags |= PFD_DOUBLEBUFFER;
if (hints->stereoscopic != -1)
pfd.dwFlags |= PFD_STEREO;
if (hints->rgb_color_depth != -1)
pfd.cColorBits = hints->rgb_color_depth;
if (hints->alpha_color_depth != -1)
pfd.cAlphaBits = hints->alpha_color_depth;
if (hints->depth_buffer_size != -1)
pfd.cDepthBits = hints->depth_buffer_size;
if (hints->num_aux_buffers != -1)
pfd.cAuxBuffers = hints->num_aux_buffers;
if (hints->stencil_buffer_size != -1)
pfd.cStencilBits = hints->stencil_buffer_size;
if (hints->accum_buffer_red_bits != -1)
pfd.cAccumRedBits = hints->accum_buffer_red_bits;
if (hints->accum_buffer_green_bits != -1)
pfd.cAccumGreenBits = hints->accum_buffer_green_bits;
if (hints->accum_buffer_blue_bits != -1)
pfd.cAccumBlueBits = hints->accum_buffer_blue_bits;
if (hints->accum_buffer_alpha_bits != -1)
pfd.cAccumAlphaBits = hints->accum_buffer_alpha_bits;
config->pixel_format = ChoosePixelFormat(screen_hdc, &pfd);
DescribePixelFormat(screen_hdc, config->pixel_format,
sizeof(config->pfd), &config->pfd);
ReleaseDC(screen, screen_hdc);
*matching = 1;
return config;
}

151
os/winapi/gl_config.h Normal file
View file

@ -0,0 +1,151 @@
//
// os/winapi/gl_config.h: WinAPI/OpenGL framebuffer configuration.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_CONFIG
#define CEN64_OS_WINAPI_GL_CONFIG
#include "gl_common.h"
#include "gl_display.h"
#include "gl_hints.h"
#include "gl_screen.h"
#include <stddef.h>
#include <stdlib.h>
#include <windows.h>
#define CEN64_GL_CONFIG_BAD (NULL)
struct cen64_gl_config {
PIXELFORMATDESCRIPTOR pfd;
int pixel_format;
};
typedef struct cen64_gl_config cen64_gl_config;
//
// Creates a matching cen64_gl_config from a cen64_gl_hints struct.
//
// On error, CEN64_GL_CONFIG_BAD is returned. On success, something
// other than CEN64_GL_CONFIG_BAD is returned, and matching is set
// to indicate the number of matches present in the returned array.
//
cen64_gl_config *cen64_gl_config_create(cen64_gl_display display,
cen64_gl_screen screen, const cen64_gl_hints *hints, int *matching);
//
// Releases resources allocated by cen64_gl_config_create.
//
static inline void cen64_gl_config_destroy(cen64_gl_config *config) {
free(config);
}
//
// Wrappers for querying for features/types.
//
static inline enum cen64_gl_context_type cen64_gl_config_get_context_type(
cen64_gl_display display, cen64_gl_config *config) {
return (enum cen64_gl_context_type) config->pfd.iPixelType;
}
static inline enum cen64_gl_drawable_type cen64_gl_config_get_drawable_type(
cen64_gl_display display, cen64_gl_config *config) {
return (config->pfd.dwFlags & PFD_DRAW_TO_BITMAP)
? CEN64_GL_DRAWABLE_TYPE_BITMAP
: CEN64_GL_DRAWABLE_TYPE_WINDOW;
}
static inline enum cen64_gl_layer_type cen64_gl_config_get_layer_type(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.iLayerType;
}
static inline int cen64_gl_config_is_double_buffered(
cen64_gl_display display, cen64_gl_config *config) {
return (config->pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
}
static inline int cen64_gl_config_is_renderable(
cen64_gl_display display, cen64_gl_config *config) {
return (config->pfd.dwFlags & PFD_SUPPORT_OPENGL) != 0;
}
static inline int cen64_gl_config_is_stereoscopic(
cen64_gl_display display, cen64_gl_config *config) {
return (config->pfd.dwFlags & PFD_STEREO) != 0;
}
//
// Wrappers for querying for color depths.
//
static inline int cen64_gl_config_get_color_depth(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cColorBits;
}
static inline int cen64_gl_config_get_red_color_depth(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cRedBits;
}
static inline int cen64_gl_config_get_green_color_depth(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cGreenBits;
}
static inline int cen64_gl_config_get_blue_color_depth(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cBlueBits;
}
static inline int cen64_gl_config_get_alpha_color_depth(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAlphaBits;
}
//
// Wrappers for querying for buffer sizes, counts.
//
static inline int cen64_gl_config_get_depth_buffer_count(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cDepthBits;
}
static inline int cen64_gl_config_get_num_auxiliary_buffers(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAuxBuffers;
}
static inline int cen64_gl_config_get_stencil_buffer_size(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cStencilBits;
}
//
// Wrappers for querying for accumulation buffer bits.
//
static inline int cen64_gl_config_get_red_accum_buffer_bits(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAccumRedBits;
}
static inline int cen64_gl_config_get_blue_accum_buffer_bits(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAccumBlueBits;
}
static inline int cen64_gl_config_get_green_accum_buffer_bits(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAccumGreenBits;
}
static inline int cen64_gl_config_get_alpha_accum_buffer_bits(
cen64_gl_display display, cen64_gl_config *config) {
return config->pfd.cAccumAlphaBits;
}
#endif

49
os/winapi/gl_context.h Normal file
View file

@ -0,0 +1,49 @@
//
// os/winapi/gl_context.h: WinAPI GL context definitions.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_CONTEXT
#define CEN64_OS_WINAPI_GL_CONTEXT
#include "gl_common.h"
#include "gl_display.h"
#include "gl_screen.h"
#include "gl_window.h"
#include <stddef.h>
#define CEN64_GL_CONTEXT_BAD (NULL)
typedef HGLRC cen64_gl_context;
//
// Creates a cen64_gl_context and binds it to the cen64_gl_window.
//
static inline cen64_gl_context cen64_gl_context_create(cen64_gl_window window) {
cen64_gl_context c;
if ((c = wglCreateContext(window->hdc)) == NULL)
return CEN64_GL_CONTEXT_BAD;
if (wglMakeCurrent(window->hdc, c) != TRUE) {
wglDeleteContext(c);
c = CEN64_GL_CONTEXT_BAD;
}
return c;
}
//
// Unbinds the cen64_gl_context from the window and releases the context.
//
static inline void cen64_gl_context_destroy(
cen64_gl_context context, cen64_gl_window window) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(context);
}
#endif

41
os/winapi/gl_display.h Normal file
View file

@ -0,0 +1,41 @@
//
// os/winapi/gl_display.h: WinAPI display definitions.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_DISPLAY
#define CEN64_OS_WINAPI_GL_DISPLAY
#include "gl_common.h"
#define CEN64_GL_DISPLAY_BAD (-1)
typedef int cen64_gl_display;
//
// Creates a cen64_gl_display (where 'source' selects the display to use).
//
// If source is NULL, it is treated as a don't care.
//
static inline cen64_gl_display cen64_gl_display_create(const char *source) {
return 0; // TODO
}
//
// Releases resources allocated by cen64_gl_display_create.
//
static inline void cen64_gl_display_destroy(cen64_gl_display display) {
}
//
// Returns the number of screens present on a given cen64_gl_display.
//
static int cen64_gl_display_get_num_screens(cen64_gl_display display) {
return 1; // TODO
}
#endif

43
os/winapi/gl_screen.h Normal file
View file

@ -0,0 +1,43 @@
//
// os/winapi/gl_screen.h: WinAPI screen definitions.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_SCREEN
#define CEN64_OS_WINAPI_GL_SCREEN
#include "gl_common.h"
#include <stddef.h>
#include <windows.h>
#define CEN64_GL_SCREEN_BAD (NULL)
typedef HWND cen64_gl_screen;
//
// Creates a cen64_gl_screen object on a given cen64_gl_display.
//
// 'which' specifies which screen on a display to use (from 0 to
// num_screens - 1). If 'which' is less than zero, it is treated as
// a don't care.
//
// On error, CEN64_GL_SCREEN_BAD is returned.
//
static inline cen64_gl_screen cen64_gl_screen_create(
cen64_gl_display display, int which) {
if (which >= 0)
return NULL; // TODO
return GetDesktopWindow();
}
//
// Releases resources allocated by cen64_screen_create.
//
static inline void cen64_gl_screen_destroy(cen64_gl_screen screen) {}
#endif

34
os/winapi/gl_window.c Normal file
View file

@ -0,0 +1,34 @@
//
// os/winapi/gl_window.h: WinAPI/OpenGL window definitions.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#include "gl_common.h"
#include "gl_window.h"
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd,
UINT message, WPARAM w_param, LPARAM l_param) {
cen64_gl_window window;
switch(message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
window = (cen64_gl_window) GetWindowLongPtr(hwnd, GWLP_USERDATA);
break;
default:
return DefWindowProc(hwnd, message, w_param, l_param);
}
return 0;
}

135
os/winapi/gl_window.h Normal file
View file

@ -0,0 +1,135 @@
//
// os/winapi/gl_window.h: WinAPI/OpenGL window definitions.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, Tyler J. Stachecki.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#ifndef CEN64_OS_WINAPI_GL_WINDOW
#define CEN64_OS_WINAPI_GL_WINDOW
#include "gl_common.h"
#include "gl_config.h"
#include "gl_display.h"
#include "gl_screen.h"
#include <stddef.h>
#include <stdlib.h>
#include <windows.h>
#define CEN64_GL_WINDOW_BAD (NULL)
struct cen64_gl_window {
HINSTANCE hinstance;
HWND hwnd;
HDC hdc;
int pixel_format;
};
typedef struct cen64_gl_window *cen64_gl_window;
LRESULT CALLBACK WndProc(HWND hwnd,
UINT message, WPARAM w_param, LPARAM l_param);
//
// Creates a (hidden) cen64_gl_window.
//
static inline cen64_gl_window cen64_gl_window_create(
cen64_gl_display display, cen64_gl_screen screen,
const cen64_gl_config *config, const char *title) {
cen64_gl_window window;
WNDCLASS wc;
DWORD dw_ex_style;
DWORD dw_style;
RECT window_rect;
if ((window = malloc(sizeof(*window))) == NULL)
return CEN64_GL_WINDOW_BAD;
window_rect.left = 0;
window_rect.right = 640;
window_rect.top = 0;
window_rect.bottom = 480;
window->hinstance = GetModuleHandle(NULL);
window->pixel_format = config->pixel_format;
memset(&wc, 0, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = window->hinstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "CEN64";
if (!RegisterClass(&wc)) {
free(window);
return CEN64_GL_WINDOW_BAD;
}
dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dw_style = WS_OVERLAPPEDWINDOW;
AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
if ((window->hwnd = CreateWindowEx(dw_ex_style, "CEN64", title,
dw_style | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0,
window_rect.right - window_rect.left, window_rect.bottom - window_rect.top,
NULL, NULL, window->hinstance, NULL)) == NULL) {
UnregisterClass("CEN64", window->hinstance);
free(window);
return CEN64_GL_WINDOW_BAD;
}
// Store the pointer to the gl_window in the HWND attribute.
// We'll need it later to perform callbacks on resize and such.
// Also grab the window's device context so we can create a GL RC.
SetLastError(0);
SetWindowLongPtr(window->hwnd, GWLP_USERDATA, (uintptr_t) window);
if (GetLastError() || (window->hdc = GetDC(window->hwnd)) == NULL) {
DestroyWindow(window->hwnd);
UnregisterClass("CEN64", window->hinstance);
free(window);
return CEN64_GL_WINDOW_BAD;
}
SetPixelFormat(window->hdc, window->pixel_format, &config->pfd);
return window;
}
//
// Releases resources allocated by cen64_gl_window_create.
//
static inline void cen64_gl_window_destroy(cen64_gl_window window) {
ReleaseDC(window->hwnd, window->hdc);
DestroyWindow(window->hwnd);
UnregisterClass("CEN64", window->hinstance);
free(window);
}
//
// Swaps the front and back buffers of the cen65_gl_window.
//
static inline void cen64_gl_window_swap_buffers(cen64_gl_window window) {
SwapBuffers(window->hdc);
}
//
// Unhides the cen64_gl_window.
//
static inline void cen64_gl_window_unhide(cen64_gl_window window) {
ShowWindow(window->hwnd, SW_SHOW);
}
#endif