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