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