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