xref: /aosp_15_r20/external/mesa3d/src/glx/windows/windowsgl.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014 Jon Turney
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "windowsgl.h"
25*61046927SAndroid Build Coastguard Worker #include "windowsgl_internal.h"
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "glapi.h"
28*61046927SAndroid Build Coastguard Worker #include "wgl.h"
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include <dlfcn.h>
31*61046927SAndroid Build Coastguard Worker #include <assert.h>
32*61046927SAndroid Build Coastguard Worker #include <stdio.h>
33*61046927SAndroid Build Coastguard Worker #include <strings.h>
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker static struct _glapi_table *windows_api = NULL;
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker static void *
windows_get_dl_handle(void)38*61046927SAndroid Build Coastguard Worker windows_get_dl_handle(void)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    static void *dl_handle = NULL;
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker    if (!dl_handle)
43*61046927SAndroid Build Coastguard Worker       dl_handle = dlopen("cygnativeGLthunk.dll", RTLD_NOW);
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    return dl_handle;
46*61046927SAndroid Build Coastguard Worker }
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker static void
windows_glapi_create_table(void)49*61046927SAndroid Build Coastguard Worker windows_glapi_create_table(void)
50*61046927SAndroid Build Coastguard Worker {
51*61046927SAndroid Build Coastguard Worker    if (windows_api)
52*61046927SAndroid Build Coastguard Worker       return;
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker    windows_api = _glapi_create_table_from_handle(windows_get_dl_handle(), "gl");
55*61046927SAndroid Build Coastguard Worker    assert(windows_api);
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker 
windows_glapi_set_dispatch(void)58*61046927SAndroid Build Coastguard Worker static void windows_glapi_set_dispatch(void)
59*61046927SAndroid Build Coastguard Worker {
60*61046927SAndroid Build Coastguard Worker    windows_glapi_create_table();
61*61046927SAndroid Build Coastguard Worker    _glapi_set_dispatch(windows_api);
62*61046927SAndroid Build Coastguard Worker }
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker windowsContext *
windows_create_context(int pxfi,windowsContext * shared)65*61046927SAndroid Build Coastguard Worker windows_create_context(int pxfi, windowsContext *shared)
66*61046927SAndroid Build Coastguard Worker {
67*61046927SAndroid Build Coastguard Worker    windowsContext *gc;
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    gc = calloc(1, sizeof *gc);
70*61046927SAndroid Build Coastguard Worker    if (gc == NULL)
71*61046927SAndroid Build Coastguard Worker       return NULL;
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    // create a temporary, invisible window
74*61046927SAndroid Build Coastguard Worker #define GL_TEMP_WINDOW_CLASS "glTempWndClass"
75*61046927SAndroid Build Coastguard Worker    {
76*61046927SAndroid Build Coastguard Worker       static wATOM glTempWndClass = 0;
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker       if (glTempWndClass == 0) {
79*61046927SAndroid Build Coastguard Worker          WNDCLASSEX wc;
80*61046927SAndroid Build Coastguard Worker          wc.cbSize = sizeof(WNDCLASSEX);
81*61046927SAndroid Build Coastguard Worker          wc.style = CS_HREDRAW | CS_VREDRAW;
82*61046927SAndroid Build Coastguard Worker          wc.lpfnWndProc = DefWindowProc;
83*61046927SAndroid Build Coastguard Worker          wc.cbClsExtra = 0;
84*61046927SAndroid Build Coastguard Worker          wc.cbWndExtra = 0;
85*61046927SAndroid Build Coastguard Worker          wc.hInstance = GetModuleHandle(NULL);
86*61046927SAndroid Build Coastguard Worker          wc.hIcon = 0;
87*61046927SAndroid Build Coastguard Worker          wc.hCursor = 0;
88*61046927SAndroid Build Coastguard Worker          wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
89*61046927SAndroid Build Coastguard Worker          wc.lpszMenuName = NULL;
90*61046927SAndroid Build Coastguard Worker          wc.lpszClassName = GL_TEMP_WINDOW_CLASS;
91*61046927SAndroid Build Coastguard Worker          wc.hIconSm = 0;
92*61046927SAndroid Build Coastguard Worker          RegisterClassEx(&wc);
93*61046927SAndroid Build Coastguard Worker       }
94*61046927SAndroid Build Coastguard Worker    }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker    HWND hwnd = CreateWindowExA(0,
97*61046927SAndroid Build Coastguard Worker                                GL_TEMP_WINDOW_CLASS,
98*61046927SAndroid Build Coastguard Worker                                "glWindow",
99*61046927SAndroid Build Coastguard Worker                                0,
100*61046927SAndroid Build Coastguard Worker                                0, 0, 0, 0,
101*61046927SAndroid Build Coastguard Worker                                NULL, NULL, GetModuleHandle(NULL), NULL);
102*61046927SAndroid Build Coastguard Worker    HDC hdc = GetDC(hwnd);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    // We must set the windows pixel format before we can create a WGL context
105*61046927SAndroid Build Coastguard Worker    gc->pxfi = pxfi;
106*61046927SAndroid Build Coastguard Worker    SetPixelFormat(hdc, gc->pxfi, NULL);
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker    gc->ctx = wglCreateContext(hdc);
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    if (shared && gc->ctx)
111*61046927SAndroid Build Coastguard Worker       wglShareLists(shared->ctx, gc->ctx);
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker    ReleaseDC(hwnd, hdc);
114*61046927SAndroid Build Coastguard Worker    DestroyWindow(hwnd);
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    if (!gc->ctx)
117*61046927SAndroid Build Coastguard Worker    {
118*61046927SAndroid Build Coastguard Worker      free(gc);
119*61046927SAndroid Build Coastguard Worker      return NULL;
120*61046927SAndroid Build Coastguard Worker    }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    return gc;
123*61046927SAndroid Build Coastguard Worker }
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker windowsContext *
windows_create_context_attribs(int pxfi,windowsContext * shared,const int * attribList)126*61046927SAndroid Build Coastguard Worker windows_create_context_attribs(int pxfi, windowsContext *shared, const int *attribList)
127*61046927SAndroid Build Coastguard Worker {
128*61046927SAndroid Build Coastguard Worker    windowsContext *gc;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    gc = calloc(1, sizeof *gc);
131*61046927SAndroid Build Coastguard Worker    if (gc == NULL)
132*61046927SAndroid Build Coastguard Worker       return NULL;
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker    // create a temporary, invisible window
135*61046927SAndroid Build Coastguard Worker #define GL_TEMP_WINDOW_CLASS "glTempWndClass"
136*61046927SAndroid Build Coastguard Worker    {
137*61046927SAndroid Build Coastguard Worker       static wATOM glTempWndClass = 0;
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker       if (glTempWndClass == 0) {
140*61046927SAndroid Build Coastguard Worker          WNDCLASSEX wc;
141*61046927SAndroid Build Coastguard Worker          wc.cbSize = sizeof(WNDCLASSEX);
142*61046927SAndroid Build Coastguard Worker          wc.style = CS_HREDRAW | CS_VREDRAW;
143*61046927SAndroid Build Coastguard Worker          wc.lpfnWndProc = DefWindowProc;
144*61046927SAndroid Build Coastguard Worker          wc.cbClsExtra = 0;
145*61046927SAndroid Build Coastguard Worker          wc.cbWndExtra = 0;
146*61046927SAndroid Build Coastguard Worker          wc.hInstance = GetModuleHandle(NULL);
147*61046927SAndroid Build Coastguard Worker          wc.hIcon = 0;
148*61046927SAndroid Build Coastguard Worker          wc.hCursor = 0;
149*61046927SAndroid Build Coastguard Worker          wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
150*61046927SAndroid Build Coastguard Worker          wc.lpszMenuName = NULL;
151*61046927SAndroid Build Coastguard Worker          wc.lpszClassName = GL_TEMP_WINDOW_CLASS;
152*61046927SAndroid Build Coastguard Worker          wc.hIconSm = 0;
153*61046927SAndroid Build Coastguard Worker          RegisterClassEx(&wc);
154*61046927SAndroid Build Coastguard Worker       }
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    HWND hwnd = CreateWindowExA(0,
158*61046927SAndroid Build Coastguard Worker                                GL_TEMP_WINDOW_CLASS,
159*61046927SAndroid Build Coastguard Worker                                "glWindow",
160*61046927SAndroid Build Coastguard Worker                                0,
161*61046927SAndroid Build Coastguard Worker                                0, 0, 0, 0,
162*61046927SAndroid Build Coastguard Worker                                NULL, NULL, GetModuleHandle(NULL), NULL);
163*61046927SAndroid Build Coastguard Worker    HDC hdc = GetDC(hwnd);
164*61046927SAndroid Build Coastguard Worker    HGLRC shareContext = NULL;
165*61046927SAndroid Build Coastguard Worker    if (shared)
166*61046927SAndroid Build Coastguard Worker       shareContext = shared->ctx;
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    // We must set the windows pixel format before we can create a WGL context
169*61046927SAndroid Build Coastguard Worker    gc->pxfi = pxfi;
170*61046927SAndroid Build Coastguard Worker    SetPixelFormat(hdc, gc->pxfi, NULL);
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker    gc->ctx = wglCreateContextAttribsARB(hdc, shareContext, attribList);
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    ReleaseDC(hwnd, hdc);
175*61046927SAndroid Build Coastguard Worker    DestroyWindow(hwnd);
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker    if (!gc->ctx)
178*61046927SAndroid Build Coastguard Worker    {
179*61046927SAndroid Build Coastguard Worker      free(gc);
180*61046927SAndroid Build Coastguard Worker      return NULL;
181*61046927SAndroid Build Coastguard Worker    }
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    return gc;
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker void
windows_destroy_context(windowsContext * context)187*61046927SAndroid Build Coastguard Worker windows_destroy_context(windowsContext *context)
188*61046927SAndroid Build Coastguard Worker {
189*61046927SAndroid Build Coastguard Worker    wglDeleteContext(context->ctx);
190*61046927SAndroid Build Coastguard Worker    context->ctx = NULL;
191*61046927SAndroid Build Coastguard Worker    free(context);
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker 
windows_bind_context(windowsContext * context,windowsDrawable * draw,windowsDrawable * read)194*61046927SAndroid Build Coastguard Worker int windows_bind_context(windowsContext *context, windowsDrawable *draw, windowsDrawable *read)
195*61046927SAndroid Build Coastguard Worker {
196*61046927SAndroid Build Coastguard Worker    HDC drawDc = draw->callbacks->getdc(draw);
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    if (!draw->pxfi)
199*61046927SAndroid Build Coastguard Worker    {
200*61046927SAndroid Build Coastguard Worker       SetPixelFormat(drawDc, context->pxfi, NULL);
201*61046927SAndroid Build Coastguard Worker       draw->pxfi = context->pxfi;
202*61046927SAndroid Build Coastguard Worker    }
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    if ((read != NULL) &&  (read != draw))
205*61046927SAndroid Build Coastguard Worker    {
206*61046927SAndroid Build Coastguard Worker       /*
207*61046927SAndroid Build Coastguard Worker         If there is a separate read drawable, create a separate read DC, and
208*61046927SAndroid Build Coastguard Worker         use the wglMakeContextCurrent extension to make the context current
209*61046927SAndroid Build Coastguard Worker         drawing to one DC and reading from the other
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker         Should only occur when WGL_ARB_make_current_read extension is present
212*61046927SAndroid Build Coastguard Worker       */
213*61046927SAndroid Build Coastguard Worker       HDC readDc = read->callbacks->getdc(read);
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker       BOOL ret = wglMakeContextCurrentARB(drawDc, readDc, context->ctx);
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker       read->callbacks->releasedc(read, readDc);
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker       if (!ret) {
220*61046927SAndroid Build Coastguard Worker          printf("wglMakeContextCurrentARB error: %08x\n", (int)GetLastError());
221*61046927SAndroid Build Coastguard Worker          return false;
222*61046927SAndroid Build Coastguard Worker       }
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker    else
225*61046927SAndroid Build Coastguard Worker    {
226*61046927SAndroid Build Coastguard Worker       /* Otherwise, just use wglMakeCurrent */
227*61046927SAndroid Build Coastguard Worker       BOOL ret = wglMakeCurrent(drawDc, context->ctx);
228*61046927SAndroid Build Coastguard Worker       if (!ret) {
229*61046927SAndroid Build Coastguard Worker          printf("wglMakeCurrent error: %08x\n", (int)GetLastError());
230*61046927SAndroid Build Coastguard Worker          return false;
231*61046927SAndroid Build Coastguard Worker       }
232*61046927SAndroid Build Coastguard Worker    }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    draw->callbacks->releasedc(draw, drawDc);
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    windows_glapi_set_dispatch();
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker    return true;
239*61046927SAndroid Build Coastguard Worker }
240*61046927SAndroid Build Coastguard Worker 
windows_unbind_context(windowsContext * context)241*61046927SAndroid Build Coastguard Worker void windows_unbind_context(windowsContext * context)
242*61046927SAndroid Build Coastguard Worker {
243*61046927SAndroid Build Coastguard Worker    wglMakeCurrent(NULL, NULL);
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker /*
247*61046927SAndroid Build Coastguard Worker  *
248*61046927SAndroid Build Coastguard Worker  */
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker void
windows_swap_buffers(windowsDrawable * draw)251*61046927SAndroid Build Coastguard Worker windows_swap_buffers(windowsDrawable *draw)
252*61046927SAndroid Build Coastguard Worker {
253*61046927SAndroid Build Coastguard Worker    HDC drawDc = GetDC(draw->hWnd);
254*61046927SAndroid Build Coastguard Worker    SwapBuffers(drawDc);
255*61046927SAndroid Build Coastguard Worker    ReleaseDC(draw->hWnd, drawDc);
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker typedef void (__stdcall * PFNGLADDSWAPHINTRECTWIN) (GLint x, GLint y,
260*61046927SAndroid Build Coastguard Worker                                                     GLsizei width,
261*61046927SAndroid Build Coastguard Worker                                                     GLsizei height);
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker static void
glAddSwapHintRectWIN(GLint x,GLint y,GLsizei width,GLsizei height)264*61046927SAndroid Build Coastguard Worker glAddSwapHintRectWIN(GLint x, GLint y, GLsizei width,
265*61046927SAndroid Build Coastguard Worker                             GLsizei height)
266*61046927SAndroid Build Coastguard Worker {
267*61046927SAndroid Build Coastguard Worker    PFNGLADDSWAPHINTRECTWIN proc = (PFNGLADDSWAPHINTRECTWIN)wglGetProcAddress("glAddSwapHintRectWIN");
268*61046927SAndroid Build Coastguard Worker    if (proc)
269*61046927SAndroid Build Coastguard Worker       proc(x, y, width, height);
270*61046927SAndroid Build Coastguard Worker }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker void
windows_copy_subbuffer(windowsDrawable * draw,int x,int y,int width,int height)273*61046927SAndroid Build Coastguard Worker windows_copy_subbuffer(windowsDrawable *draw,
274*61046927SAndroid Build Coastguard Worker                       int x, int y, int width, int height)
275*61046927SAndroid Build Coastguard Worker {
276*61046927SAndroid Build Coastguard Worker    glAddSwapHintRectWIN(x, y, width, height);
277*61046927SAndroid Build Coastguard Worker    windows_swap_buffers(draw);
278*61046927SAndroid Build Coastguard Worker }
279*61046927SAndroid Build Coastguard Worker 
280*61046927SAndroid Build Coastguard Worker /*
281*61046927SAndroid Build Coastguard Worker  * Helper function for calling a test function on an initial context
282*61046927SAndroid Build Coastguard Worker  */
283*61046927SAndroid Build Coastguard Worker static void
windows_call_with_context(void (* proc)(HDC,void *),void * args)284*61046927SAndroid Build Coastguard Worker windows_call_with_context(void (*proc)(HDC, void *), void *args)
285*61046927SAndroid Build Coastguard Worker {
286*61046927SAndroid Build Coastguard Worker    // create window class
287*61046927SAndroid Build Coastguard Worker #define WIN_GL_TEST_WINDOW_CLASS "GLTest"
288*61046927SAndroid Build Coastguard Worker    {
289*61046927SAndroid Build Coastguard Worker       static wATOM glTestWndClass = 0;
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker       if (glTestWndClass == 0) {
292*61046927SAndroid Build Coastguard Worker          WNDCLASSEX wc;
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker          wc.cbSize = sizeof(WNDCLASSEX);
295*61046927SAndroid Build Coastguard Worker          wc.style = CS_HREDRAW | CS_VREDRAW;
296*61046927SAndroid Build Coastguard Worker          wc.lpfnWndProc = DefWindowProc;
297*61046927SAndroid Build Coastguard Worker          wc.cbClsExtra = 0;
298*61046927SAndroid Build Coastguard Worker          wc.cbWndExtra = 0;
299*61046927SAndroid Build Coastguard Worker          wc.hInstance = GetModuleHandle(NULL);
300*61046927SAndroid Build Coastguard Worker          wc.hIcon = 0;
301*61046927SAndroid Build Coastguard Worker          wc.hCursor = 0;
302*61046927SAndroid Build Coastguard Worker          wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
303*61046927SAndroid Build Coastguard Worker          wc.lpszMenuName = NULL;
304*61046927SAndroid Build Coastguard Worker          wc.lpszClassName = WIN_GL_TEST_WINDOW_CLASS;
305*61046927SAndroid Build Coastguard Worker          wc.hIconSm = 0;
306*61046927SAndroid Build Coastguard Worker          glTestWndClass = RegisterClassEx(&wc);
307*61046927SAndroid Build Coastguard Worker       }
308*61046927SAndroid Build Coastguard Worker    }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    // create an invisible window for a scratch DC
311*61046927SAndroid Build Coastguard Worker    HWND hwnd = CreateWindowExA(0,
312*61046927SAndroid Build Coastguard Worker                                WIN_GL_TEST_WINDOW_CLASS,
313*61046927SAndroid Build Coastguard Worker                                "GL Renderer Capabilities Test Window",
314*61046927SAndroid Build Coastguard Worker                                0, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL),
315*61046927SAndroid Build Coastguard Worker                                NULL);
316*61046927SAndroid Build Coastguard Worker    if (hwnd) {
317*61046927SAndroid Build Coastguard Worker       HDC hdc = GetDC(hwnd);
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker       // we must set a pixel format before we can create a context, just use the first one...
320*61046927SAndroid Build Coastguard Worker       SetPixelFormat(hdc, 1, NULL);
321*61046927SAndroid Build Coastguard Worker       HGLRC hglrc = wglCreateContext(hdc);
322*61046927SAndroid Build Coastguard Worker       wglMakeCurrent(hdc, hglrc);
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker       // call the test function
325*61046927SAndroid Build Coastguard Worker       proc(hdc, args);
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker       // clean up
328*61046927SAndroid Build Coastguard Worker       wglMakeCurrent(NULL, NULL);
329*61046927SAndroid Build Coastguard Worker       wglDeleteContext(hglrc);
330*61046927SAndroid Build Coastguard Worker       ReleaseDC(hwnd, hdc);
331*61046927SAndroid Build Coastguard Worker       DestroyWindow(hwnd);
332*61046927SAndroid Build Coastguard Worker    }
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker static void
windows_check_render_test(HDC hdc,void * args)336*61046927SAndroid Build Coastguard Worker windows_check_render_test(HDC hdc, void *args)
337*61046927SAndroid Build Coastguard Worker {
338*61046927SAndroid Build Coastguard Worker    int *result = (int *)args;
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    /* Rather than play linkage games using stdcall to ensure we get
341*61046927SAndroid Build Coastguard Worker       glGetString from opengl32.dll here, use dlsym */
342*61046927SAndroid Build Coastguard Worker    void *dlhandle = windows_get_dl_handle();
343*61046927SAndroid Build Coastguard Worker    const char *(*proc)(int) = dlsym(dlhandle, "glGetString");
344*61046927SAndroid Build Coastguard Worker    const char *gl_renderer = (const char *)proc(GL_RENDERER);
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker    if ((!gl_renderer) || (strcasecmp(gl_renderer, "GDI Generic") == 0))
347*61046927SAndroid Build Coastguard Worker       *result = false;
348*61046927SAndroid Build Coastguard Worker    else
349*61046927SAndroid Build Coastguard Worker       *result = true;
350*61046927SAndroid Build Coastguard Worker }
351*61046927SAndroid Build Coastguard Worker 
352*61046927SAndroid Build Coastguard Worker int
windows_check_renderer(void)353*61046927SAndroid Build Coastguard Worker windows_check_renderer(void)
354*61046927SAndroid Build Coastguard Worker {
355*61046927SAndroid Build Coastguard Worker    int result;
356*61046927SAndroid Build Coastguard Worker    windows_call_with_context(windows_check_render_test, &result);
357*61046927SAndroid Build Coastguard Worker    return result;
358*61046927SAndroid Build Coastguard Worker }
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker typedef struct {
361*61046927SAndroid Build Coastguard Worker    char *gl_extensions;
362*61046927SAndroid Build Coastguard Worker    char *wgl_extensions;
363*61046927SAndroid Build Coastguard Worker } windows_extensions_result;
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker static void
windows_extensions_test(HDC hdc,void * args)366*61046927SAndroid Build Coastguard Worker windows_extensions_test(HDC hdc, void *args)
367*61046927SAndroid Build Coastguard Worker {
368*61046927SAndroid Build Coastguard Worker    windows_extensions_result *r = (windows_extensions_result *)args;
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker    void *dlhandle = windows_get_dl_handle();
371*61046927SAndroid Build Coastguard Worker    const char *(*proc)(int) = dlsym(dlhandle, "glGetString");
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    r->gl_extensions = strdup(proc(GL_EXTENSIONS));
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    wglResolveExtensionProcs();
376*61046927SAndroid Build Coastguard Worker    r->wgl_extensions = strdup(wglGetExtensionsStringARB(hdc));
377*61046927SAndroid Build Coastguard Worker }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker void
windows_extensions(char ** gl_extensions,char ** wgl_extensions)380*61046927SAndroid Build Coastguard Worker windows_extensions(char **gl_extensions, char **wgl_extensions)
381*61046927SAndroid Build Coastguard Worker {
382*61046927SAndroid Build Coastguard Worker    windows_extensions_result result;
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker    *gl_extensions = "";
385*61046927SAndroid Build Coastguard Worker    *wgl_extensions = "";
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker    windows_call_with_context(windows_extensions_test, &result);
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    *gl_extensions = result.gl_extensions;
390*61046927SAndroid Build Coastguard Worker    *wgl_extensions = result.wgl_extensions;
391*61046927SAndroid Build Coastguard Worker }
392