Sync with trunk r63270.
[reactos.git] / dll / opengl / opengl32 / wgl.c
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 }