• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2008 VMware, Inc.
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 VMWARE 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 "frontend/api.h"
41 #include "hud/hud_context.h"
42 
43 #include "gldrv.h"
44 #include "stw_device.h"
45 #include "stw_winsys.h"
46 #include "stw_framebuffer.h"
47 #include "stw_pixelformat.h"
48 #include "stw_context.h"
49 #include "stw_tls.h"
50 
51 
52 struct stw_context *
stw_current_context(void)53 stw_current_context(void)
54 {
55    struct st_context_iface *st;
56 
57    st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
58 
59    return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
60 }
61 
62 
63 BOOL APIENTRY
DrvCopyContext(DHGLRC dhrcSource,DHGLRC dhrcDest,UINT fuMask)64 DrvCopyContext(DHGLRC dhrcSource, DHGLRC dhrcDest, UINT fuMask)
65 {
66    struct stw_context *src;
67    struct stw_context *dst;
68    BOOL ret = FALSE;
69 
70    if (!stw_dev)
71       return FALSE;
72 
73    stw_lock_contexts(stw_dev);
74 
75    src = stw_lookup_context_locked( dhrcSource );
76    dst = stw_lookup_context_locked( dhrcDest );
77 
78    if (src && dst) {
79       /* FIXME */
80       assert(0);
81       (void) src;
82       (void) dst;
83       (void) fuMask;
84    }
85 
86    stw_unlock_contexts(stw_dev);
87 
88    return ret;
89 }
90 
91 
92 BOOL APIENTRY
DrvShareLists(DHGLRC dhglrc1,DHGLRC dhglrc2)93 DrvShareLists(DHGLRC dhglrc1, DHGLRC dhglrc2)
94 {
95    struct stw_context *ctx1;
96    struct stw_context *ctx2;
97    BOOL ret = FALSE;
98 
99    if (!stw_dev)
100       return FALSE;
101 
102    stw_lock_contexts(stw_dev);
103 
104    ctx1 = stw_lookup_context_locked( dhglrc1 );
105    ctx2 = stw_lookup_context_locked( dhglrc2 );
106 
107    if (ctx1 && ctx2 && ctx2->st->share) {
108       ret = ctx2->st->share(ctx2->st, ctx1->st);
109       ctx1->shared = TRUE;
110       ctx2->shared = TRUE;
111    }
112 
113    stw_unlock_contexts(stw_dev);
114 
115    return ret;
116 }
117 
118 
119 DHGLRC APIENTRY
DrvCreateContext(HDC hdc)120 DrvCreateContext(HDC hdc)
121 {
122    return DrvCreateLayerContext( hdc, 0 );
123 }
124 
125 
126 DHGLRC APIENTRY
DrvCreateLayerContext(HDC hdc,INT iLayerPlane)127 DrvCreateLayerContext(HDC hdc, INT iLayerPlane)
128 {
129    return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0,
130                                      WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
131                                      0);
132 }
133 
134 
135 /**
136  * Return the stw pixel format that most closely matches the pixel format
137  * on HDC.
138  * Used to get a pixel format when SetPixelFormat() hasn't been called before.
139  */
140 static int
get_matching_pixel_format(HDC hdc)141 get_matching_pixel_format(HDC hdc)
142 {
143    int iPixelFormat = GetPixelFormat(hdc);
144    PIXELFORMATDESCRIPTOR pfd;
145 
146    if (!iPixelFormat)
147       return 0;
148    if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd))
149       return 0;
150    return stw_pixelformat_choose(hdc, &pfd);
151 }
152 
153 
154 /**
155  * Called via DrvCreateContext(), DrvCreateLayerContext() and
156  * wglCreateContextAttribsARB() to actually create a rendering context.
157  * \param handle  the desired DHGLRC handle to use for the context, or zero
158  *                if a new handle should be allocated.
159  * \return the handle for the new context or zero if there was a problem.
160  */
161 DHGLRC
stw_create_context_attribs(HDC hdc,INT iLayerPlane,DHGLRC hShareContext,int majorVersion,int minorVersion,int contextFlags,int profileMask,DHGLRC handle)162 stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext,
163                            int majorVersion, int minorVersion,
164                            int contextFlags, int profileMask,
165                            DHGLRC handle)
166 {
167    int iPixelFormat;
168    struct stw_framebuffer *fb;
169    const struct stw_pixelformat_info *pfi;
170    struct st_context_attribs attribs;
171    struct stw_context *ctx = NULL;
172    struct stw_context *shareCtx = NULL;
173    enum st_context_error ctx_err = 0;
174 
175    if (!stw_dev)
176       return 0;
177 
178    if (iLayerPlane != 0)
179       return 0;
180 
181    /*
182     * GDI only knows about displayable pixel formats, so determine the pixel
183     * format from the framebuffer.
184     *
185     * This also allows to use a OpenGL DLL / ICD without installing.
186     */
187    fb = stw_framebuffer_from_hdc( hdc );
188    if (fb) {
189       iPixelFormat = fb->iPixelFormat;
190       stw_framebuffer_unlock(fb);
191    } else {
192       /* Applications should call SetPixelFormat before creating a context,
193        * but not all do, and the opengl32 runtime seems to use a default
194        * pixel format in some cases, so use that.
195        */
196       iPixelFormat = get_matching_pixel_format(hdc);
197       if (!iPixelFormat)
198          return 0;
199    }
200 
201    pfi = stw_pixelformat_get_info( iPixelFormat );
202 
203    if (hShareContext != 0) {
204       stw_lock_contexts(stw_dev);
205       shareCtx = stw_lookup_context_locked( hShareContext );
206       shareCtx->shared = TRUE;
207       stw_unlock_contexts(stw_dev);
208    }
209 
210    ctx = CALLOC_STRUCT( stw_context );
211    if (ctx == NULL)
212       goto no_ctx;
213 
214    ctx->hDrawDC = hdc;
215    ctx->hReadDC = hdc;
216    ctx->iPixelFormat = iPixelFormat;
217    ctx->shared = shareCtx != NULL;
218 
219    memset(&attribs, 0, sizeof(attribs));
220    attribs.visual = pfi->stvis;
221    attribs.major = majorVersion;
222    attribs.minor = minorVersion;
223    if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
224       attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
225    if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
226       attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
227 
228    switch (profileMask) {
229    case WGL_CONTEXT_CORE_PROFILE_BIT_ARB:
230       /* There are no profiles before OpenGL 3.2.  The
231        * WGL_ARB_create_context_profile spec says:
232        *
233        *     "If the requested OpenGL version is less than 3.2,
234        *     WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
235        *     of the context is determined solely by the requested version."
236        */
237       if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) {
238          attribs.profile = ST_PROFILE_OPENGL_CORE;
239          break;
240       }
241       /* fall-through */
242    case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
243       /*
244        * The spec also says:
245        *
246        *     "If version 3.1 is requested, the context returned may implement
247        *     any of the following versions:
248        *
249        *       * Version 3.1. The GL_ARB_compatibility extension may or may not
250        *         be implemented, as determined by the implementation.
251        *       * The core profile of version 3.2 or greater."
252        *
253        * But Mesa doesn't support GL_ARB_compatibility, while most prevalent
254        * Windows OpenGL implementations do, and unfortunately many Windows
255        * applications don't check whether they receive or not a context with
256        * GL_ARB_compatibility, so returning a core profile here does more harm
257        * than good.
258        */
259       attribs.profile = ST_PROFILE_DEFAULT;
260       break;
261    case WGL_CONTEXT_ES_PROFILE_BIT_EXT:
262       if (majorVersion >= 2) {
263          attribs.profile = ST_PROFILE_OPENGL_ES2;
264       } else {
265          attribs.profile = ST_PROFILE_OPENGL_ES1;
266       }
267       break;
268    default:
269       assert(0);
270       goto no_st_ctx;
271    }
272 
273    ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
274          stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
275    if (ctx->st == NULL)
276       goto no_st_ctx;
277 
278    ctx->st->st_manager_private = (void *) ctx;
279 
280    if (ctx->st->cso_context) {
281       ctx->hud = hud_create(ctx->st->cso_context, NULL);
282    }
283 
284    stw_lock_contexts(stw_dev);
285    if (handle) {
286       /* We're replacing the context data for this handle. See the
287        * wglCreateContextAttribsARB() function.
288        */
289       struct stw_context *old_ctx =
290          stw_lookup_context_locked((unsigned) handle);
291       if (old_ctx) {
292          /* free the old context data associated with this handle */
293          if (old_ctx->hud) {
294             hud_destroy(old_ctx->hud, NULL);
295          }
296          ctx->st->destroy(old_ctx->st);
297          FREE(old_ctx);
298       }
299 
300       /* replace table entry */
301       handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx);
302    }
303    else {
304       /* create new table entry */
305       handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx);
306    }
307 
308    ctx->dhglrc = handle;
309 
310    stw_unlock_contexts(stw_dev);
311 
312    if (!ctx->dhglrc)
313       goto no_hglrc;
314 
315    return ctx->dhglrc;
316 
317 no_hglrc:
318    if (ctx->hud) {
319       hud_destroy(ctx->hud, NULL);
320    }
321    ctx->st->destroy(ctx->st);
322 no_st_ctx:
323    FREE(ctx);
324 no_ctx:
325    return 0;
326 }
327 
328 
329 BOOL APIENTRY
DrvDeleteContext(DHGLRC dhglrc)330 DrvDeleteContext(DHGLRC dhglrc)
331 {
332    struct stw_context *ctx ;
333    BOOL ret = FALSE;
334 
335    if (!stw_dev)
336       return FALSE;
337 
338    stw_lock_contexts(stw_dev);
339    ctx = stw_lookup_context_locked(dhglrc);
340    handle_table_remove(stw_dev->ctx_table, dhglrc);
341    stw_unlock_contexts(stw_dev);
342 
343    if (ctx) {
344       struct stw_context *curctx = stw_current_context();
345 
346       /* Unbind current if deleting current context. */
347       if (curctx == ctx)
348          stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
349 
350       if (ctx->hud) {
351          hud_destroy(ctx->hud, NULL);
352       }
353 
354       ctx->st->destroy(ctx->st);
355       FREE(ctx);
356 
357       ret = TRUE;
358    }
359 
360    return ret;
361 }
362 
363 
364 BOOL APIENTRY
DrvReleaseContext(DHGLRC dhglrc)365 DrvReleaseContext(DHGLRC dhglrc)
366 {
367    struct stw_context *ctx;
368 
369    if (!stw_dev)
370       return FALSE;
371 
372    stw_lock_contexts(stw_dev);
373    ctx = stw_lookup_context_locked( dhglrc );
374    stw_unlock_contexts(stw_dev);
375 
376    if (!ctx)
377       return FALSE;
378 
379    /* The expectation is that ctx is the same context which is
380     * current for this thread.  We should check that and return False
381     * if not the case.
382     */
383    if (ctx != stw_current_context())
384       return FALSE;
385 
386    if (stw_make_current( NULL, NULL, 0 ) == FALSE)
387       return FALSE;
388 
389    return TRUE;
390 }
391 
392 
393 DHGLRC
stw_get_current_context(void)394 stw_get_current_context( void )
395 {
396    struct stw_context *ctx;
397 
398    ctx = stw_current_context();
399    if (!ctx)
400       return 0;
401 
402    return ctx->dhglrc;
403 }
404 
405 
406 HDC
stw_get_current_dc(void)407 stw_get_current_dc( void )
408 {
409    struct stw_context *ctx;
410 
411    ctx = stw_current_context();
412    if (!ctx)
413       return NULL;
414 
415    return ctx->hDrawDC;
416 }
417 
418 HDC
stw_get_current_read_dc(void)419 stw_get_current_read_dc( void )
420 {
421    struct stw_context *ctx;
422 
423    ctx = stw_current_context();
424    if (!ctx)
425       return NULL;
426 
427    return ctx->hReadDC;
428 }
429 
430 BOOL
stw_make_current(HDC hDrawDC,HDC hReadDC,DHGLRC dhglrc)431 stw_make_current(HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc)
432 {
433    struct stw_context *old_ctx = NULL;
434    struct stw_context *ctx = NULL;
435    BOOL ret = FALSE;
436 
437    if (!stw_dev)
438       return FALSE;
439 
440    old_ctx = stw_current_context();
441    if (old_ctx != NULL) {
442       if (old_ctx->dhglrc == dhglrc) {
443          if (old_ctx->hDrawDC == hDrawDC && old_ctx->hReadDC == hReadDC) {
444             /* Return if already current. */
445             return TRUE;
446          }
447       } else {
448          if (old_ctx->shared) {
449             struct pipe_fence_handle *fence = NULL;
450             old_ctx->st->flush(old_ctx->st,
451                                ST_FLUSH_FRONT | ST_FLUSH_WAIT, &fence,
452                                NULL, NULL);
453          }
454          else {
455             old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
456          }
457       }
458    }
459 
460    if (dhglrc) {
461       struct stw_framebuffer *fb = NULL;
462       struct stw_framebuffer *fbRead = NULL;
463       stw_lock_contexts(stw_dev);
464       ctx = stw_lookup_context_locked( dhglrc );
465       stw_unlock_contexts(stw_dev);
466       if (!ctx) {
467          goto fail;
468       }
469 
470       /* This call locks fb's mutex */
471       fb = stw_framebuffer_from_hdc( hDrawDC );
472       if (fb) {
473          stw_framebuffer_update(fb);
474       }
475       else {
476          /* Applications should call SetPixelFormat before creating a context,
477           * but not all do, and the opengl32 runtime seems to use a default
478           * pixel format in some cases, so we must create a framebuffer for
479           * those here.
480           */
481          int iPixelFormat = get_matching_pixel_format(hDrawDC);
482          if (iPixelFormat)
483             fb = stw_framebuffer_create( hDrawDC, iPixelFormat );
484          if (!fb)
485             goto fail;
486       }
487 
488       if (fb->iPixelFormat != ctx->iPixelFormat) {
489          stw_framebuffer_unlock(fb);
490          SetLastError(ERROR_INVALID_PIXEL_FORMAT);
491          goto fail;
492       }
493 
494       /* Bind the new framebuffer */
495       ctx->hDrawDC = hDrawDC;
496       ctx->hReadDC = hReadDC;
497 
498       struct stw_framebuffer *old_fb = ctx->current_framebuffer;
499       if (old_fb != fb) {
500          stw_framebuffer_reference_locked(fb);
501          ctx->current_framebuffer = fb;
502       }
503       stw_framebuffer_unlock(fb);
504 
505       if (hReadDC) {
506          if (hReadDC == hDrawDC) {
507             fbRead = fb;
508          }
509          else {
510             fbRead = stw_framebuffer_from_hdc( hReadDC );
511 
512             if (fbRead) {
513                stw_framebuffer_update(fbRead);
514             }
515             else {
516                /* Applications should call SetPixelFormat before creating a
517                 * context, but not all do, and the opengl32 runtime seems to
518                 * use a default pixel format in some cases, so we must create
519                 * a framebuffer for those here.
520                 */
521                int iPixelFormat = GetPixelFormat(hReadDC);
522                if (iPixelFormat)
523                   fbRead = stw_framebuffer_create( hReadDC, iPixelFormat );
524                if (!fbRead)
525                   goto fail;
526             }
527 
528             if (fbRead->iPixelFormat != ctx->iPixelFormat) {
529                stw_framebuffer_unlock(fbRead);
530                SetLastError(ERROR_INVALID_PIXEL_FORMAT);
531                goto fail;
532             }
533             stw_framebuffer_unlock(fbRead);
534          }
535          ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
536                                             fb->stfb, fbRead->stfb);
537       }
538       else {
539          /* Note: when we call this function we will wind up in the
540           * stw_st_framebuffer_validate_locked() function which will incur
541           * a recursive fb->mutex lock.
542           */
543          ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
544                                             fb->stfb, fb->stfb);
545       }
546 
547       if (old_fb && old_fb != fb) {
548          stw_lock_framebuffers(stw_dev);
549          stw_framebuffer_lock(old_fb);
550          stw_framebuffer_release_locked(old_fb);
551          stw_unlock_framebuffers(stw_dev);
552       }
553 
554 fail:
555       if (fb) {
556          /* fb must be unlocked at this point. */
557          assert(!stw_own_mutex(&fb->mutex));
558       }
559 
560       /* On failure, make the thread's current rendering context not current
561        * before returning.
562        */
563       if (!ret) {
564          stw_make_current(NULL, NULL, 0);
565       }
566    } else {
567       ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
568    }
569 
570    /* Unreference the previous framebuffer if any. It must be done after
571     * make_current, as it can be referenced inside.
572     */
573    if (old_ctx && old_ctx != ctx) {
574       struct stw_framebuffer *old_fb = old_ctx->current_framebuffer;
575       if (old_fb) {
576          old_ctx->current_framebuffer = NULL;
577          stw_lock_framebuffers(stw_dev);
578          stw_framebuffer_lock(old_fb);
579          stw_framebuffer_release_locked(old_fb);
580          stw_unlock_framebuffers(stw_dev);
581       }
582    }
583 
584    return ret;
585 }
586 
587 
588 /**
589  * Notify the current context that the framebuffer has become invalid.
590  */
591 void
stw_notify_current_locked(struct stw_framebuffer * fb)592 stw_notify_current_locked( struct stw_framebuffer *fb )
593 {
594    p_atomic_inc(&fb->stfb->stamp);
595 }
596 
597 
598 /**
599  * Although WGL allows different dispatch entrypoints per context
600  */
601 static const GLCLTPROCTABLE cpt =
602 {
603    OPENGL_VERSION_110_ENTRIES,
604    {
605       &glNewList,
606       &glEndList,
607       &glCallList,
608       &glCallLists,
609       &glDeleteLists,
610       &glGenLists,
611       &glListBase,
612       &glBegin,
613       &glBitmap,
614       &glColor3b,
615       &glColor3bv,
616       &glColor3d,
617       &glColor3dv,
618       &glColor3f,
619       &glColor3fv,
620       &glColor3i,
621       &glColor3iv,
622       &glColor3s,
623       &glColor3sv,
624       &glColor3ub,
625       &glColor3ubv,
626       &glColor3ui,
627       &glColor3uiv,
628       &glColor3us,
629       &glColor3usv,
630       &glColor4b,
631       &glColor4bv,
632       &glColor4d,
633       &glColor4dv,
634       &glColor4f,
635       &glColor4fv,
636       &glColor4i,
637       &glColor4iv,
638       &glColor4s,
639       &glColor4sv,
640       &glColor4ub,
641       &glColor4ubv,
642       &glColor4ui,
643       &glColor4uiv,
644       &glColor4us,
645       &glColor4usv,
646       &glEdgeFlag,
647       &glEdgeFlagv,
648       &glEnd,
649       &glIndexd,
650       &glIndexdv,
651       &glIndexf,
652       &glIndexfv,
653       &glIndexi,
654       &glIndexiv,
655       &glIndexs,
656       &glIndexsv,
657       &glNormal3b,
658       &glNormal3bv,
659       &glNormal3d,
660       &glNormal3dv,
661       &glNormal3f,
662       &glNormal3fv,
663       &glNormal3i,
664       &glNormal3iv,
665       &glNormal3s,
666       &glNormal3sv,
667       &glRasterPos2d,
668       &glRasterPos2dv,
669       &glRasterPos2f,
670       &glRasterPos2fv,
671       &glRasterPos2i,
672       &glRasterPos2iv,
673       &glRasterPos2s,
674       &glRasterPos2sv,
675       &glRasterPos3d,
676       &glRasterPos3dv,
677       &glRasterPos3f,
678       &glRasterPos3fv,
679       &glRasterPos3i,
680       &glRasterPos3iv,
681       &glRasterPos3s,
682       &glRasterPos3sv,
683       &glRasterPos4d,
684       &glRasterPos4dv,
685       &glRasterPos4f,
686       &glRasterPos4fv,
687       &glRasterPos4i,
688       &glRasterPos4iv,
689       &glRasterPos4s,
690       &glRasterPos4sv,
691       &glRectd,
692       &glRectdv,
693       &glRectf,
694       &glRectfv,
695       &glRecti,
696       &glRectiv,
697       &glRects,
698       &glRectsv,
699       &glTexCoord1d,
700       &glTexCoord1dv,
701       &glTexCoord1f,
702       &glTexCoord1fv,
703       &glTexCoord1i,
704       &glTexCoord1iv,
705       &glTexCoord1s,
706       &glTexCoord1sv,
707       &glTexCoord2d,
708       &glTexCoord2dv,
709       &glTexCoord2f,
710       &glTexCoord2fv,
711       &glTexCoord2i,
712       &glTexCoord2iv,
713       &glTexCoord2s,
714       &glTexCoord2sv,
715       &glTexCoord3d,
716       &glTexCoord3dv,
717       &glTexCoord3f,
718       &glTexCoord3fv,
719       &glTexCoord3i,
720       &glTexCoord3iv,
721       &glTexCoord3s,
722       &glTexCoord3sv,
723       &glTexCoord4d,
724       &glTexCoord4dv,
725       &glTexCoord4f,
726       &glTexCoord4fv,
727       &glTexCoord4i,
728       &glTexCoord4iv,
729       &glTexCoord4s,
730       &glTexCoord4sv,
731       &glVertex2d,
732       &glVertex2dv,
733       &glVertex2f,
734       &glVertex2fv,
735       &glVertex2i,
736       &glVertex2iv,
737       &glVertex2s,
738       &glVertex2sv,
739       &glVertex3d,
740       &glVertex3dv,
741       &glVertex3f,
742       &glVertex3fv,
743       &glVertex3i,
744       &glVertex3iv,
745       &glVertex3s,
746       &glVertex3sv,
747       &glVertex4d,
748       &glVertex4dv,
749       &glVertex4f,
750       &glVertex4fv,
751       &glVertex4i,
752       &glVertex4iv,
753       &glVertex4s,
754       &glVertex4sv,
755       &glClipPlane,
756       &glColorMaterial,
757       &glCullFace,
758       &glFogf,
759       &glFogfv,
760       &glFogi,
761       &glFogiv,
762       &glFrontFace,
763       &glHint,
764       &glLightf,
765       &glLightfv,
766       &glLighti,
767       &glLightiv,
768       &glLightModelf,
769       &glLightModelfv,
770       &glLightModeli,
771       &glLightModeliv,
772       &glLineStipple,
773       &glLineWidth,
774       &glMaterialf,
775       &glMaterialfv,
776       &glMateriali,
777       &glMaterialiv,
778       &glPointSize,
779       &glPolygonMode,
780       &glPolygonStipple,
781       &glScissor,
782       &glShadeModel,
783       &glTexParameterf,
784       &glTexParameterfv,
785       &glTexParameteri,
786       &glTexParameteriv,
787       &glTexImage1D,
788       &glTexImage2D,
789       &glTexEnvf,
790       &glTexEnvfv,
791       &glTexEnvi,
792       &glTexEnviv,
793       &glTexGend,
794       &glTexGendv,
795       &glTexGenf,
796       &glTexGenfv,
797       &glTexGeni,
798       &glTexGeniv,
799       &glFeedbackBuffer,
800       &glSelectBuffer,
801       &glRenderMode,
802       &glInitNames,
803       &glLoadName,
804       &glPassThrough,
805       &glPopName,
806       &glPushName,
807       &glDrawBuffer,
808       &glClear,
809       &glClearAccum,
810       &glClearIndex,
811       &glClearColor,
812       &glClearStencil,
813       &glClearDepth,
814       &glStencilMask,
815       &glColorMask,
816       &glDepthMask,
817       &glIndexMask,
818       &glAccum,
819       &glDisable,
820       &glEnable,
821       &glFinish,
822       &glFlush,
823       &glPopAttrib,
824       &glPushAttrib,
825       &glMap1d,
826       &glMap1f,
827       &glMap2d,
828       &glMap2f,
829       &glMapGrid1d,
830       &glMapGrid1f,
831       &glMapGrid2d,
832       &glMapGrid2f,
833       &glEvalCoord1d,
834       &glEvalCoord1dv,
835       &glEvalCoord1f,
836       &glEvalCoord1fv,
837       &glEvalCoord2d,
838       &glEvalCoord2dv,
839       &glEvalCoord2f,
840       &glEvalCoord2fv,
841       &glEvalMesh1,
842       &glEvalPoint1,
843       &glEvalMesh2,
844       &glEvalPoint2,
845       &glAlphaFunc,
846       &glBlendFunc,
847       &glLogicOp,
848       &glStencilFunc,
849       &glStencilOp,
850       &glDepthFunc,
851       &glPixelZoom,
852       &glPixelTransferf,
853       &glPixelTransferi,
854       &glPixelStoref,
855       &glPixelStorei,
856       &glPixelMapfv,
857       &glPixelMapuiv,
858       &glPixelMapusv,
859       &glReadBuffer,
860       &glCopyPixels,
861       &glReadPixels,
862       &glDrawPixels,
863       &glGetBooleanv,
864       &glGetClipPlane,
865       &glGetDoublev,
866       &glGetError,
867       &glGetFloatv,
868       &glGetIntegerv,
869       &glGetLightfv,
870       &glGetLightiv,
871       &glGetMapdv,
872       &glGetMapfv,
873       &glGetMapiv,
874       &glGetMaterialfv,
875       &glGetMaterialiv,
876       &glGetPixelMapfv,
877       &glGetPixelMapuiv,
878       &glGetPixelMapusv,
879       &glGetPolygonStipple,
880       &glGetString,
881       &glGetTexEnvfv,
882       &glGetTexEnviv,
883       &glGetTexGendv,
884       &glGetTexGenfv,
885       &glGetTexGeniv,
886       &glGetTexImage,
887       &glGetTexParameterfv,
888       &glGetTexParameteriv,
889       &glGetTexLevelParameterfv,
890       &glGetTexLevelParameteriv,
891       &glIsEnabled,
892       &glIsList,
893       &glDepthRange,
894       &glFrustum,
895       &glLoadIdentity,
896       &glLoadMatrixf,
897       &glLoadMatrixd,
898       &glMatrixMode,
899       &glMultMatrixf,
900       &glMultMatrixd,
901       &glOrtho,
902       &glPopMatrix,
903       &glPushMatrix,
904       &glRotated,
905       &glRotatef,
906       &glScaled,
907       &glScalef,
908       &glTranslated,
909       &glTranslatef,
910       &glViewport,
911       &glArrayElement,
912       &glBindTexture,
913       &glColorPointer,
914       &glDisableClientState,
915       &glDrawArrays,
916       &glDrawElements,
917       &glEdgeFlagPointer,
918       &glEnableClientState,
919       &glIndexPointer,
920       &glIndexub,
921       &glIndexubv,
922       &glInterleavedArrays,
923       &glNormalPointer,
924       &glPolygonOffset,
925       &glTexCoordPointer,
926       &glVertexPointer,
927       &glAreTexturesResident,
928       &glCopyTexImage1D,
929       &glCopyTexImage2D,
930       &glCopyTexSubImage1D,
931       &glCopyTexSubImage2D,
932       &glDeleteTextures,
933       &glGenTextures,
934       &glGetPointerv,
935       &glIsTexture,
936       &glPrioritizeTextures,
937       &glTexSubImage1D,
938       &glTexSubImage2D,
939       &glPopClientAttrib,
940       &glPushClientAttrib
941    }
942 };
943 
944 
945 PGLCLTPROCTABLE APIENTRY
DrvSetContext(HDC hdc,DHGLRC dhglrc,PFN_SETPROCTABLE pfnSetProcTable)946 DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable)
947 {
948    PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
949 
950    if (!stw_make_current(hdc, hdc, dhglrc))
951       r = NULL;
952 
953    return r;
954 }
955