1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 #define WGL_WGLEXT_PROTOTYPES
33 #include <GL/wglext.h>
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"
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"
53 stw_current_context(void)
55 struct st_context_iface
*st
;
57 st
= (stw_dev
) ? stw_dev
->stapi
->get_current(stw_dev
->stapi
) : NULL
;
59 return (struct stw_context
*) ((st
) ? st
->st_manager_private
: NULL
);
64 DrvCopyContext(DHGLRC dhrcSource
, DHGLRC dhrcDest
, UINT fuMask
)
66 struct stw_context
*src
;
67 struct stw_context
*dst
;
73 stw_lock_contexts(stw_dev
);
75 src
= stw_lookup_context_locked( dhrcSource
);
76 dst
= stw_lookup_context_locked( dhrcDest
);
86 stw_unlock_contexts(stw_dev
);
93 DrvShareLists(DHGLRC dhglrc1
, DHGLRC dhglrc2
)
95 struct stw_context
*ctx1
;
96 struct stw_context
*ctx2
;
102 stw_lock_contexts(stw_dev
);
104 ctx1
= stw_lookup_context_locked( dhglrc1
);
105 ctx2
= stw_lookup_context_locked( dhglrc2
);
107 if (ctx1
&& ctx2
&& ctx2
->st
->share
) {
108 ret
= ctx2
->st
->share(ctx2
->st
, ctx1
->st
);
113 stw_unlock_contexts(stw_dev
);
120 DrvCreateContext(HDC hdc
)
122 return DrvCreateLayerContext( hdc
, 0 );
127 DrvCreateLayerContext(HDC hdc
, INT iLayerPlane
)
129 return stw_create_context_attribs(hdc
, iLayerPlane
, 0, 1, 0, 0,
130 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
,
136 * Return the stw pixel format that most closely matches the pixel format
138 * Used to get a pixel format when SetPixelFormat() hasn't been called before.
141 get_matching_pixel_format(HDC hdc
)
143 int iPixelFormat
= GetPixelFormat(hdc
);
144 PIXELFORMATDESCRIPTOR pfd
;
148 if (!DescribePixelFormat(hdc
, iPixelFormat
, sizeof(pfd
), &pfd
))
150 return stw_pixelformat_choose(hdc
, &pfd
);
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.
162 stw_create_context_attribs(HDC hdc
, INT iLayerPlane
, DHGLRC hShareContext
,
163 int majorVersion
, int minorVersion
,
164 int contextFlags
, int profileMask
,
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;
178 if (iLayerPlane
!= 0)
182 * GDI only knows about displayable pixel formats, so determine the pixel
183 * format from the framebuffer.
185 * This also allows to use a OpenGL DLL / ICD without installing.
187 fb
= stw_framebuffer_from_hdc( hdc
);
189 iPixelFormat
= fb
->iPixelFormat
;
190 stw_framebuffer_unlock(fb
);
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.
196 iPixelFormat
= get_matching_pixel_format(hdc
);
201 pfi
= stw_pixelformat_get_info( iPixelFormat
);
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
);
210 ctx
= CALLOC_STRUCT( stw_context
);
216 ctx
->iPixelFormat
= iPixelFormat
;
217 ctx
->shared
= shareCtx
!= NULL
;
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
;
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:
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."
237 if (majorVersion
> 3 || (majorVersion
== 3 && minorVersion
>= 2)) {
238 attribs
.profile
= ST_PROFILE_OPENGL_CORE
;
242 case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
:
244 * The spec also says:
246 * "If version 3.1 is requested, the context returned may implement
247 * any of the following versions:
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."
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
259 attribs
.profile
= ST_PROFILE_DEFAULT
;
261 case WGL_CONTEXT_ES_PROFILE_BIT_EXT
:
262 if (majorVersion
>= 2) {
263 attribs
.profile
= ST_PROFILE_OPENGL_ES2
;
265 attribs
.profile
= ST_PROFILE_OPENGL_ES1
;
273 ctx
->st
= stw_dev
->stapi
->create_context(stw_dev
->stapi
,
274 stw_dev
->smapi
, &attribs
, &ctx_err
, shareCtx
? shareCtx
->st
: NULL
);
278 ctx
->st
->st_manager_private
= (void *) ctx
;
280 if (ctx
->st
->cso_context
) {
281 ctx
->hud
= hud_create(ctx
->st
->cso_context
, NULL
);
284 stw_lock_contexts(stw_dev
);
286 /* We're replacing the context data for this handle. See the
287 * wglCreateContextAttribsARB() function.
289 struct stw_context
*old_ctx
=
290 stw_lookup_context_locked((unsigned) handle
);
292 /* free the old context data associated with this handle */
294 hud_destroy(old_ctx
->hud
, NULL
);
296 ctx
->st
->destroy(old_ctx
->st
);
300 /* replace table entry */
301 handle_table_set(stw_dev
->ctx_table
, (unsigned) handle
, ctx
);
304 /* create new table entry */
305 handle
= (DHGLRC
) handle_table_add(stw_dev
->ctx_table
, ctx
);
308 ctx
->dhglrc
= handle
;
310 stw_unlock_contexts(stw_dev
);
319 hud_destroy(ctx
->hud
, NULL
);
321 ctx
->st
->destroy(ctx
->st
);
330 DrvDeleteContext(DHGLRC dhglrc
)
332 struct stw_context
*ctx
;
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
);
344 struct stw_context
*curctx
= stw_current_context();
346 /* Unbind current if deleting current context. */
348 stw_dev
->stapi
->make_current(stw_dev
->stapi
, NULL
, NULL
, NULL
);
351 hud_destroy(ctx
->hud
, NULL
);
354 ctx
->st
->destroy(ctx
->st
);
365 DrvReleaseContext(DHGLRC dhglrc
)
367 struct stw_context
*ctx
;
372 stw_lock_contexts(stw_dev
);
373 ctx
= stw_lookup_context_locked( dhglrc
);
374 stw_unlock_contexts(stw_dev
);
379 /* The expectation is that ctx is the same context which is
380 * current for this thread. We should check that and return False
383 if (ctx
!= stw_current_context())
386 if (stw_make_current( NULL
, NULL
, 0 ) == FALSE
)
394 stw_get_current_context( void )
396 struct stw_context
*ctx
;
398 ctx
= stw_current_context();
407 stw_get_current_dc( void )
409 struct stw_context
*ctx
;
411 ctx
= stw_current_context();
419 stw_get_current_read_dc( void )
421 struct stw_context
*ctx
;
423 ctx
= stw_current_context();
431 stw_make_current(HDC hDrawDC
, HDC hReadDC
, DHGLRC dhglrc
)
433 struct stw_context
*old_ctx
= NULL
;
434 struct stw_context
*ctx
= NULL
;
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. */
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
,
455 old_ctx
->st
->flush(old_ctx
->st
, ST_FLUSH_FRONT
, NULL
, NULL
, NULL
);
461 struct stw_framebuffer
*fb
= NULL
;
462 struct stw_framebuffer
*fbRead
= NULL
;
463 stw_lock_contexts(stw_dev
);
464 ctx
= stw_lookup_context_locked( dhglrc
);
465 stw_unlock_contexts(stw_dev
);
470 /* This call locks fb's mutex */
471 fb
= stw_framebuffer_from_hdc( hDrawDC
);
473 stw_framebuffer_update(fb
);
476 /* Applications should call SetPixelFormat before creating a context,
477 * but not all do, and the opengl32 runtime seems to use a default
478 * pixel format in some cases, so we must create a framebuffer for
481 int iPixelFormat
= get_matching_pixel_format(hDrawDC
);
483 fb
= stw_framebuffer_create( hDrawDC
, iPixelFormat
);
488 if (fb
->iPixelFormat
!= ctx
->iPixelFormat
) {
489 stw_framebuffer_unlock(fb
);
490 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
494 /* Bind the new framebuffer */
495 ctx
->hDrawDC
= hDrawDC
;
496 ctx
->hReadDC
= hReadDC
;
498 struct stw_framebuffer
*old_fb
= ctx
->current_framebuffer
;
500 stw_framebuffer_reference_locked(fb
);
501 ctx
->current_framebuffer
= fb
;
503 stw_framebuffer_unlock(fb
);
506 if (hReadDC
== hDrawDC
) {
510 fbRead
= stw_framebuffer_from_hdc( hReadDC
);
513 stw_framebuffer_update(fbRead
);
516 /* Applications should call SetPixelFormat before creating a
517 * context, but not all do, and the opengl32 runtime seems to
518 * use a default pixel format in some cases, so we must create
519 * a framebuffer for those here.
521 int iPixelFormat
= GetPixelFormat(hReadDC
);
523 fbRead
= stw_framebuffer_create( hReadDC
, iPixelFormat
);
528 if (fbRead
->iPixelFormat
!= ctx
->iPixelFormat
) {
529 stw_framebuffer_unlock(fbRead
);
530 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
533 stw_framebuffer_unlock(fbRead
);
535 ret
= stw_dev
->stapi
->make_current(stw_dev
->stapi
, ctx
->st
,
536 fb
->stfb
, fbRead
->stfb
);
539 /* Note: when we call this function we will wind up in the
540 * stw_st_framebuffer_validate_locked() function which will incur
541 * a recursive fb->mutex lock.
543 ret
= stw_dev
->stapi
->make_current(stw_dev
->stapi
, ctx
->st
,
547 if (old_fb
&& old_fb
!= fb
) {
548 stw_lock_framebuffers(stw_dev
);
549 stw_framebuffer_lock(old_fb
);
550 stw_framebuffer_release_locked(old_fb
);
551 stw_unlock_framebuffers(stw_dev
);
556 /* fb must be unlocked at this point. */
557 assert(!stw_own_mutex(&fb
->mutex
));
560 /* On failure, make the thread's current rendering context not current
564 stw_make_current(NULL
, NULL
, 0);
567 ret
= stw_dev
->stapi
->make_current(stw_dev
->stapi
, NULL
, NULL
, NULL
);
570 /* Unreference the previous framebuffer if any. It must be done after
571 * make_current, as it can be referenced inside.
573 if (old_ctx
&& old_ctx
!= ctx
) {
574 struct stw_framebuffer
*old_fb
= old_ctx
->current_framebuffer
;
576 old_ctx
->current_framebuffer
= NULL
;
577 stw_lock_framebuffers(stw_dev
);
578 stw_framebuffer_lock(old_fb
);
579 stw_framebuffer_release_locked(old_fb
);
580 stw_unlock_framebuffers(stw_dev
);
589 * Notify the current context that the framebuffer has become invalid.
592 stw_notify_current_locked( struct stw_framebuffer
*fb
)
594 p_atomic_inc(&fb
->stfb
->stamp
);
599 * Although WGL allows different dispatch entrypoints per context
601 static const GLCLTPROCTABLE cpt
=
603 OPENGL_VERSION_110_ENTRIES
,
879 &glGetPolygonStipple
,
887 &glGetTexParameterfv
,
888 &glGetTexParameteriv
,
889 &glGetTexLevelParameterfv
,
890 &glGetTexLevelParameteriv
,
914 &glDisableClientState
,
918 &glEnableClientState
,
922 &glInterleavedArrays
,
927 &glAreTexturesResident
,
930 &glCopyTexSubImage1D
,
931 &glCopyTexSubImage2D
,
936 &glPrioritizeTextures
,
945 PGLCLTPROCTABLE APIENTRY
946 DrvSetContext(HDC hdc
, DHGLRC dhglrc
, PFN_SETPROCTABLE pfnSetProcTable
)
948 PGLCLTPROCTABLE r
= (PGLCLTPROCTABLE
)&cpt
;
950 if (!stw_make_current(hdc
, hdc
, dhglrc
))