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 "state_tracker/st_api.h"
41#include "hud/hud_context.h"
42
43#include "stw_icd.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   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 */
140static int
141get_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 */
161DHGLRC
162stw_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
317no_hglrc:
318   if (ctx->hud) {
319      hud_destroy(ctx->hud, NULL);
320   }
321   ctx->st->destroy(ctx->st);
322no_st_ctx:
323   FREE(ctx);
324no_ctx:
325   return 0;
326}
327
328
329BOOL APIENTRY
330DrvDeleteContext(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
364BOOL APIENTRY
365DrvReleaseContext(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
393DHGLRC
394stw_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
406HDC
407stw_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
418HDC
419stw_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
430BOOL
431stw_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         }
453         else {
454            old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL);
455         }
456      }
457   }
458
459   if (dhglrc) {
460      struct stw_framebuffer *fb = NULL;
461      struct stw_framebuffer *fbRead = NULL;
462      stw_lock_contexts(stw_dev);
463      ctx = stw_lookup_context_locked( dhglrc );
464      stw_unlock_contexts(stw_dev);
465      if (!ctx) {
466         goto fail;
467      }
468
469      /* This call locks fb's mutex */
470      fb = stw_framebuffer_from_hdc( hDrawDC );
471      if (fb) {
472         stw_framebuffer_update(fb);
473      }
474      else {
475         /* Applications should call SetPixelFormat before creating a context,
476          * but not all do, and the opengl32 runtime seems to use a default
477          * pixel format in some cases, so we must create a framebuffer for
478          * those here.
479          */
480         int iPixelFormat = get_matching_pixel_format(hDrawDC);
481         if (iPixelFormat)
482            fb = stw_framebuffer_create( hDrawDC, iPixelFormat );
483         if (!fb)
484            goto fail;
485      }
486
487      if (fb->iPixelFormat != ctx->iPixelFormat) {
488         stw_framebuffer_unlock(fb);
489         SetLastError(ERROR_INVALID_PIXEL_FORMAT);
490         goto fail;
491      }
492
493      /* Bind the new framebuffer */
494      ctx->hDrawDC = hDrawDC;
495      ctx->hReadDC = hReadDC;
496
497      struct stw_framebuffer *old_fb = ctx->current_framebuffer;
498      if (old_fb != fb) {
499         stw_framebuffer_reference_locked(fb);
500         ctx->current_framebuffer = fb;
501      }
502      stw_framebuffer_unlock(fb);
503
504      if (hReadDC) {
505         if (hReadDC == hDrawDC) {
506            fbRead = fb;
507         }
508         else {
509            fbRead = stw_framebuffer_from_hdc( hReadDC );
510
511            if (fbRead) {
512               stw_framebuffer_update(fbRead);
513            }
514            else {
515               /* Applications should call SetPixelFormat before creating a
516                * context, but not all do, and the opengl32 runtime seems to
517                * use a default pixel format in some cases, so we must create
518                * a framebuffer for those here.
519                */
520               int iPixelFormat = GetPixelFormat(hReadDC);
521               if (iPixelFormat)
522                  fbRead = stw_framebuffer_create( hReadDC, iPixelFormat );
523               if (!fbRead)
524                  goto fail;
525            }
526
527            if (fbRead->iPixelFormat != ctx->iPixelFormat) {
528               stw_framebuffer_unlock(fbRead);
529               SetLastError(ERROR_INVALID_PIXEL_FORMAT);
530               goto fail;
531            }
532            stw_framebuffer_unlock(fbRead);
533         }
534         ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
535                                            fb->stfb, fbRead->stfb);
536      }
537      else {
538         /* Note: when we call this function we will wind up in the
539          * stw_st_framebuffer_validate_locked() function which will incur
540          * a recursive fb->mutex lock.
541          */
542         ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
543                                            fb->stfb, fb->stfb);
544      }
545
546      if (old_fb && old_fb != fb) {
547         stw_lock_framebuffers(stw_dev);
548         stw_framebuffer_lock(old_fb);
549         stw_framebuffer_release_locked(old_fb);
550         stw_unlock_framebuffers(stw_dev);
551      }
552
553fail:
554      if (fb) {
555         /* fb must be unlocked at this point. */
556         assert(!stw_own_mutex(&fb->mutex));
557      }
558
559      /* On failure, make the thread's current rendering context not current
560       * before returning.
561       */
562      if (!ret) {
563         stw_make_current(NULL, NULL, 0);
564      }
565   } else {
566      ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
567   }
568
569   /* Unreference the previous framebuffer if any. It must be done after
570    * make_current, as it can be referenced inside.
571    */
572   if (old_ctx && old_ctx != ctx) {
573      struct stw_framebuffer *old_fb = old_ctx->current_framebuffer;
574      if (old_fb) {
575         old_ctx->current_framebuffer = NULL;
576         stw_lock_framebuffers(stw_dev);
577         stw_framebuffer_lock(old_fb);
578         stw_framebuffer_release_locked(old_fb);
579         stw_unlock_framebuffers(stw_dev);
580      }
581   }
582
583   return ret;
584}
585
586
587/**
588 * Notify the current context that the framebuffer has become invalid.
589 */
590void
591stw_notify_current_locked( struct stw_framebuffer *fb )
592{
593   p_atomic_inc(&fb->stfb->stamp);
594}
595
596
597/**
598 * Although WGL allows different dispatch entrypoints per context
599 */
600static const GLCLTPROCTABLE cpt =
601{
602   OPENGL_VERSION_110_ENTRIES,
603   {
604      &glNewList,
605      &glEndList,
606      &glCallList,
607      &glCallLists,
608      &glDeleteLists,
609      &glGenLists,
610      &glListBase,
611      &glBegin,
612      &glBitmap,
613      &glColor3b,
614      &glColor3bv,
615      &glColor3d,
616      &glColor3dv,
617      &glColor3f,
618      &glColor3fv,
619      &glColor3i,
620      &glColor3iv,
621      &glColor3s,
622      &glColor3sv,
623      &glColor3ub,
624      &glColor3ubv,
625      &glColor3ui,
626      &glColor3uiv,
627      &glColor3us,
628      &glColor3usv,
629      &glColor4b,
630      &glColor4bv,
631      &glColor4d,
632      &glColor4dv,
633      &glColor4f,
634      &glColor4fv,
635      &glColor4i,
636      &glColor4iv,
637      &glColor4s,
638      &glColor4sv,
639      &glColor4ub,
640      &glColor4ubv,
641      &glColor4ui,
642      &glColor4uiv,
643      &glColor4us,
644      &glColor4usv,
645      &glEdgeFlag,
646      &glEdgeFlagv,
647      &glEnd,
648      &glIndexd,
649      &glIndexdv,
650      &glIndexf,
651      &glIndexfv,
652      &glIndexi,
653      &glIndexiv,
654      &glIndexs,
655      &glIndexsv,
656      &glNormal3b,
657      &glNormal3bv,
658      &glNormal3d,
659      &glNormal3dv,
660      &glNormal3f,
661      &glNormal3fv,
662      &glNormal3i,
663      &glNormal3iv,
664      &glNormal3s,
665      &glNormal3sv,
666      &glRasterPos2d,
667      &glRasterPos2dv,
668      &glRasterPos2f,
669      &glRasterPos2fv,
670      &glRasterPos2i,
671      &glRasterPos2iv,
672      &glRasterPos2s,
673      &glRasterPos2sv,
674      &glRasterPos3d,
675      &glRasterPos3dv,
676      &glRasterPos3f,
677      &glRasterPos3fv,
678      &glRasterPos3i,
679      &glRasterPos3iv,
680      &glRasterPos3s,
681      &glRasterPos3sv,
682      &glRasterPos4d,
683      &glRasterPos4dv,
684      &glRasterPos4f,
685      &glRasterPos4fv,
686      &glRasterPos4i,
687      &glRasterPos4iv,
688      &glRasterPos4s,
689      &glRasterPos4sv,
690      &glRectd,
691      &glRectdv,
692      &glRectf,
693      &glRectfv,
694      &glRecti,
695      &glRectiv,
696      &glRects,
697      &glRectsv,
698      &glTexCoord1d,
699      &glTexCoord1dv,
700      &glTexCoord1f,
701      &glTexCoord1fv,
702      &glTexCoord1i,
703      &glTexCoord1iv,
704      &glTexCoord1s,
705      &glTexCoord1sv,
706      &glTexCoord2d,
707      &glTexCoord2dv,
708      &glTexCoord2f,
709      &glTexCoord2fv,
710      &glTexCoord2i,
711      &glTexCoord2iv,
712      &glTexCoord2s,
713      &glTexCoord2sv,
714      &glTexCoord3d,
715      &glTexCoord3dv,
716      &glTexCoord3f,
717      &glTexCoord3fv,
718      &glTexCoord3i,
719      &glTexCoord3iv,
720      &glTexCoord3s,
721      &glTexCoord3sv,
722      &glTexCoord4d,
723      &glTexCoord4dv,
724      &glTexCoord4f,
725      &glTexCoord4fv,
726      &glTexCoord4i,
727      &glTexCoord4iv,
728      &glTexCoord4s,
729      &glTexCoord4sv,
730      &glVertex2d,
731      &glVertex2dv,
732      &glVertex2f,
733      &glVertex2fv,
734      &glVertex2i,
735      &glVertex2iv,
736      &glVertex2s,
737      &glVertex2sv,
738      &glVertex3d,
739      &glVertex3dv,
740      &glVertex3f,
741      &glVertex3fv,
742      &glVertex3i,
743      &glVertex3iv,
744      &glVertex3s,
745      &glVertex3sv,
746      &glVertex4d,
747      &glVertex4dv,
748      &glVertex4f,
749      &glVertex4fv,
750      &glVertex4i,
751      &glVertex4iv,
752      &glVertex4s,
753      &glVertex4sv,
754      &glClipPlane,
755      &glColorMaterial,
756      &glCullFace,
757      &glFogf,
758      &glFogfv,
759      &glFogi,
760      &glFogiv,
761      &glFrontFace,
762      &glHint,
763      &glLightf,
764      &glLightfv,
765      &glLighti,
766      &glLightiv,
767      &glLightModelf,
768      &glLightModelfv,
769      &glLightModeli,
770      &glLightModeliv,
771      &glLineStipple,
772      &glLineWidth,
773      &glMaterialf,
774      &glMaterialfv,
775      &glMateriali,
776      &glMaterialiv,
777      &glPointSize,
778      &glPolygonMode,
779      &glPolygonStipple,
780      &glScissor,
781      &glShadeModel,
782      &glTexParameterf,
783      &glTexParameterfv,
784      &glTexParameteri,
785      &glTexParameteriv,
786      &glTexImage1D,
787      &glTexImage2D,
788      &glTexEnvf,
789      &glTexEnvfv,
790      &glTexEnvi,
791      &glTexEnviv,
792      &glTexGend,
793      &glTexGendv,
794      &glTexGenf,
795      &glTexGenfv,
796      &glTexGeni,
797      &glTexGeniv,
798      &glFeedbackBuffer,
799      &glSelectBuffer,
800      &glRenderMode,
801      &glInitNames,
802      &glLoadName,
803      &glPassThrough,
804      &glPopName,
805      &glPushName,
806      &glDrawBuffer,
807      &glClear,
808      &glClearAccum,
809      &glClearIndex,
810      &glClearColor,
811      &glClearStencil,
812      &glClearDepth,
813      &glStencilMask,
814      &glColorMask,
815      &glDepthMask,
816      &glIndexMask,
817      &glAccum,
818      &glDisable,
819      &glEnable,
820      &glFinish,
821      &glFlush,
822      &glPopAttrib,
823      &glPushAttrib,
824      &glMap1d,
825      &glMap1f,
826      &glMap2d,
827      &glMap2f,
828      &glMapGrid1d,
829      &glMapGrid1f,
830      &glMapGrid2d,
831      &glMapGrid2f,
832      &glEvalCoord1d,
833      &glEvalCoord1dv,
834      &glEvalCoord1f,
835      &glEvalCoord1fv,
836      &glEvalCoord2d,
837      &glEvalCoord2dv,
838      &glEvalCoord2f,
839      &glEvalCoord2fv,
840      &glEvalMesh1,
841      &glEvalPoint1,
842      &glEvalMesh2,
843      &glEvalPoint2,
844      &glAlphaFunc,
845      &glBlendFunc,
846      &glLogicOp,
847      &glStencilFunc,
848      &glStencilOp,
849      &glDepthFunc,
850      &glPixelZoom,
851      &glPixelTransferf,
852      &glPixelTransferi,
853      &glPixelStoref,
854      &glPixelStorei,
855      &glPixelMapfv,
856      &glPixelMapuiv,
857      &glPixelMapusv,
858      &glReadBuffer,
859      &glCopyPixels,
860      &glReadPixels,
861      &glDrawPixels,
862      &glGetBooleanv,
863      &glGetClipPlane,
864      &glGetDoublev,
865      &glGetError,
866      &glGetFloatv,
867      &glGetIntegerv,
868      &glGetLightfv,
869      &glGetLightiv,
870      &glGetMapdv,
871      &glGetMapfv,
872      &glGetMapiv,
873      &glGetMaterialfv,
874      &glGetMaterialiv,
875      &glGetPixelMapfv,
876      &glGetPixelMapuiv,
877      &glGetPixelMapusv,
878      &glGetPolygonStipple,
879      &glGetString,
880      &glGetTexEnvfv,
881      &glGetTexEnviv,
882      &glGetTexGendv,
883      &glGetTexGenfv,
884      &glGetTexGeniv,
885      &glGetTexImage,
886      &glGetTexParameterfv,
887      &glGetTexParameteriv,
888      &glGetTexLevelParameterfv,
889      &glGetTexLevelParameteriv,
890      &glIsEnabled,
891      &glIsList,
892      &glDepthRange,
893      &glFrustum,
894      &glLoadIdentity,
895      &glLoadMatrixf,
896      &glLoadMatrixd,
897      &glMatrixMode,
898      &glMultMatrixf,
899      &glMultMatrixd,
900      &glOrtho,
901      &glPopMatrix,
902      &glPushMatrix,
903      &glRotated,
904      &glRotatef,
905      &glScaled,
906      &glScalef,
907      &glTranslated,
908      &glTranslatef,
909      &glViewport,
910      &glArrayElement,
911      &glBindTexture,
912      &glColorPointer,
913      &glDisableClientState,
914      &glDrawArrays,
915      &glDrawElements,
916      &glEdgeFlagPointer,
917      &glEnableClientState,
918      &glIndexPointer,
919      &glIndexub,
920      &glIndexubv,
921      &glInterleavedArrays,
922      &glNormalPointer,
923      &glPolygonOffset,
924      &glTexCoordPointer,
925      &glVertexPointer,
926      &glAreTexturesResident,
927      &glCopyTexImage1D,
928      &glCopyTexImage2D,
929      &glCopyTexSubImage1D,
930      &glCopyTexSubImage2D,
931      &glDeleteTextures,
932      &glGenTextures,
933      &glGetPointerv,
934      &glIsTexture,
935      &glPrioritizeTextures,
936      &glTexSubImage1D,
937      &glTexSubImage2D,
938      &glPopClientAttrib,
939      &glPushClientAttrib
940   }
941};
942
943
944PGLCLTPROCTABLE APIENTRY
945DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable)
946{
947   PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
948
949   if (!stw_make_current(hdc, hdc, dhglrc))
950      r = NULL;
951
952   return r;
953}
954