wined3d: Remove COM from the shader implementation.
[wine] / dlls / opengl32 / tests / opengl.c
1 /*
2  * Some tests for OpenGL functions
3  *
4  * Copyright (C) 2007-2008 Roderick Colenbrander
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <windows.h>
22 #include <wingdi.h>
23 #include "wine/test.h"
24
25 void WINAPI glClearColor(float red, float green, float blue, float alpha);
26 void WINAPI glClear(unsigned int mask);
27 void WINAPI glFinish(void);
28 typedef unsigned int GLenum;
29 #define GL_NO_ERROR 0x0
30 #define GL_INVALID_OPERATION 0x502
31 GLenum WINAPI glGetError(void);
32 #define GL_COLOR_BUFFER_BIT 0x00004000
33 const unsigned char * WINAPI glGetString(unsigned int);
34 #define GL_VENDOR 0x1F00
35 #define GL_RENDERER 0x1F01
36 #define GL_VERSION 0x1F02
37
38 #define MAX_FORMATS 256
39 typedef void* HPBUFFERARB;
40
41 /* WGL_ARB_create_context */
42 static HGLRC (WINAPI *pwglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContext, const int *attribList);
43 /* GetLastError */
44 #define ERROR_INVALID_VERSION_ARB 0x2095
45 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
46 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
47 #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
48 #define WGL_CONTEXT_FLAGS_ARB 0x2094
49 /* Flags for WGL_CONTEXT_FLAGS_ARB */
50 #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
51 #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB  0x0002
52
53 /* WGL_ARB_extensions_string */
54 static const char* (WINAPI *pwglGetExtensionsStringARB)(HDC);
55 static int (WINAPI *pwglReleasePbufferDCARB)(HPBUFFERARB, HDC);
56
57 /* WGL_ARB_make_current_read */
58 static BOOL (WINAPI *pwglMakeContextCurrentARB)(HDC hdraw, HDC hread, HGLRC hglrc);
59 static HDC (WINAPI *pwglGetCurrentReadDCARB)(void);
60
61 /* WGL_ARB_pixel_format */
62 #define WGL_ACCELERATION_ARB 0x2003
63 #define WGL_COLOR_BITS_ARB 0x2014
64 #define WGL_RED_BITS_ARB   0x2015
65 #define WGL_GREEN_BITS_ARB 0x2017
66 #define WGL_BLUE_BITS_ARB  0x2019
67 #define WGL_ALPHA_BITS_ARB 0x201B
68 #define WGL_SUPPORT_GDI_ARB   0x200F
69 #define WGL_DOUBLE_BUFFER_ARB 0x2011
70 #define WGL_NO_ACCELERATION_ARB        0x2025
71 #define WGL_GENERIC_ACCELERATION_ARB   0x2026
72 #define WGL_FULL_ACCELERATION_ARB      0x2027
73
74 static BOOL (WINAPI *pwglChoosePixelFormatARB)(HDC, const int *, const FLOAT *, UINT, int *, UINT *);
75 static BOOL (WINAPI *pwglGetPixelFormatAttribivARB)(HDC, int, int, UINT, const int *, int *);
76
77 /* WGL_ARB_pbuffer */
78 #define WGL_DRAW_TO_PBUFFER_ARB 0x202D
79 static HPBUFFERARB* (WINAPI *pwglCreatePbufferARB)(HDC, int, int, int, const int *);
80 static HDC (WINAPI *pwglGetPbufferDCARB)(HPBUFFERARB);
81
82 static const char* wgl_extensions = NULL;
83
84 static void init_functions(void)
85 {
86 #define GET_PROC(func) \
87     p ## func = (void*)wglGetProcAddress(#func); \
88     if(!p ## func) \
89       trace("wglGetProcAddress(%s) failed\n", #func);
90
91     /* WGL_ARB_create_context */
92     GET_PROC(wglCreateContextAttribsARB);
93
94     /* WGL_ARB_extensions_string */
95     GET_PROC(wglGetExtensionsStringARB)
96
97     /* WGL_ARB_make_current_read */
98     GET_PROC(wglMakeContextCurrentARB);
99     GET_PROC(wglGetCurrentReadDCARB);
100
101     /* WGL_ARB_pixel_format */
102     GET_PROC(wglChoosePixelFormatARB)
103     GET_PROC(wglGetPixelFormatAttribivARB)
104
105     /* WGL_ARB_pbuffer */
106     GET_PROC(wglCreatePbufferARB)
107     GET_PROC(wglGetPbufferDCARB)
108     GET_PROC(wglReleasePbufferDCARB)
109
110 #undef GET_PROC
111 }
112
113 static void test_pbuffers(HDC hdc)
114 {
115     const int iAttribList[] = { WGL_DRAW_TO_PBUFFER_ARB, 1, /* Request pbuffer support */
116                                 0 };
117     int iFormats[MAX_FORMATS];
118     unsigned int nOnscreenFormats;
119     unsigned int nFormats;
120     int i, res;
121     int iPixelFormat = 0;
122
123     nOnscreenFormats = DescribePixelFormat(hdc, 0, 0, NULL);
124
125     /* When you want to render to a pbuffer you need to call wglGetPbufferDCARB which
126      * returns a 'magic' HDC which you can then pass to wglMakeCurrent to switch rendering
127      * to the pbuffer. Below some tests are performed on what happens if you use standard WGL calls
128      * on this 'magic' HDC for both a pixelformat that support onscreen and offscreen rendering
129      * and a pixelformat that's only available for offscreen rendering (this means that only
130      * wglChoosePixelFormatARB and friends know about the format.
131      *
132      * The first thing we need are pixelformats with pbuffer capabilities.
133      */
134     res = pwglChoosePixelFormatARB(hdc, iAttribList, NULL, MAX_FORMATS, iFormats, &nFormats);
135     if(res <= 0)
136     {
137         skip("No pbuffer compatible formats found while WGL_ARB_pbuffer is supported\n");
138         return;
139     }
140     trace("nOnscreenFormats: %d\n", nOnscreenFormats);
141     trace("Total number of pbuffer capable pixelformats: %d\n", nFormats);
142
143     /* Try to select an onscreen pixelformat out of the list */
144     for(i=0; i < nFormats; i++)
145     {
146         /* Check if the format is onscreen, if it is choose it */
147         if(iFormats[i] <= nOnscreenFormats)
148         {
149             iPixelFormat = iFormats[i];
150             trace("Selected iPixelFormat=%d\n", iPixelFormat);
151             break;
152         }
153     }
154
155     /* A video driver supports a large number of onscreen and offscreen pixelformats.
156      * The traditional WGL calls only see a subset of the whole pixelformat list. First
157      * of all they only see the onscreen formats (the offscreen formats are at the end of the
158      * pixelformat list) and second extended pixelformat capabilities are hidden from the
159      * standard WGL calls. Only functions that depend on WGL_ARB_pixel_format can see them.
160      *
161      * Below we check if the pixelformat is also supported onscreen.
162      */
163     if(iPixelFormat != 0)
164     {
165         HDC pbuffer_hdc;
166         HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL);
167         if(!pbuffer)
168             skip("Pbuffer creation failed!\n");
169
170         /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */
171         pbuffer_hdc = pwglGetPbufferDCARB(pbuffer);
172         res = GetPixelFormat(pbuffer_hdc);
173         ok(res == iPixelFormat, "Unexpected iPixelFormat=%d returned by GetPixelFormat for format %d\n", res, iPixelFormat);
174         trace("iPixelFormat returned by GetPixelFormat: %d\n", res);
175         trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat);
176
177         pwglReleasePbufferDCARB(pbuffer, hdc);
178     }
179     else skip("Pbuffer test for onscreen pixelformat skipped as no onscreen format with pbuffer capabilities have been found\n");
180
181     /* Search for a real offscreen format */
182     for(i=0, iPixelFormat=0; i<nFormats; i++)
183     {
184         if(iFormats[i] > nOnscreenFormats)
185         {
186             iPixelFormat = iFormats[i];
187             trace("Selected iPixelFormat: %d\n", iPixelFormat);
188             break;
189         }
190     }
191
192     if(iPixelFormat != 0)
193     {
194         HDC pbuffer_hdc;
195         HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL);
196         if(!pbuffer)
197             skip("Pbuffer creation failed!\n");
198
199         /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */
200         pbuffer_hdc = pwglGetPbufferDCARB(pbuffer);
201         res = GetPixelFormat(pbuffer_hdc);
202
203         ok(res == 1, "Unexpected iPixelFormat=%d (1 expected) returned by GetPixelFormat for offscreen format %d\n", res, iPixelFormat);
204         trace("iPixelFormat returned by GetPixelFormat: %d\n", res);
205         trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat);
206         pwglReleasePbufferDCARB(pbuffer, hdc);
207     }
208     else skip("Pbuffer test for offscreen pixelformat skipped as no offscreen-only format with pbuffer capabilities has been found\n");
209 }
210
211 static void test_setpixelformat(HDC winhdc)
212 {
213     int res = 0;
214     int nCfgs;
215     int pf;
216     int i;
217     HWND hwnd;
218     PIXELFORMATDESCRIPTOR pfd = {
219         sizeof(PIXELFORMATDESCRIPTOR),
220         1,                     /* version */
221         PFD_DRAW_TO_WINDOW |
222         PFD_SUPPORT_OPENGL |
223         PFD_DOUBLEBUFFER,
224         PFD_TYPE_RGBA,
225         24,                    /* 24-bit color depth */
226         0, 0, 0, 0, 0, 0,      /* color bits */
227         0,                     /* alpha buffer */
228         0,                     /* shift bit */
229         0,                     /* accumulation buffer */
230         0, 0, 0, 0,            /* accum bits */
231         32,                    /* z-buffer */
232         0,                     /* stencil buffer */
233         0,                     /* auxiliary buffer */
234         PFD_MAIN_PLANE,        /* main layer */
235         0,                     /* reserved */
236         0, 0, 0                /* layer masks */
237     };
238
239     HDC hdc = GetDC(0);
240     ok(hdc != 0, "GetDC(0) failed!\n");
241
242     /* This should pass even on the main device context */
243     pf = ChoosePixelFormat(hdc, &pfd);
244     ok(pf != 0, "ChoosePixelFormat failed on main device context\n");
245
246     /* SetPixelFormat on the main device context 'X root window' should fail,
247      * but some broken drivers allow it
248      */
249     res = SetPixelFormat(hdc, pf, &pfd);
250     trace("SetPixelFormat on main device context %s\n", res ? "succeeded" : "failed");
251
252     /* Setting the same format that was set on the HDC is allowed; other
253        formats fail */
254     nCfgs = DescribePixelFormat(winhdc, 0, 0, NULL);
255     pf = GetPixelFormat(winhdc);
256     for(i = 1;i <= nCfgs;i++)
257     {
258         int res = SetPixelFormat(winhdc, i, NULL);
259         if(i == pf) ok(res, "Failed to set the same pixel format\n");
260         else ok(!res, "Unexpectedly set an alternate pixel format\n");
261     }
262
263     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
264                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
265     ok(hwnd != NULL, "err: %d\n", GetLastError());
266     if (hwnd)
267     {
268         HDC hdc = GetDC( hwnd );
269         pf = ChoosePixelFormat( hdc, &pfd );
270         ok( pf != 0, "ChoosePixelFormat failed\n" );
271         res = SetPixelFormat( hdc, pf, &pfd );
272         ok( res != 0, "SetPixelFormat failed\n" );
273         i = GetPixelFormat( hdc );
274         ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
275         ReleaseDC( hwnd, hdc );
276         hdc = GetWindowDC( hwnd );
277         i = GetPixelFormat( hdc );
278         ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
279         ReleaseDC( hwnd, hdc );
280         DestroyWindow( hwnd );
281     }
282
283     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
284                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
285     ok(hwnd != NULL, "err: %d\n", GetLastError());
286     if (hwnd)
287     {
288         HDC hdc = GetWindowDC( hwnd );
289         pf = ChoosePixelFormat( hdc, &pfd );
290         ok( pf != 0, "ChoosePixelFormat failed\n" );
291         res = SetPixelFormat( hdc, pf, &pfd );
292         ok( res != 0, "SetPixelFormat failed\n" );
293         i = GetPixelFormat( hdc );
294         ok( i == pf, "GetPixelFormat returned wrong format %d/%d\n", i, pf );
295         ReleaseDC( hwnd, hdc );
296         DestroyWindow( hwnd );
297     }
298 }
299
300 static void test_sharelists(HDC winhdc)
301 {
302     HGLRC hglrc1, hglrc2, hglrc3;
303     int res;
304
305     hglrc1 = wglCreateContext(winhdc);
306     res = wglShareLists(0, 0);
307     ok(res == FALSE, "Sharing display lists for no contexts passed!\n");
308
309     /* Test 1: Create a context and just share lists without doing anything special */
310     hglrc2 = wglCreateContext(winhdc);
311     if(hglrc2)
312     {
313         res = wglShareLists(hglrc1, hglrc2);
314         ok(res, "Sharing of display lists failed\n");
315         wglDeleteContext(hglrc2);
316     }
317
318     /* Test 2: Share display lists with a 'destination' context which has been made current */
319     hglrc2 = wglCreateContext(winhdc);
320     if(hglrc2)
321     {
322         res = wglMakeCurrent(winhdc, hglrc2);
323         ok(res, "Make current failed\n");
324         res = wglShareLists(hglrc1, hglrc2);
325         todo_wine ok(res, "Sharing display lists with a destination context which has been made current failed\n");
326         wglMakeCurrent(0, 0);
327         wglDeleteContext(hglrc2);
328     }
329
330     /* Test 3: Share display lists with a context which already shares display lists with another context.
331      * According to MSDN the second parameter cannot share any display lists but some buggy drivers might allow it */
332     hglrc3 = wglCreateContext(winhdc);
333     if(hglrc3)
334     {
335         res = wglShareLists(hglrc3, hglrc1);
336         ok(res == FALSE, "Sharing of display lists passed for a context which already shared lists before\n");
337         wglDeleteContext(hglrc3);
338     }
339
340     /* Test 4: Share display lists with a 'source' context which has been made current */
341     hglrc2 = wglCreateContext(winhdc);
342     if(hglrc2)
343     {
344         res = wglMakeCurrent(winhdc, hglrc1);
345         ok(res, "Make current failed\n");
346         res = wglShareLists(hglrc1, hglrc2);
347         ok(res, "Sharing display lists with a source context which has been made current failed\n");
348         wglMakeCurrent(0, 0);
349         wglDeleteContext(hglrc2);
350     }
351 }
352
353 static void test_makecurrent(HDC winhdc)
354 {
355     BOOL ret;
356     HGLRC hglrc;
357     DWORD error;
358
359     hglrc = wglCreateContext(winhdc);
360     ok( hglrc != 0, "wglCreateContext failed\n" );
361
362     ret = wglMakeCurrent( winhdc, hglrc );
363     ok( ret, "wglMakeCurrent failed\n" );
364
365     ok( wglGetCurrentContext() == hglrc, "wrong context\n" );
366
367     /* set the same context again */
368     ret = wglMakeCurrent( winhdc, hglrc );
369     ok( ret, "wglMakeCurrent failed\n" );
370
371     /* check wglMakeCurrent(x, y) after another call to wglMakeCurrent(x, y) */
372     ret = wglMakeCurrent( winhdc, NULL );
373     ok( ret, "wglMakeCurrent failed\n" );
374
375     ret = wglMakeCurrent( winhdc, NULL );
376     ok( ret, "wglMakeCurrent failed\n" );
377
378     SetLastError( 0xdeadbeef );
379     ret = wglMakeCurrent( NULL, NULL );
380     ok( !ret, "wglMakeCurrent succeeded\n" );
381     error = GetLastError();
382     ok( error == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got error=%x\n", error);
383
384     ret = wglMakeCurrent( winhdc, NULL );
385     ok( ret, "wglMakeCurrent failed\n" );
386
387     ret = wglMakeCurrent( winhdc, hglrc );
388     ok( ret, "wglMakeCurrent failed\n" );
389
390     ret = wglMakeCurrent( NULL, NULL );
391     ok( ret, "wglMakeCurrent failed\n" );
392
393     ok( wglGetCurrentContext() == NULL, "wrong context\n" );
394
395     SetLastError( 0xdeadbeef );
396     ret = wglMakeCurrent( NULL, NULL );
397     ok( !ret, "wglMakeCurrent succeeded\n" );
398     error = GetLastError();
399     ok( error == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got error=%x\n", error);
400
401     ret = wglMakeCurrent( winhdc, hglrc );
402     ok( ret, "wglMakeCurrent failed\n" );
403 }
404
405 static void test_colorbits(HDC hdc)
406 {
407     const int iAttribList[] = { WGL_COLOR_BITS_ARB, WGL_RED_BITS_ARB, WGL_GREEN_BITS_ARB,
408                                 WGL_BLUE_BITS_ARB, WGL_ALPHA_BITS_ARB };
409     int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
410     const int iAttribs[] = { WGL_ALPHA_BITS_ARB, 1, 0 };
411     unsigned int nFormats;
412     int res;
413     int iPixelFormat = 0;
414
415     if (!pwglChoosePixelFormatARB)
416     {
417         win_skip("wglChoosePixelFormatARB is not available\n");
418         return;
419     }
420
421     /* We need a pixel format with at least one bit of alpha */
422     res = pwglChoosePixelFormatARB(hdc, iAttribs, NULL, 1, &iPixelFormat, &nFormats);
423     if(res == FALSE || nFormats == 0)
424     {
425         skip("No suitable pixel formats found\n");
426         return;
427     }
428
429     res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
430               sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList, iAttribRet);
431     if(res == FALSE)
432     {
433         skip("wglGetPixelFormatAttribivARB failed\n");
434         return;
435     }
436     iAttribRet[1] += iAttribRet[2]+iAttribRet[3]+iAttribRet[4];
437     ok(iAttribRet[0] == iAttribRet[1], "WGL_COLOR_BITS_ARB (%d) does not equal R+G+B+A (%d)!\n",
438                                        iAttribRet[0], iAttribRet[1]);
439 }
440
441 static void test_gdi_dbuf(HDC hdc)
442 {
443     const int iAttribList[] = { WGL_SUPPORT_GDI_ARB, WGL_DOUBLE_BUFFER_ARB };
444     int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
445     unsigned int nFormats;
446     int iPixelFormat;
447     int res;
448
449     if (!pwglGetPixelFormatAttribivARB)
450     {
451         win_skip("wglGetPixelFormatAttribivARB is not available\n");
452         return;
453     }
454
455     nFormats = DescribePixelFormat(hdc, 0, 0, NULL);
456     for(iPixelFormat = 1;iPixelFormat <= nFormats;iPixelFormat++)
457     {
458         res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
459                   sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList,
460                   iAttribRet);
461         ok(res!=FALSE, "wglGetPixelFormatAttribivARB failed for pixel format %d\n", iPixelFormat);
462         if(res == FALSE)
463             continue;
464
465         ok(!(iAttribRet[0] && iAttribRet[1]), "GDI support and double buffering on pixel format %d\n", iPixelFormat);
466     }
467 }
468
469 static void test_acceleration(HDC hdc)
470 {
471     const int iAttribList[] = { WGL_ACCELERATION_ARB };
472     int iAttribRet[sizeof(iAttribList)/sizeof(iAttribList[0])];
473     unsigned int nFormats;
474     int iPixelFormat;
475     int res;
476     PIXELFORMATDESCRIPTOR pfd;
477
478     if (!pwglGetPixelFormatAttribivARB)
479     {
480         win_skip("wglGetPixelFormatAttribivARB is not available\n");
481         return;
482     }
483
484     nFormats = DescribePixelFormat(hdc, 0, 0, NULL);
485     for(iPixelFormat = 1; iPixelFormat <= nFormats; iPixelFormat++)
486     {
487         res = pwglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0,
488                   sizeof(iAttribList)/sizeof(iAttribList[0]), iAttribList,
489                   iAttribRet);
490         ok(res!=FALSE, "wglGetPixelFormatAttribivARB failed for pixel format %d\n", iPixelFormat);
491         if(res == FALSE)
492             continue;
493
494         memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
495         DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
496
497         switch(iAttribRet[0])
498         {
499             case WGL_NO_ACCELERATION_ARB:
500                 ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == PFD_GENERIC_FORMAT , "Expected only PFD_GENERIC_FORMAT to be set for WGL_NO_ACCELERATION_ARB!: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
501                 break;
502             case WGL_GENERIC_ACCELERATION_ARB:
503                 ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED), "Expected both PFD_GENERIC_FORMAT and PFD_GENERIC_ACCELERATION to be set for WGL_GENERIC_ACCELERATION_ARB: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
504                 break;
505             case WGL_FULL_ACCELERATION_ARB:
506                 ok( (pfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED)) == 0, "Expected no PFD_GENERIC_FORMAT/_ACCELERATION to be set for WGL_FULL_ACCELERATION_ARB: iPixelFormat=%d, dwFlags=%x!\n", iPixelFormat, pfd.dwFlags);
507                 break;
508         }
509     }
510 }
511
512 static void test_bitmap_rendering(void)
513 {
514     PIXELFORMATDESCRIPTOR pfd;
515     int i, iPixelFormat=0;
516     unsigned int nFormats;
517     HGLRC hglrc;
518     BITMAPINFO biDst;
519     HBITMAP bmpDst, oldDst;
520     HDC hdcDst, hdcScreen;
521     UINT32 *dstBuffer;
522
523     memset(&biDst, 0, sizeof(BITMAPINFO));
524     biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
525     biDst.bmiHeader.biWidth = 2;
526     biDst.bmiHeader.biHeight = -2;
527     biDst.bmiHeader.biPlanes = 1;
528     biDst.bmiHeader.biBitCount = 32;
529     biDst.bmiHeader.biCompression = BI_RGB;
530
531     hdcScreen = CreateCompatibleDC(0);
532     if(GetDeviceCaps(hdcScreen, BITSPIXEL) != 32)
533     {
534         DeleteDC(hdcScreen);
535         trace("Skipping bitmap rendering test\n");
536         return;
537     }
538
539     hdcDst = CreateCompatibleDC(hdcScreen);
540     bmpDst = CreateDIBSection(hdcDst, &biDst, DIB_RGB_COLORS, (void**)&dstBuffer, NULL, 0);
541     oldDst = SelectObject(hdcDst, bmpDst);
542
543     /* Pick a pixel format by hand because ChoosePixelFormat is unreliable */
544     nFormats = DescribePixelFormat(hdcDst, 0, 0, NULL);
545     for(i=1; i<=nFormats; i++)
546     {
547         memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
548         DescribePixelFormat(hdcDst, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
549
550         if((pfd.dwFlags & PFD_DRAW_TO_BITMAP) &&
551            (pfd.dwFlags & PFD_SUPPORT_OPENGL) &&
552            (pfd.cColorBits == 32) &&
553            (pfd.cAlphaBits == 8) )
554         {
555             iPixelFormat = i;
556             break;
557         }
558     }
559
560     if(!iPixelFormat)
561     {
562         skip("Unable to find a suitable pixel format\n");
563     }
564     else
565     {
566         SetPixelFormat(hdcDst, iPixelFormat, &pfd);
567         hglrc = wglCreateContext(hdcDst);
568         todo_wine ok(hglrc != NULL, "Unable to create a context\n");
569
570         if(hglrc)
571         {
572             wglMakeCurrent(hdcDst, hglrc);
573
574             /* Note this is RGBA but we read ARGB back */
575             glClearColor((float)0x22/0xff, (float)0x33/0xff, (float)0x44/0xff, (float)0x11/0xff);
576             glClear(GL_COLOR_BUFFER_BIT);
577             glFinish();
578
579             /* Note apparently the alpha channel is not supported by the software renderer (bitmap only works using software) */
580             ok(dstBuffer[0] == 0x223344, "Expected color=0x223344, received color=%x\n", dstBuffer[0]);
581
582             wglMakeCurrent(NULL, NULL);
583             wglDeleteContext(hglrc);
584         }
585     }
586
587     SelectObject(hdcDst, oldDst);
588     DeleteObject(bmpDst);
589     DeleteDC(hdcDst);
590
591     DeleteDC(hdcScreen);
592 }
593
594 struct wgl_thread_param
595 {
596     HANDLE test_finished;
597     HGLRC hglrc;
598     BOOL hglrc_deleted;
599     DWORD last_error;
600 };
601
602 static DWORD WINAPI wgl_thread(void *param)
603 {
604     struct wgl_thread_param *p = param;
605
606     SetLastError(0xdeadbeef);
607     p->hglrc_deleted = wglDeleteContext(p->hglrc);
608     p->last_error = GetLastError();
609     SetEvent(p->test_finished);
610
611     return 0;
612 }
613
614 static void test_deletecontext(HDC hdc)
615 {
616     struct wgl_thread_param thread_params;
617     HGLRC hglrc = wglCreateContext(hdc);
618     HANDLE thread_handle;
619     DWORD res, tid;
620
621     SetLastError(0xdeadbeef);
622     res = wglDeleteContext(NULL);
623     ok(res == FALSE, "wglDeleteContext succeeded\n");
624     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected last error to be ERROR_INVALID_HANDLE, got %u\n", GetLastError());
625
626     if(!hglrc)
627     {
628         skip("wglCreateContext failed!\n");
629         return;
630     }
631
632     res = wglMakeCurrent(hdc, hglrc);
633     if(!res)
634     {
635         skip("wglMakeCurrent failed!\n");
636         return;
637     }
638
639     /* WGL doesn't allow you to delete a context from a different thread than the one in which it is current.
640      * This differs from GLX which does allow it but it delays actual deletion until the context becomes not current.
641      */
642     thread_params.hglrc = hglrc;
643     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
644     thread_handle = CreateThread(NULL, 0, wgl_thread, &thread_params, 0, &tid);
645     ok(!!thread_handle, "Failed to create thread, last error %#x.\n", GetLastError());
646     if(thread_handle)
647     {
648         WaitForSingleObject(thread_handle, INFINITE);
649         ok(thread_params.hglrc_deleted == FALSE, "Attempt to delete WGL context from another thread passed but should fail!\n");
650         ok(thread_params.last_error == ERROR_BUSY, "Expected last error to be ERROR_BUSY, got %u\n", thread_params.last_error);
651     }
652     CloseHandle(thread_params.test_finished);
653
654     res = wglDeleteContext(hglrc);
655     ok(res == TRUE, "wglDeleteContext failed\n");
656
657     /* Attempting to delete the same context twice should fail. */
658     SetLastError(0xdeadbeef);
659     res = wglDeleteContext(hglrc);
660     ok(res == FALSE, "wglDeleteContext succeeded\n");
661     ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected last error to be ERROR_INVALID_HANDLE, got %u\n", GetLastError());
662
663     /* WGL makes a context not current when deleting it. This differs from GLX behavior where
664      * deletion takes place when the thread becomes not current. */
665     hglrc = wglGetCurrentContext();
666     ok(hglrc == NULL, "A WGL context is active while none was expected\n");
667 }
668
669 static void test_make_current_read(HDC hdc)
670 {
671     int res;
672     HDC hread;
673     HGLRC hglrc = wglCreateContext(hdc);
674
675     if(!hglrc)
676     {
677         skip("wglCreateContext failed!\n");
678         return;
679     }
680
681     res = wglMakeCurrent(hdc, hglrc);
682     if(!res)
683     {
684         skip("wglMakeCurrent failed!\n");
685         return;
686     }
687
688     /* Test what wglGetCurrentReadDCARB does for wglMakeCurrent as the spec doesn't mention it */
689     hread = pwglGetCurrentReadDCARB();
690     trace("hread %p, hdc %p\n", hread, hdc);
691     ok(hread == hdc, "wglGetCurrentReadDCARB failed for standard wglMakeCurrent\n");
692
693     pwglMakeContextCurrentARB(hdc, hdc, hglrc);
694     hread = pwglGetCurrentReadDCARB();
695     ok(hread == hdc, "wglGetCurrentReadDCARB failed for wglMakeContextCurrent\n");
696 }
697
698 static void test_dc(HWND hwnd, HDC hdc)
699 {
700     int pf1, pf2;
701     HDC hdc2;
702
703     /* Get another DC and make sure it has the same pixel format */
704     hdc2 = GetDC(hwnd);
705     if(hdc != hdc2)
706     {
707         pf1 = GetPixelFormat(hdc);
708         pf2 = GetPixelFormat(hdc2);
709         ok(pf1 == pf2, "Second DC does not have the same format (%d != %d)\n", pf1, pf2);
710     }
711     else
712         skip("Could not get a different DC for the window\n");
713
714     if(hdc2)
715     {
716         ReleaseDC(hwnd, hdc2);
717         hdc2 = NULL;
718     }
719 }
720
721 /* Nvidia converts win32 error codes to (0xc007 << 16) | win32_error_code */
722 #define NVIDIA_HRESULT_FROM_WIN32(x) (HRESULT_FROM_WIN32(x) | 0x40000000)
723 static void test_opengl3(HDC hdc)
724 {
725     /* Try to create a context compatible with OpenGL 1.x; 1.0-2.1 is allowed */
726     {
727         HGLRC gl3Ctx;
728         int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 1, 0};
729
730         gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);
731         ok(gl3Ctx != 0, "pwglCreateContextAttribsARB for a 1.x context failed!\n");
732         wglDeleteContext(gl3Ctx);
733     }
734
735     /* Try to pass an invalid HDC */
736     {
737         HGLRC gl3Ctx;
738         DWORD error;
739         gl3Ctx = pwglCreateContextAttribsARB((HDC)0xdeadbeef, 0, 0);
740         ok(gl3Ctx == 0, "pwglCreateContextAttribsARB using an invalid HDC passed\n");
741         error = GetLastError();
742         todo_wine ok(error == ERROR_DC_NOT_FOUND ||
743                      broken(error == NVIDIA_HRESULT_FROM_WIN32(ERROR_INVALID_DATA)), /* Nvidia Vista + Win7 */
744                      "Expected ERROR_DC_NOT_FOUND, got error=%x\n", error);
745         wglDeleteContext(gl3Ctx);
746     }
747
748     /* Try to pass an invalid shareList */
749     {
750         HGLRC gl3Ctx;
751         DWORD error;
752         gl3Ctx = pwglCreateContextAttribsARB(hdc, (HGLRC)0xdeadbeef, 0);
753         todo_wine ok(gl3Ctx == 0, "pwglCreateContextAttribsARB using an invalid shareList passed\n");
754         error = GetLastError();
755         /* The Nvidia implementation seems to return hresults instead of win32 error codes */
756         todo_wine ok(error == ERROR_INVALID_OPERATION ||
757                      error == NVIDIA_HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION), "Expected ERROR_INVALID_OPERATION, got error=%x\n", error);
758         wglDeleteContext(gl3Ctx);
759     }
760
761     /* Try to create an OpenGL 3.0 context */
762     {
763         int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
764         HGLRC gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);
765
766         if(gl3Ctx == NULL)
767         {
768             skip("Skipping the rest of the WGL_ARB_create_context test due to lack of OpenGL 3.0\n");
769             return;
770         }
771
772         wglDeleteContext(gl3Ctx);
773     }
774
775     /* Test matching an OpenGL 3.0 context with an older one, OpenGL 3.0 should allow it until the new object model is introduced in a future revision */
776     {
777         HGLRC glCtx = wglCreateContext(hdc);
778
779         int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
780         int attribs_future[] = {WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
781
782         HGLRC gl3Ctx = pwglCreateContextAttribsARB(hdc, glCtx, attribs);
783         ok(gl3Ctx != NULL, "Sharing of a display list between OpenGL 3.0 and OpenGL 1.x/2.x failed!\n");
784         if(gl3Ctx)
785             wglDeleteContext(gl3Ctx);
786
787         gl3Ctx = pwglCreateContextAttribsARB(hdc, glCtx, attribs_future);
788         ok(gl3Ctx != NULL, "Sharing of a display list between a forward compatible OpenGL 3.0 context and OpenGL 1.x/2.x failed!\n");
789         if(gl3Ctx)
790             wglDeleteContext(gl3Ctx);
791
792         if(glCtx)
793             wglDeleteContext(glCtx);
794     }
795
796     /* Try to create an OpenGL 3.0 context and test windowless rendering */
797     {
798         HGLRC gl3Ctx;
799         int attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 0, 0};
800         BOOL res;
801
802         gl3Ctx = pwglCreateContextAttribsARB(hdc, 0, attribs);
803         ok(gl3Ctx != 0, "pwglCreateContextAttribsARB for a 3.0 context failed!\n");
804
805         /* OpenGL 3.0 allows offscreen rendering WITHOUT a drawable
806          * Neither AMD or Nvidia support it at this point. The WGL_ARB_create_context specs also say that
807          * it is hard because drivers use the HDC to enter the display driver and it sounds like they don't
808          * expect drivers to ever offer it.
809          */
810         res = wglMakeCurrent(0, gl3Ctx);
811         ok(res == FALSE, "Wow, OpenGL 3.0 windowless rendering passed while it was expected not to!\n");
812         if(res)
813             wglMakeCurrent(0, 0);
814
815         if(gl3Ctx)
816             wglDeleteContext(gl3Ctx);
817     }
818 }
819
820 static void test_minimized(void)
821 {
822     PIXELFORMATDESCRIPTOR pf_desc =
823     {
824         sizeof(PIXELFORMATDESCRIPTOR),
825         1,                     /* version */
826         PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
827         PFD_TYPE_RGBA,
828         24,                    /* 24-bit color depth */
829         0, 0, 0, 0, 0, 0,      /* color bits */
830         0,                     /* alpha buffer */
831         0,                     /* shift bit */
832         0,                     /* accumulation buffer */
833         0, 0, 0, 0,            /* accum bits */
834         32,                    /* z-buffer */
835         0,                     /* stencil buffer */
836         0,                     /* auxiliary buffer */
837         PFD_MAIN_PLANE,        /* main layer */
838         0,                     /* reserved */
839         0, 0, 0                /* layer masks */
840     };
841     int pixel_format;
842     HWND window;
843     LONG style;
844     HGLRC ctx;
845     BOOL ret;
846     HDC dc;
847
848     window = CreateWindowA("static", "opengl32_test",
849             WS_POPUP | WS_MINIMIZE, 0, 0, 640, 480, 0, 0, 0, 0);
850     ok(!!window, "Failed to create window, last error %#x.\n", GetLastError());
851
852     dc = GetDC(window);
853     ok(!!dc, "Failed to get DC.\n");
854
855     pixel_format = ChoosePixelFormat(dc, &pf_desc);
856     if (!pixel_format)
857     {
858         win_skip("Failed to find pixel format.\n");
859         ReleaseDC(window, dc);
860         DestroyWindow(window);
861         return;
862     }
863
864     ret = SetPixelFormat(dc, pixel_format, &pf_desc);
865     ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());
866
867     style = GetWindowLongA(window, GWL_STYLE);
868     ok(style & WS_MINIMIZE, "Window should be minimized, got style %#x.\n", style);
869
870     ctx = wglCreateContext(dc);
871     ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());
872
873     ret = wglMakeCurrent(dc, ctx);
874     ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
875
876     style = GetWindowLongA(window, GWL_STYLE);
877     ok(style & WS_MINIMIZE, "window should be minimized, got style %#x.\n", style);
878
879     ret = wglMakeCurrent(NULL, NULL);
880     ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());
881
882     ret = wglDeleteContext(ctx);
883     ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());
884
885     ReleaseDC(window, dc);
886     DestroyWindow(window);
887 }
888
889 static void test_destroy(HDC oldhdc)
890 {
891     PIXELFORMATDESCRIPTOR pf_desc =
892     {
893         sizeof(PIXELFORMATDESCRIPTOR),
894         1,                     /* version */
895         PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
896         PFD_TYPE_RGBA,
897         24,                    /* 24-bit color depth */
898         0, 0, 0, 0, 0, 0,      /* color bits */
899         0,                     /* alpha buffer */
900         0,                     /* shift bit */
901         0,                     /* accumulation buffer */
902         0, 0, 0, 0,            /* accum bits */
903         32,                    /* z-buffer */
904         0,                     /* stencil buffer */
905         0,                     /* auxiliary buffer */
906         PFD_MAIN_PLANE,        /* main layer */
907         0,                     /* reserved */
908         0, 0, 0                /* layer masks */
909     };
910     int pixel_format;
911     HWND window;
912     HGLRC ctx;
913     BOOL ret;
914     HDC dc;
915     GLenum glerr;
916     DWORD err;
917     HGLRC oldctx = wglGetCurrentContext();
918
919     ok(!!oldctx, "Expected to find a valid current context.\n");
920
921     window = CreateWindowA("static", "opengl32_test",
922             WS_POPUP, 0, 0, 640, 480, 0, 0, 0, 0);
923     ok(!!window, "Failed to create window, last error %#x.\n", GetLastError());
924
925     dc = GetDC(window);
926     ok(!!dc, "Failed to get DC.\n");
927
928     pixel_format = ChoosePixelFormat(dc, &pf_desc);
929     if (!pixel_format)
930     {
931         win_skip("Failed to find pixel format.\n");
932         ReleaseDC(window, dc);
933         DestroyWindow(window);
934         return;
935     }
936
937     ret = SetPixelFormat(dc, pixel_format, &pf_desc);
938     ok(ret, "Failed to set pixel format, last error %#x.\n", GetLastError());
939
940     ctx = wglCreateContext(dc);
941     ok(!!ctx, "Failed to create GL context, last error %#x.\n", GetLastError());
942
943     ret = wglMakeCurrent(dc, ctx);
944     ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
945
946     glClear(GL_COLOR_BUFFER_BIT);
947     glFinish();
948     glerr = glGetError();
949     ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
950
951     ret = DestroyWindow(window);
952     ok(ret, "Failed to destroy window, last error %#x.\n", GetLastError());
953
954     ok(wglGetCurrentContext() == ctx, "Wrong current context.\n");
955
956     SetLastError(0xdeadbeef);
957     ret = wglMakeCurrent(dc, ctx);
958     err = GetLastError();
959     ok(!ret && err == ERROR_INVALID_HANDLE,
960             "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);
961
962     ok(wglGetCurrentContext() == ctx, "Wrong current context.\n");
963
964     glClear(GL_COLOR_BUFFER_BIT);
965     glFinish();
966     glerr = glGetError();
967     ok(glerr == GL_NO_ERROR, "Failed glClear, error %#x.\n", glerr);
968
969     ret = wglMakeCurrent(NULL, NULL);
970     ok(ret, "Failed to clear current context, last error %#x.\n", GetLastError());
971
972     glClear(GL_COLOR_BUFFER_BIT);
973     glFinish();
974     glerr = glGetError();
975     todo_wine ok(glerr == GL_INVALID_OPERATION, "Failed glClear, error %#x.\n", glerr);
976
977     SetLastError(0xdeadbeef);
978     ret = wglMakeCurrent(dc, ctx);
979     err = GetLastError();
980     ok(!ret && err == ERROR_INVALID_HANDLE,
981             "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);
982
983     ok(wglGetCurrentContext() == NULL, "Wrong current context.\n");
984
985     ret = wglMakeCurrent(oldhdc, oldctx);
986     ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
987     ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");
988
989     SetLastError(0xdeadbeef);
990     ret = wglMakeCurrent(dc, ctx);
991     err = GetLastError();
992     ok(!ret && err == ERROR_INVALID_HANDLE,
993             "Unexpected behavior when making context current, ret %d, last error %#x.\n", ret, err);
994
995     ok(wglGetCurrentContext() == oldctx, "Wrong current context.\n");
996
997     ret = wglDeleteContext(ctx);
998     ok(ret, "Failed to delete GL context, last error %#x.\n", GetLastError());
999
1000     ReleaseDC(window, dc);
1001
1002     ret = wglMakeCurrent(oldhdc, oldctx);
1003     ok(ret, "Failed to make context current, last error %#x.\n", GetLastError());
1004 }
1005
1006 START_TEST(opengl)
1007 {
1008     HWND hwnd;
1009     PIXELFORMATDESCRIPTOR pfd = {
1010         sizeof(PIXELFORMATDESCRIPTOR),
1011         1,                     /* version */
1012         PFD_DRAW_TO_WINDOW |
1013         PFD_SUPPORT_OPENGL |
1014         PFD_DOUBLEBUFFER,
1015         PFD_TYPE_RGBA,
1016         24,                    /* 24-bit color depth */
1017         0, 0, 0, 0, 0, 0,      /* color bits */
1018         0,                     /* alpha buffer */
1019         0,                     /* shift bit */
1020         0,                     /* accumulation buffer */
1021         0, 0, 0, 0,            /* accum bits */
1022         32,                    /* z-buffer */
1023         0,                     /* stencil buffer */
1024         0,                     /* auxiliary buffer */
1025         PFD_MAIN_PLANE,        /* main layer */
1026         0,                     /* reserved */
1027         0, 0, 0                /* layer masks */
1028     };
1029
1030     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
1031                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
1032     ok(hwnd != NULL, "err: %d\n", GetLastError());
1033     if (hwnd)
1034     {
1035         HDC hdc;
1036         int iPixelFormat, res;
1037         HGLRC hglrc;
1038         DWORD error;
1039         ShowWindow(hwnd, SW_SHOW);
1040
1041         hdc = GetDC(hwnd);
1042
1043         iPixelFormat = ChoosePixelFormat(hdc, &pfd);
1044         if(iPixelFormat == 0)
1045         {
1046             /* This should never happen as ChoosePixelFormat always returns a closest match, but currently this fails in Wine if we don't have glX */
1047             win_skip("Unable to find pixel format.\n");
1048             goto cleanup;
1049         }
1050
1051         /* We shouldn't be able to create a context from a hdc which doesn't have a pixel format set */
1052         hglrc = wglCreateContext(hdc);
1053         ok(hglrc == NULL, "wglCreateContext should fail when no pixel format has been set, but it passed\n");
1054         error = GetLastError();
1055         ok(error == ERROR_INVALID_PIXEL_FORMAT, "expected ERROR_INVALID_PIXEL_FORMAT for wglCreateContext without a pixelformat set, but received %#x\n", error);
1056
1057         res = SetPixelFormat(hdc, iPixelFormat, &pfd);
1058         ok(res, "SetPixelformat failed: %x\n", GetLastError());
1059
1060         test_bitmap_rendering();
1061         test_minimized();
1062         test_dc(hwnd, hdc);
1063
1064         hglrc = wglCreateContext(hdc);
1065         res = wglMakeCurrent(hdc, hglrc);
1066         ok(res, "wglMakeCurrent failed!\n");
1067         if(res)
1068         {
1069             trace("OpenGL renderer: %s\n", glGetString(GL_RENDERER));
1070             trace("OpenGL driver version: %s\n", glGetString(GL_VERSION));
1071             trace("OpenGL vendor: %s\n", glGetString(GL_VENDOR));
1072         }
1073         else
1074         {
1075             skip("Skipping OpenGL tests without a current context\n");
1076             return;
1077         }
1078
1079         /* Initialisation of WGL functions depends on an implicit WGL context. For this reason we can't load them before making
1080          * any WGL call :( On Wine this would work but not on real Windows because there can be different implementations (software, ICD, MCD).
1081          */
1082         init_functions();
1083         /* The lack of wglGetExtensionsStringARB in general means broken software rendering or the lack of decent OpenGL support, skip tests in such cases */
1084         if (!pwglGetExtensionsStringARB)
1085         {
1086             win_skip("wglGetExtensionsStringARB is not available\n");
1087             return;
1088         }
1089
1090         test_deletecontext(hdc);
1091         test_makecurrent(hdc);
1092         test_setpixelformat(hdc);
1093         test_destroy(hdc);
1094         test_sharelists(hdc);
1095         test_colorbits(hdc);
1096         test_gdi_dbuf(hdc);
1097         test_acceleration(hdc);
1098
1099         wgl_extensions = pwglGetExtensionsStringARB(hdc);
1100         if(wgl_extensions == NULL) skip("Skipping opengl32 tests because this OpenGL implementation doesn't support WGL extensions!\n");
1101
1102         if(strstr(wgl_extensions, "WGL_ARB_create_context"))
1103             test_opengl3(hdc);
1104
1105         if(strstr(wgl_extensions, "WGL_ARB_make_current_read"))
1106             test_make_current_read(hdc);
1107         else
1108             skip("WGL_ARB_make_current_read not supported, skipping test\n");
1109
1110         if(strstr(wgl_extensions, "WGL_ARB_pbuffer"))
1111             test_pbuffers(hdc);
1112         else
1113             skip("WGL_ARB_pbuffer not supported, skipping pbuffer test\n");
1114
1115 cleanup:
1116         ReleaseDC(hwnd, hdc);
1117         DestroyWindow(hwnd);
1118     }
1119 }