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
52struct stw_context *
53stw_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
63BOOL APIENTRY
64DrvCopyContext(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
92BOOL APIENTRY
93DrvShareLists(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
119DHGLRC APIENTRY
120DrvCreateContext(HDC hdc)
121{
122   return DrvCreateLayerContext( hdc, 0 );
123}
124
125
126DHGLRC APIENTRY
127DrvCreateLayerContext(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 */
148static int
149get_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 */
166struct stw_context *
167stw_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
294no_st_ctx:
295   FREE(ctx);
296no_ctx:
297   return NULL;
298}
299
300DHGLRC
301stw_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
331void
332stw_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
343BOOL APIENTRY
344DrvDeleteContext(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
371BOOL
372stw_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
390BOOL APIENTRY
391DrvReleaseContext(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
406DHGLRC
407stw_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
419HDC
420stw_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
431HDC
432stw_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
443static void
444release_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
461BOOL
462stw_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
533fail:
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
562static struct stw_framebuffer *
563get_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
587BOOL
588stw_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 */
641void
642stw_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 */
651static 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
995PGLCLTPROCTABLE APIENTRY
996DrvSetContext(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