st-api: Clean-up OpenGL profile handling
[mesa.git] / src / gallium / state_trackers / wgl / stw_context.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <windows.h>
29
30 #define WGL_WGLEXT_PROTOTYPES
31
32 #include <GL/gl.h>
33 #include <GL/wglext.h>
34
35 #include "pipe/p_compiler.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_state.h"
38 #include "util/u_memory.h"
39 #include "util/u_atomic.h"
40 #include "state_tracker/st_api.h"
41
42 #include "stw_icd.h"
43 #include "stw_device.h"
44 #include "stw_winsys.h"
45 #include "stw_framebuffer.h"
46 #include "stw_pixelformat.h"
47 #include "stw_context.h"
48 #include "stw_tls.h"
49
50
51 static INLINE struct stw_context *
52 stw_current_context(void)
53 {
54 struct st_context_iface *st;
55
56 st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
57
58 return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
59 }
60
61 BOOL APIENTRY
62 DrvCopyContext(
63 DHGLRC dhrcSource,
64 DHGLRC dhrcDest,
65 UINT fuMask )
66 {
67 struct stw_context *src;
68 struct stw_context *dst;
69 BOOL ret = FALSE;
70
71 if (!stw_dev)
72 return FALSE;
73
74 pipe_mutex_lock( stw_dev->ctx_mutex );
75
76 src = stw_lookup_context_locked( dhrcSource );
77 dst = stw_lookup_context_locked( dhrcDest );
78
79 if (src && dst) {
80 /* FIXME */
81 assert(0);
82 (void) src;
83 (void) dst;
84 (void) fuMask;
85 }
86
87 pipe_mutex_unlock( stw_dev->ctx_mutex );
88
89 return ret;
90 }
91
92 BOOL APIENTRY
93 DrvShareLists(
94 DHGLRC dhglrc1,
95 DHGLRC dhglrc2 )
96 {
97 struct stw_context *ctx1;
98 struct stw_context *ctx2;
99 BOOL ret = FALSE;
100
101 if (!stw_dev)
102 return FALSE;
103
104 pipe_mutex_lock( stw_dev->ctx_mutex );
105
106 ctx1 = stw_lookup_context_locked( dhglrc1 );
107 ctx2 = stw_lookup_context_locked( dhglrc2 );
108
109 if (ctx1 && ctx2 && ctx2->st->share)
110 ret = ctx2->st->share(ctx2->st, ctx1->st);
111
112 pipe_mutex_unlock( stw_dev->ctx_mutex );
113
114 return ret;
115 }
116
117 DHGLRC APIENTRY
118 DrvCreateContext(
119 HDC hdc )
120 {
121 return DrvCreateLayerContext( hdc, 0 );
122 }
123
124 DHGLRC APIENTRY
125 DrvCreateLayerContext(
126 HDC hdc,
127 INT iLayerPlane )
128 {
129 return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
130 }
131
132 DHGLRC
133 stw_create_context_attribs(
134 HDC hdc,
135 INT iLayerPlane,
136 DHGLRC hShareContext,
137 int majorVersion, int minorVersion,
138 int contextFlags, int profileMask)
139 {
140 int iPixelFormat;
141 const struct stw_pixelformat_info *pfi;
142 struct st_context_attribs attribs;
143 struct stw_context *ctx = NULL;
144 struct stw_context *shareCtx = NULL;
145
146 if (!stw_dev)
147 return 0;
148
149 if (iLayerPlane != 0)
150 return 0;
151
152 iPixelFormat = GetPixelFormat(hdc);
153 if(!iPixelFormat)
154 return 0;
155
156 pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
157
158 if (hShareContext != 0) {
159 pipe_mutex_lock( stw_dev->ctx_mutex );
160 shareCtx = stw_lookup_context_locked( hShareContext );
161 pipe_mutex_unlock( stw_dev->ctx_mutex );
162 }
163
164 ctx = CALLOC_STRUCT( stw_context );
165 if (ctx == NULL)
166 goto no_ctx;
167
168 ctx->hdc = hdc;
169 ctx->iPixelFormat = iPixelFormat;
170
171 memset(&attribs, 0, sizeof(attribs));
172 attribs.visual = pfi->stvis;
173 attribs.major = majorVersion;
174 attribs.minor = minorVersion;
175 if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
176 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
177 if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
178 attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
179
180 /* There are no profiles before OpenGL 3.2. The
181 * WGL_ARB_create_context_profile spec says:
182 *
183 * "If the requested OpenGL version is less than 3.2,
184 * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the
185 * context is determined solely by the requested version."
186 *
187 * The spec also says:
188 *
189 * "The default value for WGL_CONTEXT_PROFILE_MASK_ARB is
190 * WGL_CONTEXT_CORE_PROFILE_BIT_ARB."
191 */
192 attribs.profile = ST_PROFILE_DEFAULT;
193 if ((major > 3 || (major == 3 && minor >= 2))
194 && ((profileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0))
195 attribs.profile = ST_PROFILE_OPENGL_CORE;
196
197 ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
198 stw_dev->smapi, &attribs, shareCtx ? shareCtx->st : NULL);
199 if (ctx->st == NULL)
200 goto no_st_ctx;
201
202 ctx->st->st_manager_private = (void *) ctx;
203
204 pipe_mutex_lock( stw_dev->ctx_mutex );
205 ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
206 pipe_mutex_unlock( stw_dev->ctx_mutex );
207 if (!ctx->dhglrc)
208 goto no_hglrc;
209
210 return ctx->dhglrc;
211
212 no_hglrc:
213 ctx->st->destroy(ctx->st);
214 no_st_ctx:
215 FREE(ctx);
216 no_ctx:
217 return 0;
218 }
219
220 BOOL APIENTRY
221 DrvDeleteContext(
222 DHGLRC dhglrc )
223 {
224 struct stw_context *ctx ;
225 BOOL ret = FALSE;
226
227 if (!stw_dev)
228 return FALSE;
229
230 pipe_mutex_lock( stw_dev->ctx_mutex );
231 ctx = stw_lookup_context_locked(dhglrc);
232 handle_table_remove(stw_dev->ctx_table, dhglrc);
233 pipe_mutex_unlock( stw_dev->ctx_mutex );
234
235 if (ctx) {
236 struct stw_context *curctx = stw_current_context();
237
238 /* Unbind current if deleting current context. */
239 if (curctx == ctx)
240 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
241
242 ctx->st->destroy(ctx->st);
243 FREE(ctx);
244
245 ret = TRUE;
246 }
247
248 return ret;
249 }
250
251 BOOL APIENTRY
252 DrvReleaseContext(
253 DHGLRC dhglrc )
254 {
255 struct stw_context *ctx;
256
257 if (!stw_dev)
258 return FALSE;
259
260 pipe_mutex_lock( stw_dev->ctx_mutex );
261 ctx = stw_lookup_context_locked( dhglrc );
262 pipe_mutex_unlock( stw_dev->ctx_mutex );
263
264 if (!ctx)
265 return FALSE;
266
267 /* The expectation is that ctx is the same context which is
268 * current for this thread. We should check that and return False
269 * if not the case.
270 */
271 if (ctx != stw_current_context())
272 return FALSE;
273
274 if (stw_make_current( NULL, 0 ) == FALSE)
275 return FALSE;
276
277 return TRUE;
278 }
279
280
281 DHGLRC
282 stw_get_current_context( void )
283 {
284 struct stw_context *ctx;
285
286 ctx = stw_current_context();
287 if(!ctx)
288 return 0;
289
290 return ctx->dhglrc;
291 }
292
293 HDC
294 stw_get_current_dc( void )
295 {
296 struct stw_context *ctx;
297
298 ctx = stw_current_context();
299 if(!ctx)
300 return NULL;
301
302 return ctx->hdc;
303 }
304
305 BOOL
306 stw_make_current(
307 HDC hdc,
308 DHGLRC dhglrc )
309 {
310 struct stw_context *curctx = NULL;
311 struct stw_context *ctx = NULL;
312 struct stw_framebuffer *fb = NULL;
313 BOOL ret = FALSE;
314
315 if (!stw_dev)
316 return FALSE;
317
318 curctx = stw_current_context();
319 if (curctx != NULL) {
320 if (curctx->dhglrc == dhglrc) {
321 if (curctx->hdc == hdc) {
322 /* Return if already current. */
323 return TRUE;
324 }
325 } else {
326 curctx->st->flush(curctx->st, ST_FLUSH_FRONT, NULL);
327 }
328 }
329
330 if (dhglrc) {
331 pipe_mutex_lock( stw_dev->ctx_mutex );
332 ctx = stw_lookup_context_locked( dhglrc );
333 pipe_mutex_unlock( stw_dev->ctx_mutex );
334 if (!ctx) {
335 goto fail;
336 }
337
338 fb = stw_framebuffer_from_hdc( hdc );
339 if (fb) {
340 stw_framebuffer_update(fb);
341 }
342 else {
343 /* Applications should call SetPixelFormat before creating a context,
344 * but not all do, and the opengl32 runtime seems to use a default pixel
345 * format in some cases, so we must create a framebuffer for those here
346 */
347 int iPixelFormat = GetPixelFormat(hdc);
348 if (iPixelFormat)
349 fb = stw_framebuffer_create( hdc, iPixelFormat );
350 if (!fb)
351 goto fail;
352 }
353
354 if (fb->iPixelFormat != ctx->iPixelFormat) {
355 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
356 goto fail;
357 }
358
359 /* Bind the new framebuffer */
360 ctx->hdc = hdc;
361
362 ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb);
363 stw_framebuffer_reference(&ctx->current_framebuffer, fb);
364 } else {
365 ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
366 }
367
368 fail:
369
370 if (fb) {
371 stw_framebuffer_release(fb);
372 }
373
374 /* On failure, make the thread's current rendering context not current
375 * before returning */
376 if (!ret) {
377 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
378 ctx = NULL;
379 }
380
381 /* Unreference the previous framebuffer if any. It must be done after
382 * make_current, as it can be referenced inside.
383 */
384 if (curctx && curctx != ctx) {
385 stw_framebuffer_reference(&curctx->current_framebuffer, NULL);
386 }
387
388 return ret;
389 }
390
391 /**
392 * Flush the current context if it is bound to the framebuffer.
393 */
394 void
395 stw_flush_current_locked( struct stw_framebuffer *fb )
396 {
397 struct stw_context *ctx = stw_current_context();
398
399 if (ctx && ctx->current_framebuffer == fb) {
400 ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
401 }
402 }
403
404 /**
405 * Notify the current context that the framebuffer has become invalid.
406 */
407 void
408 stw_notify_current_locked( struct stw_framebuffer *fb )
409 {
410 p_atomic_inc(&fb->stfb->stamp);
411 }
412
413 /**
414 * Although WGL allows different dispatch entrypoints per context
415 */
416 static const GLCLTPROCTABLE cpt =
417 {
418 OPENGL_VERSION_110_ENTRIES,
419 {
420 &glNewList,
421 &glEndList,
422 &glCallList,
423 &glCallLists,
424 &glDeleteLists,
425 &glGenLists,
426 &glListBase,
427 &glBegin,
428 &glBitmap,
429 &glColor3b,
430 &glColor3bv,
431 &glColor3d,
432 &glColor3dv,
433 &glColor3f,
434 &glColor3fv,
435 &glColor3i,
436 &glColor3iv,
437 &glColor3s,
438 &glColor3sv,
439 &glColor3ub,
440 &glColor3ubv,
441 &glColor3ui,
442 &glColor3uiv,
443 &glColor3us,
444 &glColor3usv,
445 &glColor4b,
446 &glColor4bv,
447 &glColor4d,
448 &glColor4dv,
449 &glColor4f,
450 &glColor4fv,
451 &glColor4i,
452 &glColor4iv,
453 &glColor4s,
454 &glColor4sv,
455 &glColor4ub,
456 &glColor4ubv,
457 &glColor4ui,
458 &glColor4uiv,
459 &glColor4us,
460 &glColor4usv,
461 &glEdgeFlag,
462 &glEdgeFlagv,
463 &glEnd,
464 &glIndexd,
465 &glIndexdv,
466 &glIndexf,
467 &glIndexfv,
468 &glIndexi,
469 &glIndexiv,
470 &glIndexs,
471 &glIndexsv,
472 &glNormal3b,
473 &glNormal3bv,
474 &glNormal3d,
475 &glNormal3dv,
476 &glNormal3f,
477 &glNormal3fv,
478 &glNormal3i,
479 &glNormal3iv,
480 &glNormal3s,
481 &glNormal3sv,
482 &glRasterPos2d,
483 &glRasterPos2dv,
484 &glRasterPos2f,
485 &glRasterPos2fv,
486 &glRasterPos2i,
487 &glRasterPos2iv,
488 &glRasterPos2s,
489 &glRasterPos2sv,
490 &glRasterPos3d,
491 &glRasterPos3dv,
492 &glRasterPos3f,
493 &glRasterPos3fv,
494 &glRasterPos3i,
495 &glRasterPos3iv,
496 &glRasterPos3s,
497 &glRasterPos3sv,
498 &glRasterPos4d,
499 &glRasterPos4dv,
500 &glRasterPos4f,
501 &glRasterPos4fv,
502 &glRasterPos4i,
503 &glRasterPos4iv,
504 &glRasterPos4s,
505 &glRasterPos4sv,
506 &glRectd,
507 &glRectdv,
508 &glRectf,
509 &glRectfv,
510 &glRecti,
511 &glRectiv,
512 &glRects,
513 &glRectsv,
514 &glTexCoord1d,
515 &glTexCoord1dv,
516 &glTexCoord1f,
517 &glTexCoord1fv,
518 &glTexCoord1i,
519 &glTexCoord1iv,
520 &glTexCoord1s,
521 &glTexCoord1sv,
522 &glTexCoord2d,
523 &glTexCoord2dv,
524 &glTexCoord2f,
525 &glTexCoord2fv,
526 &glTexCoord2i,
527 &glTexCoord2iv,
528 &glTexCoord2s,
529 &glTexCoord2sv,
530 &glTexCoord3d,
531 &glTexCoord3dv,
532 &glTexCoord3f,
533 &glTexCoord3fv,
534 &glTexCoord3i,
535 &glTexCoord3iv,
536 &glTexCoord3s,
537 &glTexCoord3sv,
538 &glTexCoord4d,
539 &glTexCoord4dv,
540 &glTexCoord4f,
541 &glTexCoord4fv,
542 &glTexCoord4i,
543 &glTexCoord4iv,
544 &glTexCoord4s,
545 &glTexCoord4sv,
546 &glVertex2d,
547 &glVertex2dv,
548 &glVertex2f,
549 &glVertex2fv,
550 &glVertex2i,
551 &glVertex2iv,
552 &glVertex2s,
553 &glVertex2sv,
554 &glVertex3d,
555 &glVertex3dv,
556 &glVertex3f,
557 &glVertex3fv,
558 &glVertex3i,
559 &glVertex3iv,
560 &glVertex3s,
561 &glVertex3sv,
562 &glVertex4d,
563 &glVertex4dv,
564 &glVertex4f,
565 &glVertex4fv,
566 &glVertex4i,
567 &glVertex4iv,
568 &glVertex4s,
569 &glVertex4sv,
570 &glClipPlane,
571 &glColorMaterial,
572 &glCullFace,
573 &glFogf,
574 &glFogfv,
575 &glFogi,
576 &glFogiv,
577 &glFrontFace,
578 &glHint,
579 &glLightf,
580 &glLightfv,
581 &glLighti,
582 &glLightiv,
583 &glLightModelf,
584 &glLightModelfv,
585 &glLightModeli,
586 &glLightModeliv,
587 &glLineStipple,
588 &glLineWidth,
589 &glMaterialf,
590 &glMaterialfv,
591 &glMateriali,
592 &glMaterialiv,
593 &glPointSize,
594 &glPolygonMode,
595 &glPolygonStipple,
596 &glScissor,
597 &glShadeModel,
598 &glTexParameterf,
599 &glTexParameterfv,
600 &glTexParameteri,
601 &glTexParameteriv,
602 &glTexImage1D,
603 &glTexImage2D,
604 &glTexEnvf,
605 &glTexEnvfv,
606 &glTexEnvi,
607 &glTexEnviv,
608 &glTexGend,
609 &glTexGendv,
610 &glTexGenf,
611 &glTexGenfv,
612 &glTexGeni,
613 &glTexGeniv,
614 &glFeedbackBuffer,
615 &glSelectBuffer,
616 &glRenderMode,
617 &glInitNames,
618 &glLoadName,
619 &glPassThrough,
620 &glPopName,
621 &glPushName,
622 &glDrawBuffer,
623 &glClear,
624 &glClearAccum,
625 &glClearIndex,
626 &glClearColor,
627 &glClearStencil,
628 &glClearDepth,
629 &glStencilMask,
630 &glColorMask,
631 &glDepthMask,
632 &glIndexMask,
633 &glAccum,
634 &glDisable,
635 &glEnable,
636 &glFinish,
637 &glFlush,
638 &glPopAttrib,
639 &glPushAttrib,
640 &glMap1d,
641 &glMap1f,
642 &glMap2d,
643 &glMap2f,
644 &glMapGrid1d,
645 &glMapGrid1f,
646 &glMapGrid2d,
647 &glMapGrid2f,
648 &glEvalCoord1d,
649 &glEvalCoord1dv,
650 &glEvalCoord1f,
651 &glEvalCoord1fv,
652 &glEvalCoord2d,
653 &glEvalCoord2dv,
654 &glEvalCoord2f,
655 &glEvalCoord2fv,
656 &glEvalMesh1,
657 &glEvalPoint1,
658 &glEvalMesh2,
659 &glEvalPoint2,
660 &glAlphaFunc,
661 &glBlendFunc,
662 &glLogicOp,
663 &glStencilFunc,
664 &glStencilOp,
665 &glDepthFunc,
666 &glPixelZoom,
667 &glPixelTransferf,
668 &glPixelTransferi,
669 &glPixelStoref,
670 &glPixelStorei,
671 &glPixelMapfv,
672 &glPixelMapuiv,
673 &glPixelMapusv,
674 &glReadBuffer,
675 &glCopyPixels,
676 &glReadPixels,
677 &glDrawPixels,
678 &glGetBooleanv,
679 &glGetClipPlane,
680 &glGetDoublev,
681 &glGetError,
682 &glGetFloatv,
683 &glGetIntegerv,
684 &glGetLightfv,
685 &glGetLightiv,
686 &glGetMapdv,
687 &glGetMapfv,
688 &glGetMapiv,
689 &glGetMaterialfv,
690 &glGetMaterialiv,
691 &glGetPixelMapfv,
692 &glGetPixelMapuiv,
693 &glGetPixelMapusv,
694 &glGetPolygonStipple,
695 &glGetString,
696 &glGetTexEnvfv,
697 &glGetTexEnviv,
698 &glGetTexGendv,
699 &glGetTexGenfv,
700 &glGetTexGeniv,
701 &glGetTexImage,
702 &glGetTexParameterfv,
703 &glGetTexParameteriv,
704 &glGetTexLevelParameterfv,
705 &glGetTexLevelParameteriv,
706 &glIsEnabled,
707 &glIsList,
708 &glDepthRange,
709 &glFrustum,
710 &glLoadIdentity,
711 &glLoadMatrixf,
712 &glLoadMatrixd,
713 &glMatrixMode,
714 &glMultMatrixf,
715 &glMultMatrixd,
716 &glOrtho,
717 &glPopMatrix,
718 &glPushMatrix,
719 &glRotated,
720 &glRotatef,
721 &glScaled,
722 &glScalef,
723 &glTranslated,
724 &glTranslatef,
725 &glViewport,
726 &glArrayElement,
727 &glBindTexture,
728 &glColorPointer,
729 &glDisableClientState,
730 &glDrawArrays,
731 &glDrawElements,
732 &glEdgeFlagPointer,
733 &glEnableClientState,
734 &glIndexPointer,
735 &glIndexub,
736 &glIndexubv,
737 &glInterleavedArrays,
738 &glNormalPointer,
739 &glPolygonOffset,
740 &glTexCoordPointer,
741 &glVertexPointer,
742 &glAreTexturesResident,
743 &glCopyTexImage1D,
744 &glCopyTexImage2D,
745 &glCopyTexSubImage1D,
746 &glCopyTexSubImage2D,
747 &glDeleteTextures,
748 &glGenTextures,
749 &glGetPointerv,
750 &glIsTexture,
751 &glPrioritizeTextures,
752 &glTexSubImage1D,
753 &glTexSubImage2D,
754 &glPopClientAttrib,
755 &glPushClientAttrib
756 }
757 };
758
759 PGLCLTPROCTABLE APIENTRY
760 DrvSetContext(
761 HDC hdc,
762 DHGLRC dhglrc,
763 PFN_SETPROCTABLE pfnSetProcTable )
764 {
765 PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
766
767 if (!stw_make_current( hdc, dhglrc ))
768 r = NULL;
769
770 return r;
771 }