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