xref: /reactos/dll/opengl/opengl32/wgl.c (revision b819608e)
1 /*
2  * COPYRIGHT:            See COPYING in the top level directory
3  * PROJECT:              ReactOS
4  * FILE:                 dll/opengl/opengl32/wgl.c
5  * PURPOSE:              OpenGL32 DLL, WGL functions
6  */
7 
8 #include "opengl32.h"
9 
10 #include <pseh/pseh2.h>
11 
12 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
13 
14 static CRITICAL_SECTION dc_data_cs = {NULL, -1, 0, 0, 0, 0};
15 static struct wgl_dc_data* dc_data_list = NULL;
16 
17 /* FIXME: suboptimal */
18 static
19 struct wgl_dc_data*
20 get_dc_data(HDC hdc)
21 {
22     HWND hwnd = NULL;
23     struct wgl_dc_data* data;
24     DWORD objType = GetObjectType(hdc);
25     ULONG flags = 0;
26     union
27     {
28         HWND hwnd;
29         HDC hdc;
30         HANDLE u;
31     } id;
32 
33     /* Look for the right data identifier */
34     if(objType == OBJ_DC)
35     {
36         hwnd = WindowFromDC(hdc);
37         if(!hwnd)
38             return NULL;
39         id.hwnd = hwnd;
40         flags = WGL_DC_OBJ_DC;
41     }
42     else if(objType == OBJ_MEMDC)
43     {
44         id.hdc = hdc;
45     }
46     else
47     {
48         return NULL;
49     }
50 
51     EnterCriticalSection(&dc_data_cs);
52     data = dc_data_list;
53     while(data)
54     {
55         if(data->owner.u == id.u)
56         {
57             LeaveCriticalSection(&dc_data_cs);
58             return data;
59         }
60         data = data->next;
61     }
62     data= HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
63     if(!data)
64     {
65         LeaveCriticalSection(&dc_data_cs);
66         return NULL;
67     }
68     /* initialize the structure */
69     data->owner.u = id.u;
70     data->flags = flags;
71     data->pixelformat = 0;
72     data->sw_data = NULL;
73     /* Load the driver */
74     data->icd_data = IntGetIcdData(hdc);
75     /* Get the number of available formats for this DC once and for all */
76     if(data->icd_data)
77         data->nb_icd_formats = data->icd_data->DrvDescribePixelFormat(hdc, 0, 0, NULL);
78     else
79         data->nb_icd_formats = 0;
80     TRACE("ICD %S has %u formats for HDC %x.\n", data->icd_data->DriverName, data->nb_icd_formats, hdc);
81     data->nb_sw_formats = sw_DescribePixelFormat(hdc, 0, 0, NULL);
82     data->next = dc_data_list;
83     dc_data_list = data;
84     LeaveCriticalSection(&dc_data_cs);
85     return data;
86 }
87 
88 void release_dc_data(struct wgl_dc_data* dc_data)
89 {
90     (void)dc_data;
91 }
92 
93 struct wgl_context* get_context(HGLRC hglrc)
94 {
95     struct wgl_context* context = (struct wgl_context*)hglrc;
96 
97     if(!hglrc)
98         return NULL;
99 
100     _SEH2_TRY
101     {
102         if(context->magic != 'GLRC')
103             context = NULL;
104     }
105     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
106     {
107         context = NULL;
108     }
109     _SEH2_END;
110 
111     return context;
112 }
113 
114 INT WINAPI wglDescribePixelFormat(HDC hdc, INT format, UINT size, PIXELFORMATDESCRIPTOR *descr )
115 {
116     struct wgl_dc_data* dc_data = get_dc_data(hdc);
117     INT ret;
118 
119     if(!dc_data)
120     {
121         SetLastError(ERROR_INVALID_HANDLE);
122         return 0;
123     }
124 
125     ret = dc_data->nb_icd_formats + dc_data->nb_sw_formats;
126 
127     if(!descr)
128     {
129         release_dc_data(dc_data);
130         return ret;
131     }
132     if((format == 0) || (format > ret) || (size != sizeof(*descr)))
133     {
134         release_dc_data(dc_data);
135         SetLastError(ERROR_INVALID_PARAMETER);
136         return 0;
137     }
138 
139     /* Query ICD if needed */
140     if(format <= dc_data->nb_icd_formats)
141     {
142         if(!dc_data->icd_data->DrvDescribePixelFormat(hdc, format, size, descr))
143         {
144             ret = 0;
145         }
146     }
147     else
148     {
149         /* This is a software format */
150         format -= dc_data->nb_icd_formats;
151         if(!sw_DescribePixelFormat(hdc, format, size, descr))
152         {
153             ret = 0;
154         }
155     }
156 
157     release_dc_data(dc_data);
158     return ret;
159 }
160 
161 INT WINAPI wglChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd)
162 {
163     PIXELFORMATDESCRIPTOR format, best;
164     int i, count, best_format;
165     int bestDBuffer = -1, bestStereo = -1;
166 
167     TRACE_(wgl)( "%p %p: size %u version %u flags %u type %u color %u %u,%u,%u,%u "
168                  "accum %u depth %u stencil %u aux %u\n",
169                  hdc, ppfd, ppfd->nSize, ppfd->nVersion, ppfd->dwFlags, ppfd->iPixelType,
170                  ppfd->cColorBits, ppfd->cRedBits, ppfd->cGreenBits, ppfd->cBlueBits, ppfd->cAlphaBits,
171                  ppfd->cAccumBits, ppfd->cDepthBits, ppfd->cStencilBits, ppfd->cAuxBuffers );
172 
173     count = wglDescribePixelFormat( hdc, 0, 0, NULL );
174     if (!count) return 0;
175 
176     best_format = 0;
177     best.dwFlags = 0;
178     best.cAlphaBits = -1;
179     best.cColorBits = -1;
180     best.cDepthBits = -1;
181     best.cStencilBits = -1;
182     best.cAuxBuffers = -1;
183 
184     for (i = 1; i <= count; i++)
185     {
186         if (!wglDescribePixelFormat( hdc, i, sizeof(format), &format )) continue;
187 
188         if (ppfd->iPixelType != format.iPixelType)
189         {
190             TRACE( "pixel type mismatch for iPixelFormat=%d\n", i );
191             continue;
192         }
193 
194         /* only use bitmap capable formats for bitmap rendering */
195         if ((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) != (format.dwFlags & PFD_DRAW_TO_BITMAP))
196         {
197             TRACE( "PFD_DRAW_TO_BITMAP mismatch for iPixelFormat=%d\n", i );
198             continue;
199         }
200 
201         /* only use window capable formats for window rendering */
202         if ((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) != (format.dwFlags & PFD_DRAW_TO_WINDOW))
203         {
204             TRACE( "PFD_DRAW_TO_WINDOW mismatch for iPixelFormat=%d\n", i );
205             continue;
206         }
207 
208         /* only use opengl capable formats for opengl rendering */
209         if ((ppfd->dwFlags & PFD_SUPPORT_OPENGL) != (format.dwFlags & PFD_SUPPORT_OPENGL))
210         {
211             TRACE( "PFD_SUPPORT_OPENGL mismatch for iPixelFormat=%d\n", i );
212             continue;
213         }
214 
215         /* only use GDI capable formats for GDI rendering */
216         if ((ppfd->dwFlags & PFD_SUPPORT_GDI) != (format.dwFlags & PFD_SUPPORT_GDI))
217         {
218             TRACE( "PFD_SUPPORT_GDI mismatch for iPixelFormat=%d\n", i );
219             continue;
220         }
221 
222         /* The behavior of PDF_STEREO/PFD_STEREO_DONTCARE and PFD_DOUBLEBUFFER / PFD_DOUBLEBUFFER_DONTCARE
223          * is not very clear on MSDN. They specify that ChoosePixelFormat tries to match pixel formats
224          * with the flag (PFD_STEREO / PFD_DOUBLEBUFFERING) set. Otherwise it says that it tries to match
225          * formats without the given flag set.
226          * A test on Windows using a Radeon 9500pro on WinXP (the driver doesn't support Stereo)
227          * has indicated that a format without stereo is returned when stereo is unavailable.
228          * So in case PFD_STEREO is set, formats that support it should have priority above formats
229          * without. In case PFD_STEREO_DONTCARE is set, stereo is ignored.
230          *
231          * To summarize the following is most likely the correct behavior:
232          * stereo not set -> prefer non-stereo formats, but also accept stereo formats
233          * stereo set -> prefer stereo formats, but also accept non-stereo formats
234          * stereo don't care -> it doesn't matter whether we get stereo or not
235          *
236          * In Wine we will treat non-stereo the same way as don't care because it makes
237          * format selection even more complicated and second drivers with Stereo advertise
238          * each format twice anyway.
239          */
240 
241         /* Doublebuffer, see the comments above */
242         if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE))
243         {
244             if (((ppfd->dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) &&
245                 ((format.dwFlags & PFD_DOUBLEBUFFER) == (ppfd->dwFlags & PFD_DOUBLEBUFFER)))
246                 goto found;
247 
248             if (bestDBuffer != -1 && (format.dwFlags & PFD_DOUBLEBUFFER) != bestDBuffer) continue;
249         }
250 
251         /* Stereo, see the comments above. */
252         if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE))
253         {
254             if (((ppfd->dwFlags & PFD_STEREO) != bestStereo) &&
255                 ((format.dwFlags & PFD_STEREO) == (ppfd->dwFlags & PFD_STEREO)))
256                 goto found;
257 
258             if (bestStereo != -1 && (format.dwFlags & PFD_STEREO) != bestStereo) continue;
259         }
260 
261         /* Below we will do a number of checks to select the 'best' pixelformat.
262          * We assume the precedence cColorBits > cAlphaBits > cDepthBits > cStencilBits -> cAuxBuffers.
263          * The code works by trying to match the most important options as close as possible.
264          * When a reasonable format is found, we will try to match more options.
265          * It appears (see the opengl32 test) that Windows opengl drivers ignore options
266          * like cColorBits, cAlphaBits and friends if they are set to 0, so they are considered
267          * as DONTCARE. At least Serious Sam TSE relies on this behavior. */
268 
269         if (ppfd->cColorBits)
270         {
271             if (((ppfd->cColorBits > best.cColorBits) && (format.cColorBits > best.cColorBits)) ||
272                 ((format.cColorBits >= ppfd->cColorBits) && (format.cColorBits < best.cColorBits)))
273                 goto found;
274 
275             if (best.cColorBits != format.cColorBits)  /* Do further checks if the format is compatible */
276             {
277                 TRACE( "color mismatch for iPixelFormat=%d\n", i );
278                 continue;
279             }
280         }
281         if (ppfd->cAlphaBits)
282         {
283             if (((ppfd->cAlphaBits > best.cAlphaBits) && (format.cAlphaBits > best.cAlphaBits)) ||
284                 ((format.cAlphaBits >= ppfd->cAlphaBits) && (format.cAlphaBits < best.cAlphaBits)))
285                 goto found;
286 
287             if (best.cAlphaBits != format.cAlphaBits)
288             {
289                 TRACE( "alpha mismatch for iPixelFormat=%d\n", i );
290                 continue;
291             }
292         }
293         if (ppfd->cDepthBits)
294         {
295             if (((ppfd->cDepthBits > best.cDepthBits) && (format.cDepthBits > best.cDepthBits)) ||
296                 ((format.cDepthBits >= ppfd->cDepthBits) && (format.cDepthBits < best.cDepthBits)))
297                 goto found;
298 
299             if (best.cDepthBits != format.cDepthBits)
300             {
301                 TRACE( "depth mismatch for iPixelFormat=%d\n", i );
302                 continue;
303             }
304         }
305         if (ppfd->cStencilBits)
306         {
307             if (((ppfd->cStencilBits > best.cStencilBits) && (format.cStencilBits > best.cStencilBits)) ||
308                 ((format.cStencilBits >= ppfd->cStencilBits) && (format.cStencilBits < best.cStencilBits)))
309                 goto found;
310 
311             if (best.cStencilBits != format.cStencilBits)
312             {
313                 TRACE( "stencil mismatch for iPixelFormat=%d\n", i );
314                 continue;
315             }
316         }
317         if (ppfd->cAuxBuffers)
318         {
319             if (((ppfd->cAuxBuffers > best.cAuxBuffers) && (format.cAuxBuffers > best.cAuxBuffers)) ||
320                 ((format.cAuxBuffers >= ppfd->cAuxBuffers) && (format.cAuxBuffers < best.cAuxBuffers)))
321                 goto found;
322 
323             if (best.cAuxBuffers != format.cAuxBuffers)
324             {
325                 TRACE( "aux mismatch for iPixelFormat=%d\n", i );
326                 continue;
327             }
328         }
329         continue;
330 
331     found:
332         best_format = i;
333         best = format;
334         bestDBuffer = format.dwFlags & PFD_DOUBLEBUFFER;
335         bestStereo = format.dwFlags & PFD_STEREO;
336     }
337 
338     TRACE( "returning %u\n", best_format );
339     return best_format;
340 }
341 
342 BOOL WINAPI wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
343 {
344     struct wgl_context* ctx_src = get_context(hglrcSrc);
345     struct wgl_context* ctx_dst = get_context(hglrcDst);
346 
347     if(!ctx_src || !ctx_dst)
348     {
349         SetLastError(ERROR_INVALID_HANDLE);
350         return FALSE;
351     }
352 
353     /* Check this is the same pixel format */
354     if((ctx_dst->icd_data != ctx_src->icd_data) ||
355         (ctx_dst->pixelformat != ctx_src->pixelformat))
356     {
357         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
358         return FALSE;
359     }
360 
361     if(ctx_src->icd_data)
362         return ctx_src->icd_data->DrvCopyContext(ctx_src->dhglrc, ctx_dst->dhglrc, mask);
363 
364     return sw_CopyContext(ctx_src->dhglrc, ctx_dst->dhglrc, mask);
365 }
366 
367 HGLRC WINAPI wglCreateContext(HDC hdc)
368 {
369     struct wgl_dc_data* dc_data = get_dc_data(hdc);
370     struct wgl_context* context;
371     DHGLRC dhglrc;
372 
373     TRACE("Creating context for %p, format %i\n", hdc);
374 
375     if(!dc_data)
376     {
377         WARN("Not a DC handle!\n");
378         SetLastError(ERROR_INVALID_HANDLE);
379         return NULL;
380     }
381 
382     if(!dc_data->pixelformat)
383     {
384         WARN("Pixel format not set!\n");
385         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
386         return NULL;
387     }
388 
389     if(!dc_data->icd_data)
390     {
391         TRACE("Calling SW implementation.\n");
392         dhglrc = sw_CreateContext(dc_data);
393         TRACE("done\n");
394     }
395     else
396     {
397         TRACE("Calling ICD.\n");
398         dhglrc = dc_data->icd_data->DrvCreateContext(hdc);
399     }
400 
401     if(!dhglrc)
402     {
403         WARN("Failed!\n");
404         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
405         return NULL;
406     }
407 
408     context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
409     if(!context)
410     {
411         WARN("Failed to allocate a context!\n");
412         if(!dc_data->icd_data)
413             sw_DeleteContext(dhglrc);
414         else
415             dc_data->icd_data->DrvDeleteContext(dhglrc);
416         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
417         return NULL;
418     }
419     /* Copy info from the DC data */
420     context->dhglrc = dhglrc;
421     context->icd_data = dc_data->icd_data;
422     context->pixelformat = dc_data->pixelformat;
423     context->thread_id = 0;
424 
425     context->magic = 'GLRC';
426     TRACE("Success!\n");
427     return (HGLRC)context;
428 }
429 
430 HGLRC WINAPI wglCreateLayerContext(HDC hdc, int iLayerPlane)
431 {
432     struct wgl_dc_data* dc_data = get_dc_data(hdc);
433     struct wgl_context* context;
434     DHGLRC dhglrc;
435 
436     if(!dc_data)
437     {
438         SetLastError(ERROR_INVALID_HANDLE);
439         return NULL;
440     }
441 
442     if(!dc_data->pixelformat)
443     {
444         release_dc_data(dc_data);
445         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
446         return NULL;
447     }
448 
449     if(!dc_data->icd_data)
450     {
451         if(iLayerPlane != 0)
452         {
453             /* Not supported in SW implementation  */
454             release_dc_data(dc_data);
455             SetLastError(ERROR_INVALID_PIXEL_FORMAT);
456             return NULL;
457         }
458         dhglrc = sw_CreateContext(dc_data);
459     }
460     else
461     {
462         dhglrc = dc_data->icd_data->DrvCreateLayerContext(hdc, iLayerPlane);
463     }
464 
465     if(!dhglrc)
466     {
467         release_dc_data(dc_data);
468         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
469         return NULL;
470     }
471 
472     context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
473     if(!context)
474     {
475         if(!dc_data->icd_data)
476             sw_DeleteContext(dhglrc);
477         else
478             dc_data->icd_data->DrvDeleteContext(dhglrc);
479         release_dc_data(dc_data);
480         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
481         return NULL;
482     }
483     /* Copy info from the DC data */
484     context->dhglrc = dhglrc;
485     context->icd_data = dc_data->icd_data;
486     context->pixelformat = dc_data->pixelformat;
487     context->thread_id = 0;
488 
489     context->magic = 'GLRC';
490 
491     release_dc_data(dc_data);
492     return (HGLRC)context;
493 }
494 
495 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
496 {
497     struct wgl_context* context = get_context(hglrc);
498     LONG thread_id = GetCurrentThreadId();
499 
500     if(!context)
501     {
502         SetLastError(ERROR_INVALID_HANDLE);
503         return FALSE;
504     }
505 
506     /* Own this context before touching it */
507     if(InterlockedCompareExchange(&context->thread_id, thread_id, 0) != 0)
508     {
509         /* We can't delete a context current to another thread */
510         if(context->thread_id != thread_id)
511         {
512             SetLastError(ERROR_BUSY);
513             return FALSE;
514         }
515 
516         /* This is in our thread. Release and try again */
517         if(!wglMakeCurrent(NULL, NULL))
518             return FALSE;
519         return wglDeleteContext(hglrc);
520     }
521 
522     if(context->icd_data)
523         context->icd_data->DrvDeleteContext(context->dhglrc);
524     else
525         sw_DeleteContext(context->dhglrc);
526 
527     context->magic = 0;
528     HeapFree(GetProcessHeap(), 0, context);
529 
530     return TRUE;
531 }
532 
533 BOOL WINAPI wglDescribeLayerPlane(HDC hdc,
534                                   int iPixelFormat,
535                                   int iLayerPlane,
536                                   UINT nBytes,
537                                   LPLAYERPLANEDESCRIPTOR plpd)
538 {
539     struct wgl_dc_data* dc_data = get_dc_data(hdc);
540 
541     if(!dc_data)
542     {
543         SetLastError(ERROR_INVALID_HANDLE);
544         return FALSE;
545     }
546 
547     if(iPixelFormat <= dc_data->nb_icd_formats)
548         return dc_data->icd_data->DrvDescribeLayerPlane(hdc, iPixelFormat, iLayerPlane, nBytes, plpd);
549 
550     /* SW implementation doesn't support this */
551     return FALSE;
552 }
553 
554 HGLRC WINAPI wglGetCurrentContext(void)
555 {
556     return IntGetCurrentRC();
557 }
558 
559 HDC WINAPI wglGetCurrentDC(void)
560 {
561     return IntGetCurrentDC();
562 }
563 
564 PROC WINAPI wglGetDefaultProcAddress(LPCSTR lpszProc)
565 {
566     /* undocumented... */
567     return NULL;
568 }
569 
570 int WINAPI wglGetLayerPaletteEntries(HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF* pcr )
571 {
572     struct wgl_dc_data* dc_data = get_dc_data(hdc);
573 
574     if(!dc_data)
575     {
576         SetLastError(ERROR_INVALID_HANDLE);
577         return 0;
578     }
579 
580     if(!dc_data->pixelformat)
581     {
582         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
583         return 0;
584     }
585 
586     if(dc_data->icd_data)
587         return dc_data->icd_data->DrvGetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
588 
589     /* SW implementation doesn't support this */
590     return 0;
591 }
592 
593 INT WINAPI wglGetPixelFormat(HDC hdc)
594 {
595     INT ret;
596     struct wgl_dc_data* dc_data = get_dc_data(hdc);
597 
598     if(!dc_data)
599     {
600         SetLastError(ERROR_INVALID_HANDLE);
601         return 0;
602     }
603 
604     ret = dc_data->pixelformat;
605     release_dc_data(dc_data);
606     return ret;
607 }
608 
609 PROC WINAPI wglGetProcAddress(LPCSTR name)
610 {
611     struct wgl_context* context = get_context(IntGetCurrentRC());
612     if(!context)
613         return NULL;
614 
615     /* This shall fail for opengl 1.1 functions */
616 #define USE_GL_FUNC(func, w, x, y, z) if(!strcmp(name, "gl" #func)) return NULL;
617 #include "glfuncs.h"
618 
619     /* Forward */
620     if(context->icd_data)
621         return context->icd_data->DrvGetProcAddress(name);
622     return sw_GetProcAddress(name);
623 }
624 
625 void APIENTRY set_api_table(const GLCLTPROCTABLE* table)
626 {
627     IntSetCurrentDispatchTable(&table->glDispatchTable);
628 }
629 
630 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
631 {
632     struct wgl_context* ctx = get_context(hglrc);
633     struct wgl_context* old_ctx = get_context(IntGetCurrentRC());
634     const GLCLTPROCTABLE* apiTable;
635     LONG thread_id = (LONG)GetCurrentThreadId();
636 
637     if(ctx)
638     {
639         struct wgl_dc_data* dc_data = get_dc_data(hdc);
640         if(!dc_data)
641         {
642             ERR("wglMakeCurrent was passed an invalid DC handle.\n");
643             SetLastError(ERROR_INVALID_HANDLE);
644             return FALSE;
645         }
646 
647         /* Check compatibility */
648         if((ctx->icd_data != dc_data->icd_data) || (ctx->pixelformat != dc_data->pixelformat))
649         {
650             /* That's bad, man */
651             ERR("HGLRC %p and HDC %p are not compatible.\n", hglrc, hdc);
652             release_dc_data(dc_data);
653             SetLastError(ERROR_INVALID_HANDLE);
654             return FALSE;
655         }
656 
657         /* Set the thread ID */
658         if(InterlockedCompareExchange(&ctx->thread_id, thread_id, 0) != 0)
659         {
660             /* Already current for a thread. Maybe it's us ? */
661             release_dc_data(dc_data);
662             if(ctx->thread_id != thread_id)
663                 SetLastError(ERROR_BUSY);
664             return (ctx->thread_id == thread_id);
665         }
666 
667         if(old_ctx)
668         {
669             /* Unset it */
670             if(old_ctx->icd_data)
671                 old_ctx->icd_data->DrvReleaseContext(old_ctx->dhglrc);
672             else
673                 sw_ReleaseContext(old_ctx->dhglrc);
674             InterlockedExchange(&old_ctx->thread_id, 0);
675         }
676 
677         /* Call the ICD or SW implementation */
678         if(ctx->icd_data)
679         {
680             apiTable = ctx->icd_data->DrvSetContext(hdc, ctx->dhglrc, set_api_table);
681             if(!apiTable)
682             {
683                 ERR("DrvSetContext failed!\n");
684                 /* revert */
685                 InterlockedExchange(&ctx->thread_id, 0);
686                 IntSetCurrentDispatchTable(&StubTable.glDispatchTable);
687                 SetLastError(ERROR_INVALID_PARAMETER);
688                 return FALSE;
689             }
690             set_api_table(apiTable);
691             /* Make it current */
692             IntMakeCurrent(hglrc, hdc, dc_data);
693         }
694         else
695         {
696             /* We must set current before, SW implementation relies on it */
697             IntMakeCurrent(hglrc, hdc, dc_data);
698             if(!sw_SetContext(dc_data, ctx->dhglrc))
699             {
700                 ERR("sw_SetContext failed!\n");
701                 /* revert */
702                 IntMakeCurrent(NULL, NULL, NULL);
703                 InterlockedExchange(&ctx->thread_id, 0);
704                 SetLastError(ERROR_INVALID_PARAMETER);
705                 return FALSE;
706             }
707         }
708     }
709     else if(old_ctx)
710     {
711         if(old_ctx->icd_data)
712             old_ctx->icd_data->DrvReleaseContext(old_ctx->dhglrc);
713         else
714             sw_ReleaseContext(old_ctx->dhglrc);
715         InterlockedExchange(&old_ctx->thread_id, 0);
716         /* Unset it */
717         IntMakeCurrent(NULL, NULL, NULL);
718         /* Reset the no-op table */
719         set_api_table(&StubTable);
720         /* Test conformance (extreme cases) */
721         return hglrc == NULL;
722     }
723     else
724     {
725         /* Winetest conformance */
726         if (GetObjectType( hdc ) != OBJ_DC && GetObjectType( hdc ) != OBJ_MEMDC)
727         {
728             ERR( "Error: hdc is not a DC handle!\n");
729             SetLastError( ERROR_INVALID_HANDLE );
730             return FALSE;
731         }
732     }
733 
734     return TRUE;
735 }
736 
737 BOOL WINAPI wglRealizeLayerPalette(HDC hdc,
738                                    int iLayerPlane,
739                                    BOOL bRealize)
740 {
741     struct wgl_dc_data* dc_data = get_dc_data(hdc);
742 
743     if(!dc_data)
744     {
745         SetLastError(ERROR_INVALID_HANDLE);
746         return FALSE;
747     }
748 
749     if(!dc_data->pixelformat)
750     {
751         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
752         return FALSE;
753     }
754 
755     if(dc_data->icd_data)
756         return dc_data->icd_data->DrvRealizeLayerPalette(hdc, iLayerPlane, bRealize);
757 
758     /* SW implementation doesn't support this */
759     return FALSE;
760 }
761 
762 int WINAPI wglSetLayerPaletteEntries(HDC hdc,
763                                      int iLayerPlane,
764                                      int iStart,
765                                      int cEntries,
766                                      const COLORREF *pcr)
767 {
768     struct wgl_dc_data* dc_data = get_dc_data(hdc);
769 
770     if(!dc_data)
771     {
772         SetLastError(ERROR_INVALID_HANDLE);
773         return 0;
774     }
775 
776     if(!dc_data->pixelformat)
777     {
778         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
779         return 0;
780     }
781 
782     if(dc_data->icd_data)
783         return dc_data->icd_data->DrvSetLayerPaletteEntries(hdc, iLayerPlane, iStart, cEntries, pcr);
784 
785     /* SW implementation doesn't support this */
786     return 0;
787 }
788 
789 BOOL WINAPI wglSetPixelFormat(HDC hdc, INT format, const PIXELFORMATDESCRIPTOR *descr)
790 {
791     struct wgl_dc_data* dc_data = get_dc_data(hdc);
792     INT sw_format;
793     BOOL ret;
794 
795     TRACE("HDC %p, format %i.\n", hdc, format);
796 
797     if(!dc_data)
798     {
799         WARN("Not a valid DC!.\n");
800         SetLastError(ERROR_INVALID_HANDLE);
801         return FALSE;
802     }
803 
804     if(!format)
805     {
806         WARN("format == 0!\n");
807         SetLastError(ERROR_INVALID_PARAMETER);
808         return FALSE;
809     }
810 
811     if(dc_data->pixelformat)
812     {
813         TRACE("DC format already set, %i.\n", dc_data->pixelformat);
814         return (format == dc_data->pixelformat);
815     }
816 
817     if(format <= dc_data->nb_icd_formats)
818     {
819         TRACE("Calling ICD.\n");
820         ret = dc_data->icd_data->DrvSetPixelFormat(hdc, format);
821         if(ret)
822         {
823             TRACE("Success!\n");
824             dc_data->pixelformat = format;
825         }
826         return ret;
827     }
828 
829     sw_format = format - dc_data->nb_icd_formats;
830     if(sw_format <= dc_data->nb_sw_formats)
831     {
832         TRACE("Calling SW implementation.\n");
833         ret = sw_SetPixelFormat(hdc, dc_data, sw_format);
834         if(ret)
835         {
836             TRACE("Success!\n");
837             /* This is now officially a software-only HDC */
838             dc_data->icd_data = NULL;
839             dc_data->pixelformat = format;
840         }
841         return ret;
842     }
843 
844     TRACE("Invalid pixel format!\n");
845     SetLastError(ERROR_INVALID_PARAMETER);
846     return FALSE;
847 }
848 
849 BOOL WINAPI wglShareLists(HGLRC hglrcSrc, HGLRC hglrcDst)
850 {
851     struct wgl_context* ctx_src = get_context(hglrcSrc);
852     struct wgl_context* ctx_dst = get_context(hglrcDst);
853 
854     if(!ctx_src || !ctx_dst)
855     {
856         SetLastError(ERROR_INVALID_HANDLE);
857         return FALSE;
858     }
859 
860     /* Check this is the same pixel format */
861     if((ctx_dst->icd_data != ctx_src->icd_data) ||
862         (ctx_dst->pixelformat != ctx_src->pixelformat))
863     {
864         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
865         return FALSE;
866     }
867 
868     if(ctx_src->icd_data)
869         return ctx_src->icd_data->DrvShareLists(ctx_src->dhglrc, ctx_dst->dhglrc);
870 
871     return sw_ShareLists(ctx_src->dhglrc, ctx_dst->dhglrc);
872 }
873 
874 BOOL WINAPI DECLSPEC_HOTPATCH wglSwapBuffers(HDC hdc)
875 {
876     struct wgl_dc_data* dc_data = get_dc_data(hdc);
877 
878     if(!dc_data)
879     {
880         SetLastError(ERROR_INVALID_HANDLE);
881         return FALSE;
882     }
883 
884     if(!dc_data->pixelformat)
885     {
886         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
887         return FALSE;
888     }
889 
890     if(dc_data->icd_data)
891         return dc_data->icd_data->DrvSwapBuffers(hdc);
892 
893     return sw_SwapBuffers(hdc, dc_data);
894 }
895 
896 BOOL WINAPI wglSwapLayerBuffers(HDC hdc, UINT fuPlanes)
897 {
898     return FALSE;
899 }
900 
901 DWORD WINAPI wglSwapMultipleBuffers(UINT count, CONST WGLSWAP * toSwap)
902 {
903     return 0;
904 }
905