From e1115b2a7c74bf7903732e4b7712b2cf6ceda62d Mon Sep 17 00:00:00 2001 From: wayo Date: Tue, 2 Apr 2013 22:04:51 -0600 Subject: [PATCH] Moved gloffscreen files to gl dir, and the gloffscreen_glx.c. Trimmed gloffscreen_common.c a little. Modified Makefile.target and nv2a.c according to the new gloffscreen files location. --- gl/gloffscreen.h | 117 +++++++++++++++ gl/gloffscreen_cgl.c | 132 +++++++++++++++++ gl/gloffscreen_common.c | 295 ++++++++++++++++++++++++++++++++++++++ gl/gloffscreen_wgl.c | 310 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 854 insertions(+) create mode 100644 gl/gloffscreen.h create mode 100644 gl/gloffscreen_cgl.c create mode 100644 gl/gloffscreen_common.c create mode 100644 gl/gloffscreen_wgl.c diff --git a/gl/gloffscreen.h b/gl/gloffscreen.h new file mode 100644 index 0000000000..5476ba83a7 --- /dev/null +++ b/gl/gloffscreen.h @@ -0,0 +1,117 @@ +/* + * Offscreen OpenGL abstraction layer + * + * Copyright (c) 2010 Intel + * Written by: + * Gordon Williams + * Ian Molton + * Wayo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GLOFFSCREEN_H_ +#define GLOFFSCREEN_H_ + +#ifdef __APPLE__ +#include +#else +#include +#endif + +/* Used to hold data for the OpenGL context */ +struct _GloContext; +typedef struct _GloContext GloContext; + +/* Format flags for glo_surface_create */ +#define GLO_FF_ALPHA_MASK (0x0001) +#define GLO_FF_NOALPHA (0x0000) +#define GLO_FF_ALPHA (0x0001) + +#define GLO_FF_BITS_MASK (0x00F0) +#define GLO_FF_BITS_16 (0x0020) +#define GLO_FF_BITS_24 (0x0030) +#define GLO_FF_BITS_32 (0x0040) + +#define GLO_FF_DEPTH_MASK (0x0F00) +#define GLO_FF_DEPTH_16 (0x0100) +#define GLO_FF_DEPTH_24 (0x0200) +#define GLO_FF_DEPTH_32 (0x0300) + +#define GLO_FF_STENCIL_MASK (0xF000) +#define GLO_FF_STENCIL_8 (0x1000) + +/* The only currently supported format */ +#define GLO_FF_DEFAULT (GLO_FF_BITS_24|GLO_FF_DEPTH_24) + +/* Has gloffscreen been previously initialised? */ +extern int glo_initialised(void); + +/* Initialise gloffscreen */ +extern void glo_init(void); + +/* Change current context */ +extern void glo_set_current(GloContext *context); + +/* Uninitialise gloffscreen */ +extern void glo_kill(void); + +/* Check GL Extensions */ +extern GLboolean glo_check_extension( + const GLubyte *extName, const GLubyte *extString); + +/* Create an OpenGL context for a certain + * pixel format. formatflags are from the + * GLO_ constants */ +extern GloContext *glo_context_create(int formatFlags); + +/* Destroy a previouslu created OpenGL context */ +extern void glo_context_destroy(GloContext *context); + +/* Functions to decode the format flags */ +extern int glo_flags_get_depth_bits(int formatFlags); +extern int glo_flags_get_stencil_bits(int formatFlags); +extern void glo_flags_get_rgba_bits(int formatFlags, int *rgba); +extern int glo_flags_get_bytes_per_pixel(int formatFlags); +extern void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType); +/* Score how close the given format flags match. 0=great, >0 not so great */ +extern int glo_flags_score(int formatFlagsExpected, int formatFlagsReal); + +/* Create a set of format flags from a null-terminated list + * of GLX fbConfig flags. If assumeBooleans is set, items such + * as GLX_RGBA/GLX_DOUBLEBUFFER are treated as booleans, not key-value pairs + * (glXChooseVisual treats them as booleans, glXChooseFBConfig as key-value pairs) + */ +extern int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans); +/* Use in place of glxGetConfig - returns information from flags based on a GLX enum */ +extern int glo_get_glx_from_flags(int formatFlags, int glxEnum); + + +/* In terms of speed, glReadPixels actually seems the best we can do. + * * On Windows PFB_DRAW_TO_BITMAP is software-only. + * * http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt would be + * useful if we didn't want the data right away (as we could avoid flushing the + * pipeline). + * * The internal data format seems to be GL_BGRA - and this is indeed faster. + * * Apple suggests using GL_UNSIGNED_INT_8_8_8_8_REV instead of + * GL_UNSIGNED_BYTE, but there don't appear to be any speed increase from + * doing this on Windows at least. + */ + +#endif /* GLOFFSCREEN_H_ */ diff --git a/gl/gloffscreen_cgl.c b/gl/gloffscreen_cgl.c new file mode 100644 index 0000000000..6f4cc93a4c --- /dev/null +++ b/gl/gloffscreen_cgl.c @@ -0,0 +1,132 @@ +/* + * Offscreen OpenGL abstraction layer - CGL (Apple) specific + * + * Copyright (c) 2010 Intel + * Written by: + * Wayo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "gloffscreen.h" + +/* In Windows, you must create a window *before* you can create a pbuffer or + * get a context. So we create a hidden Window on startup(see glo_init/GloMain). + * + * Also, you can't share contexts that have different pixel formats, so we can't + * just create a new context from the window. We must create a whole new PBuffer + * just for a context :( + */ + +struct GloMain { + int init; + /* Not needed for CGL? */ +}; + +struct GloMain glo; +int glo_inited = 0; + +struct _GloContext { + CGLContextObj cglContext; +}; + +int glo_initialised(void) { + return glo_inited; +} + +/* Initialise gloffscreen */ +void glo_init(void) { + /* TODO: CGL Implementation. + * Initialization needed for CGL? */ + + if (glo_inited) { + printf( "gloffscreen already inited\n" ); + exit( EXIT_FAILURE ); + } + + glo_inited = 1; +} + +/* Uninitialise gloffscreen */ +void glo_kill(void) { + glo_inited = 0; +} + +/* Create an OpenGL context for a certain pixel format. formatflags are from + * the GLO_ constants */ +GloContext *glo_context_create(int formatFlags) +{ + GloContext *context; + + context = (GloContext *)malloc(sizeof(GloContext)); + memset(context, 0, sizeof(GloContext)); + + /* pixel format attributes */ + CGLPixelFormatAttribute attributes[] = { + kCGLPFAAccelerated, + (CGLPixelFormatAttribute)0 + }; + + CGLPixelFormatObj pix; + GLint num; + CGLChoosePixelFormat(attributes, &pix, &num); + CGLCreateContext(pix, NULL, &context->cglContext); + CGLDestroyPixelFormat(pix); + + if (!glo_inited) + glo_init(); + + glo_set_current(context); + + return context; +} + +/* Check if an extension is available. */ +GLboolean glo_check_extension(const GLubyte *extName, + const GLubyte *extString) +{ + return gluCheckExtension(extName, extString); +} + +/* Set current context */ +void glo_set_current(GloContext *context) +{ + if (context == NULL) { + CGLSetCurrentContext(NULL); + } else { + CGLSetCurrentContext(context->cglContext); + } +} + +/* Destroy a previously created OpenGL context */ +void glo_context_destroy(GloContext *context) +{ + if (!context) return; + glo_set_current(NULL); + CGLDestroyContext(context->cglContext); +} diff --git a/gl/gloffscreen_common.c b/gl/gloffscreen_common.c new file mode 100644 index 0000000000..9a3e289210 --- /dev/null +++ b/gl/gloffscreen_common.c @@ -0,0 +1,295 @@ +/* + * Offscreen OpenGL abstraction layer - Common utilities + * + * Copyright (c) 2010 Intel + * Written by: + * Gordon Williams + * Ian Molton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "gloffscreen.h" + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include +#include +#include + +// --------------------------------------------------- +// Copied from glx.h as we need them in windows too +/* + * Tokens for glXChooseVisual and glXGetConfig: + */ +#define GLX_USE_GL 1 +#define GLX_BUFFER_SIZE 2 +#define GLX_LEVEL 3 +#define GLX_RGBA 4 +#define GLX_DOUBLEBUFFER 5 +#define GLX_STEREO 6 +#define GLX_AUX_BUFFERS 7 +#define GLX_RED_SIZE 8 +#define GLX_GREEN_SIZE 9 +#define GLX_BLUE_SIZE 10 +#define GLX_ALPHA_SIZE 11 +#define GLX_DEPTH_SIZE 12 +#define GLX_STENCIL_SIZE 13 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_ALPHA_SIZE 17 +// --------------------------------------------------- + +extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, + int bpp, int width, int height, void *data); + +// --------------------------------------------------- + +int glo_flags_get_depth_bits(int formatFlags) { + switch ( formatFlags & GLO_FF_DEPTH_MASK ) { + case GLO_FF_DEPTH_16: return 16; + case GLO_FF_DEPTH_24: return 24; + case GLO_FF_DEPTH_32: return 32; + default: return 0; + } +} + +int glo_flags_get_stencil_bits(int formatFlags) { + switch ( formatFlags & GLO_FF_STENCIL_MASK ) { + case GLO_FF_STENCIL_8: return 8; + default: return 0; + } +} + +void glo_flags_get_rgba_bits(int formatFlags, int *rgba) { + int alpha = (formatFlags & GLO_FF_ALPHA) != 0; + switch ( formatFlags & GLO_FF_BITS_MASK ) { + case GLO_FF_BITS_16: + rgba[0] = alpha ? 4 : 5; + rgba[1] = alpha ? 4 : 6; + rgba[2] = alpha ? 4 : 5; + rgba[3] = alpha ? 4 : 0; + break; + case GLO_FF_BITS_24: + // ignore alpha + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 0; + break; + case GLO_FF_BITS_32: + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 8; + break; + default: + rgba[0] = 8; + rgba[1] = 8; + rgba[2] = 8; + rgba[3] = 0; + break; + } +} + +int glo_flags_get_bytes_per_pixel(int formatFlags) { + switch ( formatFlags & GLO_FF_BITS_MASK ) { + case GLO_FF_BITS_16: return 2; + case GLO_FF_BITS_24: return 3; + case GLO_FF_BITS_32: return 4; + default: return 3; + } +} + +void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType) { + GLenum gFormat, gType; + + if (formatFlags & GLO_FF_ALPHA) { + switch ( formatFlags & GLO_FF_BITS_MASK ) { + case GLO_FF_BITS_16: + gFormat = GL_RGBA; + gType = GL_UNSIGNED_SHORT_4_4_4_4; + break; + case GLO_FF_BITS_24: + case GLO_FF_BITS_32: + default: + gFormat = GL_BGRA; + gType = GL_UNSIGNED_BYTE; + break; + } + } else { + switch ( formatFlags & GLO_FF_BITS_MASK ) { + case GLO_FF_BITS_16: + gFormat = GL_RGB; + gType = GL_UNSIGNED_SHORT_5_6_5; + break; + case GLO_FF_BITS_24: + case GLO_FF_BITS_32: + default: + gFormat = GL_BGR; + gType = GL_UNSIGNED_BYTE; + break; + } + } + + if (glFormat) *glFormat = gFormat; + if (glType) *glType = gType; +} + +int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) { + if (formatFlagsExpected == formatFlagsReal) return 0; + int score = 1; + // we wanted alpha, but we didn't get it + if ((formatFlagsExpected&GLO_FF_ALPHA_MASK) < + (formatFlagsReal&GLO_FF_ALPHA_MASK)) + score++; + // less bits than we expected + if ((formatFlagsExpected&GLO_FF_BITS_MASK) < + !(formatFlagsReal&GLO_FF_BITS_MASK)) + score++; + // less depth bits than we expected + if ((formatFlagsExpected&GLO_FF_DEPTH_MASK) < + !(formatFlagsReal&GLO_FF_DEPTH_MASK)) + score++; + // less stencil bits than we expected + if ((formatFlagsExpected&GLO_FF_STENCIL_MASK) < + !(formatFlagsReal&GLO_FF_STENCIL_MASK)) + score++; + return score; +} + +int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans) { + int bufferSize = 0; + int depthSize = 0; + int stencilSize = 0; + int rgbaSize[] = {0,0,0,0}; + int flags = 0; + + while (*fbConfig) { + int isSingle = 0; + switch (*fbConfig) { + case GLX_USE_GL: + isSingle = 1; + break; + case GLX_BUFFER_SIZE: + bufferSize = fbConfig[1]; + break; + case GLX_LEVEL: + break; + case GLX_RGBA: + flags |= GLO_FF_ALPHA; + break; + case GLX_DOUBLEBUFFER: + isSingle = 1; + break; + case GLX_STEREO: + isSingle = 1; + break; + case GLX_AUX_BUFFERS: + break; + case GLX_RED_SIZE: + rgbaSize[0] = fbConfig[1]; + break; + case GLX_GREEN_SIZE: + rgbaSize[1] = fbConfig[1]; + break; + case GLX_BLUE_SIZE: + rgbaSize[2] = fbConfig[1]; + break; + case GLX_ALPHA_SIZE: + rgbaSize[3] = fbConfig[1]; + break; + case GLX_DEPTH_SIZE: + depthSize = fbConfig[1]; + break; + case GLX_STENCIL_SIZE: + stencilSize = fbConfig[1]; + break; + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + break; + } + // go to next + if (isSingle && assumeBooleans) + fbConfig++; + else + fbConfig+=2; + } + if (rgbaSize[3]) + flags |= GLO_FF_ALPHA; + // ensure we have room for *some* alpha + if ((flags & GLO_FF_ALPHA) && (rgbaSize[3]==0)) + rgbaSize[3] = 1; + // Buffer size flag + if (bufferSize==0) + bufferSize = rgbaSize[0]+rgbaSize[1]+rgbaSize[2]+rgbaSize[3]; + if (bufferSize==0) + bufferSize = (flags & GLO_FF_ALPHA) ? 32 : 24; + if (bufferSize<=16) + flags |= GLO_FF_BITS_16; + else if (bufferSize<=24) + flags |= GLO_FF_BITS_24; + else flags |= GLO_FF_BITS_32; + // Depth + if (depthSize<=16) + flags |= GLO_FF_DEPTH_16; + else if (depthSize<=24) + flags |= GLO_FF_DEPTH_24; + else flags |= GLO_FF_DEPTH_32; + // Stencil + if (stencilSize>0) + flags |= GLO_FF_STENCIL_8; + return flags; +} + +int glo_get_glx_from_flags(int formatFlags, int glxEnum) { + int rgba[4]; + glo_flags_get_rgba_bits(formatFlags, rgba); + + switch (glxEnum) { + case GLX_USE_GL: return 1; + case GLX_BUFFER_SIZE: return glo_flags_get_bytes_per_pixel(formatFlags)*8; + case GLX_LEVEL: return 0; + case GLX_RGBA: return formatFlags & GLO_FF_ALPHA; + case GLX_DOUBLEBUFFER: return 1; + case GLX_STEREO: return 0; + case GLX_AUX_BUFFERS: return 0; + case GLX_RED_SIZE: return rgba[0]; + case GLX_GREEN_SIZE: return rgba[1]; + case GLX_BLUE_SIZE: return rgba[2]; + case GLX_ALPHA_SIZE: return rgba[3]; + case GLX_DEPTH_SIZE: return glo_flags_get_depth_bits(formatFlags); + case GLX_STENCIL_SIZE: return glo_flags_get_stencil_bits(formatFlags); + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + return 0; + } + return 0; +} + diff --git a/gl/gloffscreen_wgl.c b/gl/gloffscreen_wgl.c new file mode 100644 index 0000000000..a0f89389e5 --- /dev/null +++ b/gl/gloffscreen_wgl.c @@ -0,0 +1,310 @@ +/* + * Offscreen OpenGL abstraction layer - WGL (windows) specific + * + * Copyright (c) 2010 Intel + * Written by: + * Gordon Williams + * Ian Molton + * Wayo + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "gloffscreen.h" + +/* In Windows, you must create a window *before* you can create a pbuffer or + * get a context. So we create a hidden Window on startup(see glo_init/GloMain). + * + * Also, you can't share contexts that have different pixel formats, so we can't + * just create a new context from the window. We must create a whole new PBuffer + * just for a context :( + */ + +struct GloMain { + HINSTANCE hInstance; + HDC hDC; + HWND hWnd; /* Our hidden window */ + HGLRC hContext; +}; + +struct GloMain glo; +int glo_inited = 0; + +struct _GloContext { + int formatFlags; + /* Pixel format returned by wglChoosePixelFormat */ + int wglPixelFormat; + /* We need a pbuffer to make a context of the right pixelformat :( */ + HPBUFFERARB hPBuffer; + HDC hDC; + HGLRC hContext; +}; + + +#define GLO_WINDOW_CLASS "QEmuGLClass" +#define DEFAULT_DEPTH_BUFFER (16) + +PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; +PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB; +PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB; +PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB; +PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB; + +int glo_initialised(void) { + return glo_inited; +} + +/* Initialise gloffscreen */ +void glo_init(void) { + WNDCLASSEX wcx; + PIXELFORMATDESCRIPTOR pfd; + + if (glo_inited) { + printf("gloffscreen already inited\n"); + exit(EXIT_FAILURE); + } + + /* Grab An Instance For Our Window */ + glo.hInstance = GetModuleHandle(NULL); + + wcx.cbSize = sizeof(wcx); + wcx.style = 0; + wcx.lpfnWndProc = DefWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = glo.hInstance; + wcx.hIcon = NULL; + wcx.hCursor = NULL; + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = GLO_WINDOW_CLASS; + wcx.hIconSm = NULL; + RegisterClassEx(&wcx); + glo.hWnd = CreateWindow( + GLO_WINDOW_CLASS, + "QEmuGL", + 0,0,0,0,0, + (HWND)NULL, (HMENU)NULL, + glo.hInstance, + (LPVOID) NULL); + + if (!glo.hWnd) { + printf("Unable to create window\n"); + exit(EXIT_FAILURE); + } + glo.hDC = GetDC(glo.hWnd); + + memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.iLayerType = PFD_MAIN_PLANE; + unsigned int pixelFormat = ChoosePixelFormat(glo.hDC, &pfd); + DescribePixelFormat(glo.hDC, + pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + if (!SetPixelFormat(glo.hDC, pixelFormat, &pfd)) + return; + + glo.hContext = wglCreateContext(glo.hDC); + if (glo.hContext == NULL) { + printf("Unable to create GL context\n"); + exit(EXIT_FAILURE); + } + wglMakeCurrent(glo.hDC, glo.hContext); + + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatARB"); + wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC) + wglGetProcAddress("wglGetPbufferDCARB"); + wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC) + wglGetProcAddress("wglReleasePbufferDCARB"); + wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC) + wglGetProcAddress("wglCreatePbufferARB"); + wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC) + wglGetProcAddress("wglDestroyPbufferARB"); + + if (!wglChoosePixelFormatARB || + !wglGetPbufferDCARB || + !wglReleasePbufferDCARB || + !wglCreatePbufferARB || + !wglDestroyPbufferARB) { + printf("Unable to load the required WGL extensions\n"); + exit(EXIT_FAILURE); + } + + /* Initialize glew */ + if (GLEW_OK != glewInit()) { + /* GLEW failed! */ + printf("Glew init failed."); + exit(1); + } + glo_inited = 1; +} + +/* Uninitialise gloffscreen */ +void glo_kill(void) { + if (glo.hContext) { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(glo.hContext); + glo.hContext = NULL; + } + if (glo.hDC) { + ReleaseDC(glo.hWnd, glo.hDC); + glo.hDC = NULL; + } + if (glo.hWnd) { + DestroyWindow(glo.hWnd); + glo.hWnd = NULL; + } + UnregisterClass(GLO_WINDOW_CLASS, glo.hInstance); +} + +/* Create an OpenGL context for a certain pixel format. formatflags are from + * the GLO_ constants */ +GloContext *glo_context_create(int formatFlags) { + GloContext *context; + /* pixel format attributes */ + int pf_attri[] = { + WGL_SUPPORT_OPENGL_ARB, TRUE, + WGL_DRAW_TO_PBUFFER_ARB, TRUE, + WGL_RED_BITS_ARB, 8, + WGL_GREEN_BITS_ARB, 8, + WGL_BLUE_BITS_ARB, 8, + WGL_ALPHA_BITS_ARB, 8, + WGL_DEPTH_BITS_ARB, 0, + WGL_STENCIL_BITS_ARB, 0, + WGL_DOUBLE_BUFFER_ARB, FALSE, + 0 + }; + float pf_attrf[] = {0, 0}; + unsigned int numReturned = 0; + int pb_attr[] = { 0 }; + int rgbaBits[4]; + + if (!glo_inited) + glo_init(); + + context = (GloContext *)malloc(sizeof(GloContext)); + memset(context, 0, sizeof(GloContext)); + context->formatFlags = formatFlags; + + /* set up the surface format from the flags we were given */ + glo_flags_get_rgba_bits(context->formatFlags, rgbaBits); + pf_attri[5] = rgbaBits[0]; + pf_attri[7] = rgbaBits[1]; + pf_attri[9] = rgbaBits[2]; + pf_attri[11] = rgbaBits[3]; + pf_attri[13] = glo_flags_get_depth_bits(context->formatFlags); + pf_attri[15] = glo_flags_get_stencil_bits(context->formatFlags); + + /* find out what pixel format to use */ + wglChoosePixelFormatARB(glo.hDC, pf_attri, pf_attrf, 1, + &context->wglPixelFormat, &numReturned); + if (numReturned == 0) { + printf( "No matching configs found.\n" ); + exit(EXIT_FAILURE); + } + + /* We create a tiny pbuffer - just so we can make a context of + * the right pixel format */ + context->hPBuffer = wglCreatePbufferARB(glo.hDC, context->wglPixelFormat, + 16, 16, pb_attr); + if (!context->hPBuffer) { + printf("Couldn't create the PBuffer\n"); + exit(EXIT_FAILURE); + } + context->hDC = wglGetPbufferDCARB(context->hPBuffer); + if (!context->hDC) { + printf("Couldn't create the DC\n"); + exit(EXIT_FAILURE); + } + context->hContext = wglCreateContext(context->hDC); + if (context->hContext == NULL) { + printf("Unable to create GL context\n"); + exit(EXIT_FAILURE); + } + glo_set_current(context); + return context; +} + +/* Set current context */ +void glo_set_current(GloContext *context) { + + if (context == NULL) { + wglMakeCurrent(NULL, NULL); + } else { + wglMakeCurrent(context->hDC, context->hContext); + } +} + +/* Destroy a previously created OpenGL context */ +void glo_context_destroy(GloContext *context) +{ + if (!context) return; + + wglMakeCurrent(NULL, NULL); + if (context->hPBuffer != NULL) { + wglReleasePbufferDCARB(context->hPBuffer, context->hDC); + wglDestroyPbufferARB(context->hPBuffer); + } + if (context->hDC != NULL) { + ReleaseDC(glo.hWnd, context->hDC); + } + if (context->hContext) { + wglDeleteContext(context->hContext); + } + free(context); +} + + +/* Check extension implementation for Windows. + * The Glu 1.2 framework in Windows doesn't include them... */ +GLboolean glo_check_extension(const GLubyte *extName, + const GLubyte *extString) +{ + char *p = (char *) glGetString(GL_EXTENSIONS); + char *end; + if (p == NULL) { + return GL_FALSE; + } + end = p + strlen(p); + + while (p < end) { + int n = strcspn(p, " "); + if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) { + return GL_TRUE; + } + p += (n + 1); + } + return GL_FALSE; +}