2 * Copyright © 2014 Jon Turney
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 #include "windowsgl.h"
25 #include "windowsgl_internal.h"
35 static struct _glapi_table
*windows_api
= NULL
;
38 windows_get_dl_handle(void)
40 static void *dl_handle
= NULL
;
43 dl_handle
= dlopen("cygnativeGLthunk.dll", RTLD_NOW
);
49 windows_glapi_create_table(void)
54 windows_api
= _glapi_create_table_from_handle(windows_get_dl_handle(), "gl");
58 static void windows_glapi_set_dispatch(void)
60 windows_glapi_create_table();
61 _glapi_set_dispatch(windows_api
);
65 windows_create_context(int pxfi
, windowsContext
*shared
)
69 gc
= calloc(1, sizeof *gc
);
73 // create a temporary, invisible window
74 #define GL_TEMP_WINDOW_CLASS "glTempWndClass"
76 static wATOM glTempWndClass
= 0;
78 if (glTempWndClass
== 0) {
80 wc
.cbSize
= sizeof(WNDCLASSEX
);
81 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
82 wc
.lpfnWndProc
= DefWindowProc
;
85 wc
.hInstance
= GetModuleHandle(NULL
);
88 wc
.hbrBackground
= (HBRUSH
) GetStockObject(WHITE_BRUSH
);
89 wc
.lpszMenuName
= NULL
;
90 wc
.lpszClassName
= GL_TEMP_WINDOW_CLASS
;
96 HWND hwnd
= CreateWindowExA(0,
101 NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
102 HDC hdc
= GetDC(hwnd
);
104 // We must set the windows pixel format before we can create a WGL context
106 SetPixelFormat(hdc
, gc
->pxfi
, NULL
);
108 gc
->ctx
= wglCreateContext(hdc
);
110 if (shared
&& gc
->ctx
)
111 wglShareLists(shared
->ctx
, gc
->ctx
);
113 ReleaseDC(hwnd
, hdc
);
126 windows_create_context_attribs(int pxfi
, windowsContext
*shared
, const int *attribList
)
130 gc
= calloc(1, sizeof *gc
);
134 // create a temporary, invisible window
135 #define GL_TEMP_WINDOW_CLASS "glTempWndClass"
137 static wATOM glTempWndClass
= 0;
139 if (glTempWndClass
== 0) {
141 wc
.cbSize
= sizeof(WNDCLASSEX
);
142 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
143 wc
.lpfnWndProc
= DefWindowProc
;
146 wc
.hInstance
= GetModuleHandle(NULL
);
149 wc
.hbrBackground
= (HBRUSH
) GetStockObject(WHITE_BRUSH
);
150 wc
.lpszMenuName
= NULL
;
151 wc
.lpszClassName
= GL_TEMP_WINDOW_CLASS
;
153 RegisterClassEx(&wc
);
157 HWND hwnd
= CreateWindowExA(0,
158 GL_TEMP_WINDOW_CLASS
,
162 NULL
, NULL
, GetModuleHandle(NULL
), NULL
);
163 HDC hdc
= GetDC(hwnd
);
164 HGLRC shareContext
= NULL
;
166 shareContext
= shared
->ctx
;
168 // We must set the windows pixel format before we can create a WGL context
170 SetPixelFormat(hdc
, gc
->pxfi
, NULL
);
172 gc
->ctx
= wglCreateContextAttribsARB(hdc
, shareContext
, attribList
);
174 ReleaseDC(hwnd
, hdc
);
187 windows_destroy_context(windowsContext
*context
)
189 wglDeleteContext(context
->ctx
);
194 int windows_bind_context(windowsContext
*context
, windowsDrawable
*draw
, windowsDrawable
*read
)
196 HDC drawDc
= draw
->callbacks
->getdc(draw
);
200 SetPixelFormat(drawDc
, context
->pxfi
, NULL
);
201 draw
->pxfi
= context
->pxfi
;
204 if ((read
!= NULL
) && (read
!= draw
))
207 If there is a separate read drawable, create a separate read DC, and
208 use the wglMakeContextCurrent extension to make the context current
209 drawing to one DC and reading from the other
211 Should only occur when WGL_ARB_make_current_read extension is present
213 HDC readDc
= read
->callbacks
->getdc(read
);
215 BOOL ret
= wglMakeContextCurrentARB(drawDc
, readDc
, context
->ctx
);
217 read
->callbacks
->releasedc(read
, readDc
);
220 printf("wglMakeContextCurrentARB error: %08x\n", (int)GetLastError());
226 /* Otherwise, just use wglMakeCurrent */
227 BOOL ret
= wglMakeCurrent(drawDc
, context
->ctx
);
229 printf("wglMakeCurrent error: %08x\n", (int)GetLastError());
234 draw
->callbacks
->releasedc(draw
, drawDc
);
236 windows_glapi_set_dispatch();
241 void windows_unbind_context(windowsContext
* context
)
243 wglMakeCurrent(NULL
, NULL
);
251 windows_swap_buffers(windowsDrawable
*draw
)
253 HDC drawDc
= GetDC(draw
->hWnd
);
255 ReleaseDC(draw
->hWnd
, drawDc
);
259 typedef void (__stdcall
* PFNGLADDSWAPHINTRECTWIN
) (GLint x
, GLint y
,
264 glAddSwapHintRectWIN(GLint x
, GLint y
, GLsizei width
,
267 PFNGLADDSWAPHINTRECTWIN proc
= (PFNGLADDSWAPHINTRECTWIN
)wglGetProcAddress("glAddSwapHintRectWIN");
269 proc(x
, y
, width
, height
);
273 windows_copy_subbuffer(windowsDrawable
*draw
,
274 int x
, int y
, int width
, int height
)
276 glAddSwapHintRectWIN(x
, y
, width
, height
);
277 windows_swap_buffers(draw
);
281 * Helper function for calling a test function on an initial context
284 windows_call_with_context(void (*proc
)(HDC
, void *), void *args
)
286 // create window class
287 #define WIN_GL_TEST_WINDOW_CLASS "GLTest"
289 static wATOM glTestWndClass
= 0;
291 if (glTestWndClass
== 0) {
294 wc
.cbSize
= sizeof(WNDCLASSEX
);
295 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
296 wc
.lpfnWndProc
= DefWindowProc
;
299 wc
.hInstance
= GetModuleHandle(NULL
);
302 wc
.hbrBackground
= (HBRUSH
) GetStockObject(WHITE_BRUSH
);
303 wc
.lpszMenuName
= NULL
;
304 wc
.lpszClassName
= WIN_GL_TEST_WINDOW_CLASS
;
306 glTestWndClass
= RegisterClassEx(&wc
);
310 // create an invisible window for a scratch DC
311 HWND hwnd
= CreateWindowExA(0,
312 WIN_GL_TEST_WINDOW_CLASS
,
313 "GL Renderer Capabilities Test Window",
314 0, 0, 0, 0, 0, NULL
, NULL
, GetModuleHandle(NULL
),
317 HDC hdc
= GetDC(hwnd
);
319 // we must set a pixel format before we can create a context, just use the first one...
320 SetPixelFormat(hdc
, 1, NULL
);
321 HGLRC hglrc
= wglCreateContext(hdc
);
322 wglMakeCurrent(hdc
, hglrc
);
324 // call the test function
328 wglMakeCurrent(NULL
, NULL
);
329 wglDeleteContext(hglrc
);
330 ReleaseDC(hwnd
, hdc
);
336 windows_check_render_test(HDC hdc
, void *args
)
338 int *result
= (int *)args
;
340 /* Rather than play linkage games using stdcall to ensure we get
341 glGetString from opengl32.dll here, use dlsym */
342 void *dlhandle
= windows_get_dl_handle();
343 const char *(*proc
)(int) = dlsym(dlhandle
, "glGetString");
344 const char *gl_renderer
= (const char *)proc(GL_RENDERER
);
346 if ((!gl_renderer
) || (strcasecmp(gl_renderer
, "GDI Generic") == 0))
353 windows_check_renderer(void)
356 windows_call_with_context(windows_check_render_test
, &result
);
362 char *wgl_extensions
;
363 } windows_extensions_result
;
366 windows_extensions_test(HDC hdc
, void *args
)
368 windows_extensions_result
*r
= (windows_extensions_result
*)args
;
370 void *dlhandle
= windows_get_dl_handle();
371 const char *(*proc
)(int) = dlsym(dlhandle
, "glGetString");
373 r
->gl_extensions
= strdup(proc(GL_EXTENSIONS
));
375 wglResolveExtensionProcs();
376 r
->wgl_extensions
= strdup(wglGetExtensionsStringARB(hdc
));
380 windows_extensions(char **gl_extensions
, char **wgl_extensions
)
382 windows_extensions_result result
;
385 *wgl_extensions
= "";
387 windows_call_with_context(windows_extensions_test
, &result
);
389 *gl_extensions
= result
.gl_extensions
;
390 *wgl_extensions
= result
.wgl_extensions
;
393 void windows_setTexBuffer(windowsContext
*context
, int textureTarget
,
394 int textureFormat
, windowsDrawable
*drawable
)
396 // not yet implemented
399 void windows_releaseTexBuffer(windowsContext
*context
, int textureTarget
,
400 windowsDrawable
*drawable
)
402 // not yet implemented