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