1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <windows.h>
29
30 #define WGL_WGLEXT_PROTOTYPES
31
32 #include <GL/gl.h>
33 #include <GL/wglext.h>
34
35 #include "pipe/p_compiler.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_state.h"
38 #include "util/u_memory.h"
39 #include "util/u_atomic.h"
40 #include "state_tracker/st_api.h"
41
42 #include "stw_icd.h"
43 #include "stw_device.h"
44 #include "stw_winsys.h"
45 #include "stw_framebuffer.h"
46 #include "stw_pixelformat.h"
47 #include "stw_context.h"
48 #include "stw_tls.h"
49
50
51 static INLINE struct stw_context *
stw_current_context(void)52 stw_current_context(void)
53 {
54 struct st_context_iface *st;
55
56 st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
57
58 return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
59 }
60
61 BOOL APIENTRY
DrvCopyContext(DHGLRC dhrcSource,DHGLRC dhrcDest,UINT fuMask)62 DrvCopyContext(
63 DHGLRC dhrcSource,
64 DHGLRC dhrcDest,
65 UINT fuMask )
66 {
67 struct stw_context *src;
68 struct stw_context *dst;
69 BOOL ret = FALSE;
70
71 if (!stw_dev)
72 return FALSE;
73
74 pipe_mutex_lock( stw_dev->ctx_mutex );
75
76 src = stw_lookup_context_locked( dhrcSource );
77 dst = stw_lookup_context_locked( dhrcDest );
78
79 if (src && dst) {
80 /* FIXME */
81 assert(0);
82 (void) src;
83 (void) dst;
84 (void) fuMask;
85 }
86
87 pipe_mutex_unlock( stw_dev->ctx_mutex );
88
89 return ret;
90 }
91
92 BOOL APIENTRY
DrvShareLists(DHGLRC dhglrc1,DHGLRC dhglrc2)93 DrvShareLists(
94 DHGLRC dhglrc1,
95 DHGLRC dhglrc2 )
96 {
97 struct stw_context *ctx1;
98 struct stw_context *ctx2;
99 BOOL ret = FALSE;
100
101 if (!stw_dev)
102 return FALSE;
103
104 pipe_mutex_lock( stw_dev->ctx_mutex );
105
106 ctx1 = stw_lookup_context_locked( dhglrc1 );
107 ctx2 = stw_lookup_context_locked( dhglrc2 );
108
109 if (ctx1 && ctx2 && ctx2->st->share)
110 ret = ctx2->st->share(ctx2->st, ctx1->st);
111
112 pipe_mutex_unlock( stw_dev->ctx_mutex );
113
114 return ret;
115 }
116
117 DHGLRC APIENTRY
DrvCreateContext(HDC hdc)118 DrvCreateContext(
119 HDC hdc )
120 {
121 return DrvCreateLayerContext( hdc, 0 );
122 }
123
124 DHGLRC APIENTRY
DrvCreateLayerContext(HDC hdc,INT iLayerPlane)125 DrvCreateLayerContext(
126 HDC hdc,
127 INT iLayerPlane )
128 {
129 return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0,
130 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
131 }
132
133 DHGLRC
stw_create_context_attribs(HDC hdc,INT iLayerPlane,DHGLRC hShareContext,int majorVersion,int minorVersion,int contextFlags,int profileMask)134 stw_create_context_attribs(
135 HDC hdc,
136 INT iLayerPlane,
137 DHGLRC hShareContext,
138 int majorVersion, int minorVersion,
139 int contextFlags, int profileMask)
140 {
141 int iPixelFormat;
142 struct stw_framebuffer *fb;
143 const struct stw_pixelformat_info *pfi;
144 struct st_context_attribs attribs;
145 struct stw_context *ctx = NULL;
146 struct stw_context *shareCtx = NULL;
147 enum st_context_error ctx_err = 0;
148
149 if (!stw_dev)
150 return 0;
151
152 if (iLayerPlane != 0)
153 return 0;
154
155 iPixelFormat = GetPixelFormat(hdc);
156 if(!iPixelFormat)
157 return 0;
158
159 /*
160 * GDI only knows about displayable pixel formats, so determine the pixel
161 * format from the framebuffer.
162 *
163 * TODO: Remove the GetPixelFormat() above, and stop relying on GDI.
164 */
165 fb = stw_framebuffer_from_hdc( hdc );
166 if (fb) {
167 assert(iPixelFormat == fb->iDisplayablePixelFormat);
168 iPixelFormat = fb->iPixelFormat;
169 stw_framebuffer_release(fb);
170 }
171
172 pfi = stw_pixelformat_get_info( iPixelFormat );
173
174 if (hShareContext != 0) {
175 pipe_mutex_lock( stw_dev->ctx_mutex );
176 shareCtx = stw_lookup_context_locked( hShareContext );
177 pipe_mutex_unlock( stw_dev->ctx_mutex );
178 }
179
180 ctx = CALLOC_STRUCT( stw_context );
181 if (ctx == NULL)
182 goto no_ctx;
183
184 ctx->hdc = hdc;
185 ctx->iPixelFormat = iPixelFormat;
186
187 memset(&attribs, 0, sizeof(attribs));
188 attribs.visual = pfi->stvis;
189 attribs.major = majorVersion;
190 attribs.minor = minorVersion;
191 if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
192 attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
193 if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
194 attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
195
196 /* There are no profiles before OpenGL 3.2. The
197 * WGL_ARB_create_context_profile spec says:
198 *
199 * "If the requested OpenGL version is less than 3.2,
200 * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the
201 * context is determined solely by the requested version."
202 *
203 * The spec also says:
204 *
205 * "The default value for WGL_CONTEXT_PROFILE_MASK_ARB is
206 * WGL_CONTEXT_CORE_PROFILE_BIT_ARB."
207 */
208 attribs.profile = ST_PROFILE_DEFAULT;
209 if ((majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2))
210 && ((profileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0))
211 attribs.profile = ST_PROFILE_OPENGL_CORE;
212
213 ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
214 stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
215 if (ctx->st == NULL)
216 goto no_st_ctx;
217
218 ctx->st->st_manager_private = (void *) ctx;
219
220 pipe_mutex_lock( stw_dev->ctx_mutex );
221 ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
222 pipe_mutex_unlock( stw_dev->ctx_mutex );
223 if (!ctx->dhglrc)
224 goto no_hglrc;
225
226 return ctx->dhglrc;
227
228 no_hglrc:
229 ctx->st->destroy(ctx->st);
230 no_st_ctx:
231 FREE(ctx);
232 no_ctx:
233 return 0;
234 }
235
236 BOOL APIENTRY
DrvDeleteContext(DHGLRC dhglrc)237 DrvDeleteContext(
238 DHGLRC dhglrc )
239 {
240 struct stw_context *ctx ;
241 BOOL ret = FALSE;
242
243 if (!stw_dev)
244 return FALSE;
245
246 pipe_mutex_lock( stw_dev->ctx_mutex );
247 ctx = stw_lookup_context_locked(dhglrc);
248 handle_table_remove(stw_dev->ctx_table, dhglrc);
249 pipe_mutex_unlock( stw_dev->ctx_mutex );
250
251 if (ctx) {
252 struct stw_context *curctx = stw_current_context();
253
254 /* Unbind current if deleting current context. */
255 if (curctx == ctx)
256 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
257
258 ctx->st->destroy(ctx->st);
259 FREE(ctx);
260
261 ret = TRUE;
262 }
263
264 return ret;
265 }
266
267 BOOL APIENTRY
DrvReleaseContext(DHGLRC dhglrc)268 DrvReleaseContext(
269 DHGLRC dhglrc )
270 {
271 struct stw_context *ctx;
272
273 if (!stw_dev)
274 return FALSE;
275
276 pipe_mutex_lock( stw_dev->ctx_mutex );
277 ctx = stw_lookup_context_locked( dhglrc );
278 pipe_mutex_unlock( stw_dev->ctx_mutex );
279
280 if (!ctx)
281 return FALSE;
282
283 /* The expectation is that ctx is the same context which is
284 * current for this thread. We should check that and return False
285 * if not the case.
286 */
287 if (ctx != stw_current_context())
288 return FALSE;
289
290 if (stw_make_current( NULL, 0 ) == FALSE)
291 return FALSE;
292
293 return TRUE;
294 }
295
296
297 DHGLRC
stw_get_current_context(void)298 stw_get_current_context( void )
299 {
300 struct stw_context *ctx;
301
302 ctx = stw_current_context();
303 if(!ctx)
304 return 0;
305
306 return ctx->dhglrc;
307 }
308
309 HDC
stw_get_current_dc(void)310 stw_get_current_dc( void )
311 {
312 struct stw_context *ctx;
313
314 ctx = stw_current_context();
315 if(!ctx)
316 return NULL;
317
318 return ctx->hdc;
319 }
320
321 BOOL
stw_make_current(HDC hdc,DHGLRC dhglrc)322 stw_make_current(
323 HDC hdc,
324 DHGLRC dhglrc )
325 {
326 struct stw_context *curctx = NULL;
327 struct stw_context *ctx = NULL;
328 struct stw_framebuffer *fb = NULL;
329 BOOL ret = FALSE;
330
331 if (!stw_dev)
332 return FALSE;
333
334 curctx = stw_current_context();
335 if (curctx != NULL) {
336 if (curctx->dhglrc == dhglrc) {
337 if (curctx->hdc == hdc) {
338 /* Return if already current. */
339 return TRUE;
340 }
341 } else {
342 curctx->st->flush(curctx->st, ST_FLUSH_FRONT, NULL);
343 }
344 }
345
346 if (dhglrc) {
347 pipe_mutex_lock( stw_dev->ctx_mutex );
348 ctx = stw_lookup_context_locked( dhglrc );
349 pipe_mutex_unlock( stw_dev->ctx_mutex );
350 if (!ctx) {
351 goto fail;
352 }
353
354 fb = stw_framebuffer_from_hdc( hdc );
355 if (fb) {
356 stw_framebuffer_update(fb);
357 }
358 else {
359 /* Applications should call SetPixelFormat before creating a context,
360 * but not all do, and the opengl32 runtime seems to use a default pixel
361 * format in some cases, so we must create a framebuffer for those here
362 */
363 int iPixelFormat = GetPixelFormat(hdc);
364 if (iPixelFormat)
365 fb = stw_framebuffer_create( hdc, iPixelFormat );
366 if (!fb)
367 goto fail;
368 }
369
370 if (fb->iPixelFormat != ctx->iPixelFormat) {
371 SetLastError(ERROR_INVALID_PIXEL_FORMAT);
372 goto fail;
373 }
374
375 /* Bind the new framebuffer */
376 ctx->hdc = hdc;
377
378 ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
379 fb->stfb, fb->stfb);
380 stw_framebuffer_reference(&ctx->current_framebuffer, fb);
381 } else {
382 ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
383 }
384
385 fail:
386
387 if (fb) {
388 stw_framebuffer_release(fb);
389 }
390
391 /* On failure, make the thread's current rendering context not current
392 * before returning */
393 if (!ret) {
394 stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
395 ctx = NULL;
396 }
397
398 /* Unreference the previous framebuffer if any. It must be done after
399 * make_current, as it can be referenced inside.
400 */
401 if (curctx && curctx != ctx) {
402 stw_framebuffer_reference(&curctx->current_framebuffer, NULL);
403 }
404
405 return ret;
406 }
407
408 /**
409 * Flush the current context if it is bound to the framebuffer.
410 */
411 void
stw_flush_current_locked(struct stw_framebuffer * fb)412 stw_flush_current_locked( struct stw_framebuffer *fb )
413 {
414 struct stw_context *ctx = stw_current_context();
415
416 if (ctx && ctx->current_framebuffer == fb) {
417 ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
418 }
419 }
420
421 /**
422 * Notify the current context that the framebuffer has become invalid.
423 */
424 void
stw_notify_current_locked(struct stw_framebuffer * fb)425 stw_notify_current_locked( struct stw_framebuffer *fb )
426 {
427 p_atomic_inc(&fb->stfb->stamp);
428 }
429
430 /**
431 * Although WGL allows different dispatch entrypoints per context
432 */
433 static const GLCLTPROCTABLE cpt =
434 {
435 OPENGL_VERSION_110_ENTRIES,
436 {
437 &glNewList,
438 &glEndList,
439 &glCallList,
440 &glCallLists,
441 &glDeleteLists,
442 &glGenLists,
443 &glListBase,
444 &glBegin,
445 &glBitmap,
446 &glColor3b,
447 &glColor3bv,
448 &glColor3d,
449 &glColor3dv,
450 &glColor3f,
451 &glColor3fv,
452 &glColor3i,
453 &glColor3iv,
454 &glColor3s,
455 &glColor3sv,
456 &glColor3ub,
457 &glColor3ubv,
458 &glColor3ui,
459 &glColor3uiv,
460 &glColor3us,
461 &glColor3usv,
462 &glColor4b,
463 &glColor4bv,
464 &glColor4d,
465 &glColor4dv,
466 &glColor4f,
467 &glColor4fv,
468 &glColor4i,
469 &glColor4iv,
470 &glColor4s,
471 &glColor4sv,
472 &glColor4ub,
473 &glColor4ubv,
474 &glColor4ui,
475 &glColor4uiv,
476 &glColor4us,
477 &glColor4usv,
478 &glEdgeFlag,
479 &glEdgeFlagv,
480 &glEnd,
481 &glIndexd,
482 &glIndexdv,
483 &glIndexf,
484 &glIndexfv,
485 &glIndexi,
486 &glIndexiv,
487 &glIndexs,
488 &glIndexsv,
489 &glNormal3b,
490 &glNormal3bv,
491 &glNormal3d,
492 &glNormal3dv,
493 &glNormal3f,
494 &glNormal3fv,
495 &glNormal3i,
496 &glNormal3iv,
497 &glNormal3s,
498 &glNormal3sv,
499 &glRasterPos2d,
500 &glRasterPos2dv,
501 &glRasterPos2f,
502 &glRasterPos2fv,
503 &glRasterPos2i,
504 &glRasterPos2iv,
505 &glRasterPos2s,
506 &glRasterPos2sv,
507 &glRasterPos3d,
508 &glRasterPos3dv,
509 &glRasterPos3f,
510 &glRasterPos3fv,
511 &glRasterPos3i,
512 &glRasterPos3iv,
513 &glRasterPos3s,
514 &glRasterPos3sv,
515 &glRasterPos4d,
516 &glRasterPos4dv,
517 &glRasterPos4f,
518 &glRasterPos4fv,
519 &glRasterPos4i,
520 &glRasterPos4iv,
521 &glRasterPos4s,
522 &glRasterPos4sv,
523 &glRectd,
524 &glRectdv,
525 &glRectf,
526 &glRectfv,
527 &glRecti,
528 &glRectiv,
529 &glRects,
530 &glRectsv,
531 &glTexCoord1d,
532 &glTexCoord1dv,
533 &glTexCoord1f,
534 &glTexCoord1fv,
535 &glTexCoord1i,
536 &glTexCoord1iv,
537 &glTexCoord1s,
538 &glTexCoord1sv,
539 &glTexCoord2d,
540 &glTexCoord2dv,
541 &glTexCoord2f,
542 &glTexCoord2fv,
543 &glTexCoord2i,
544 &glTexCoord2iv,
545 &glTexCoord2s,
546 &glTexCoord2sv,
547 &glTexCoord3d,
548 &glTexCoord3dv,
549 &glTexCoord3f,
550 &glTexCoord3fv,
551 &glTexCoord3i,
552 &glTexCoord3iv,
553 &glTexCoord3s,
554 &glTexCoord3sv,
555 &glTexCoord4d,
556 &glTexCoord4dv,
557 &glTexCoord4f,
558 &glTexCoord4fv,
559 &glTexCoord4i,
560 &glTexCoord4iv,
561 &glTexCoord4s,
562 &glTexCoord4sv,
563 &glVertex2d,
564 &glVertex2dv,
565 &glVertex2f,
566 &glVertex2fv,
567 &glVertex2i,
568 &glVertex2iv,
569 &glVertex2s,
570 &glVertex2sv,
571 &glVertex3d,
572 &glVertex3dv,
573 &glVertex3f,
574 &glVertex3fv,
575 &glVertex3i,
576 &glVertex3iv,
577 &glVertex3s,
578 &glVertex3sv,
579 &glVertex4d,
580 &glVertex4dv,
581 &glVertex4f,
582 &glVertex4fv,
583 &glVertex4i,
584 &glVertex4iv,
585 &glVertex4s,
586 &glVertex4sv,
587 &glClipPlane,
588 &glColorMaterial,
589 &glCullFace,
590 &glFogf,
591 &glFogfv,
592 &glFogi,
593 &glFogiv,
594 &glFrontFace,
595 &glHint,
596 &glLightf,
597 &glLightfv,
598 &glLighti,
599 &glLightiv,
600 &glLightModelf,
601 &glLightModelfv,
602 &glLightModeli,
603 &glLightModeliv,
604 &glLineStipple,
605 &glLineWidth,
606 &glMaterialf,
607 &glMaterialfv,
608 &glMateriali,
609 &glMaterialiv,
610 &glPointSize,
611 &glPolygonMode,
612 &glPolygonStipple,
613 &glScissor,
614 &glShadeModel,
615 &glTexParameterf,
616 &glTexParameterfv,
617 &glTexParameteri,
618 &glTexParameteriv,
619 &glTexImage1D,
620 &glTexImage2D,
621 &glTexEnvf,
622 &glTexEnvfv,
623 &glTexEnvi,
624 &glTexEnviv,
625 &glTexGend,
626 &glTexGendv,
627 &glTexGenf,
628 &glTexGenfv,
629 &glTexGeni,
630 &glTexGeniv,
631 &glFeedbackBuffer,
632 &glSelectBuffer,
633 &glRenderMode,
634 &glInitNames,
635 &glLoadName,
636 &glPassThrough,
637 &glPopName,
638 &glPushName,
639 &glDrawBuffer,
640 &glClear,
641 &glClearAccum,
642 &glClearIndex,
643 &glClearColor,
644 &glClearStencil,
645 &glClearDepth,
646 &glStencilMask,
647 &glColorMask,
648 &glDepthMask,
649 &glIndexMask,
650 &glAccum,
651 &glDisable,
652 &glEnable,
653 &glFinish,
654 &glFlush,
655 &glPopAttrib,
656 &glPushAttrib,
657 &glMap1d,
658 &glMap1f,
659 &glMap2d,
660 &glMap2f,
661 &glMapGrid1d,
662 &glMapGrid1f,
663 &glMapGrid2d,
664 &glMapGrid2f,
665 &glEvalCoord1d,
666 &glEvalCoord1dv,
667 &glEvalCoord1f,
668 &glEvalCoord1fv,
669 &glEvalCoord2d,
670 &glEvalCoord2dv,
671 &glEvalCoord2f,
672 &glEvalCoord2fv,
673 &glEvalMesh1,
674 &glEvalPoint1,
675 &glEvalMesh2,
676 &glEvalPoint2,
677 &glAlphaFunc,
678 &glBlendFunc,
679 &glLogicOp,
680 &glStencilFunc,
681 &glStencilOp,
682 &glDepthFunc,
683 &glPixelZoom,
684 &glPixelTransferf,
685 &glPixelTransferi,
686 &glPixelStoref,
687 &glPixelStorei,
688 &glPixelMapfv,
689 &glPixelMapuiv,
690 &glPixelMapusv,
691 &glReadBuffer,
692 &glCopyPixels,
693 &glReadPixels,
694 &glDrawPixels,
695 &glGetBooleanv,
696 &glGetClipPlane,
697 &glGetDoublev,
698 &glGetError,
699 &glGetFloatv,
700 &glGetIntegerv,
701 &glGetLightfv,
702 &glGetLightiv,
703 &glGetMapdv,
704 &glGetMapfv,
705 &glGetMapiv,
706 &glGetMaterialfv,
707 &glGetMaterialiv,
708 &glGetPixelMapfv,
709 &glGetPixelMapuiv,
710 &glGetPixelMapusv,
711 &glGetPolygonStipple,
712 &glGetString,
713 &glGetTexEnvfv,
714 &glGetTexEnviv,
715 &glGetTexGendv,
716 &glGetTexGenfv,
717 &glGetTexGeniv,
718 &glGetTexImage,
719 &glGetTexParameterfv,
720 &glGetTexParameteriv,
721 &glGetTexLevelParameterfv,
722 &glGetTexLevelParameteriv,
723 &glIsEnabled,
724 &glIsList,
725 &glDepthRange,
726 &glFrustum,
727 &glLoadIdentity,
728 &glLoadMatrixf,
729 &glLoadMatrixd,
730 &glMatrixMode,
731 &glMultMatrixf,
732 &glMultMatrixd,
733 &glOrtho,
734 &glPopMatrix,
735 &glPushMatrix,
736 &glRotated,
737 &glRotatef,
738 &glScaled,
739 &glScalef,
740 &glTranslated,
741 &glTranslatef,
742 &glViewport,
743 &glArrayElement,
744 &glBindTexture,
745 &glColorPointer,
746 &glDisableClientState,
747 &glDrawArrays,
748 &glDrawElements,
749 &glEdgeFlagPointer,
750 &glEnableClientState,
751 &glIndexPointer,
752 &glIndexub,
753 &glIndexubv,
754 &glInterleavedArrays,
755 &glNormalPointer,
756 &glPolygonOffset,
757 &glTexCoordPointer,
758 &glVertexPointer,
759 &glAreTexturesResident,
760 &glCopyTexImage1D,
761 &glCopyTexImage2D,
762 &glCopyTexSubImage1D,
763 &glCopyTexSubImage2D,
764 &glDeleteTextures,
765 &glGenTextures,
766 &glGetPointerv,
767 &glIsTexture,
768 &glPrioritizeTextures,
769 &glTexSubImage1D,
770 &glTexSubImage2D,
771 &glPopClientAttrib,
772 &glPushClientAttrib
773 }
774 };
775
776 PGLCLTPROCTABLE APIENTRY
DrvSetContext(HDC hdc,DHGLRC dhglrc,PFN_SETPROCTABLE pfnSetProcTable)777 DrvSetContext(
778 HDC hdc,
779 DHGLRC dhglrc,
780 PFN_SETPROCTABLE pfnSetProcTable )
781 {
782 PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
783
784 if (!stw_make_current( hdc, dhglrc ))
785 r = NULL;
786
787 return r;
788 }
789