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