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