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
);
68 struct stw_context
*src
;
69 struct stw_context
*dst
;
75 pipe_mutex_lock( stw_dev
->ctx_mutex
);
77 src
= stw_lookup_context_locked( dhrcSource
);
78 dst
= stw_lookup_context_locked( dhrcDest
);
88 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
98 struct stw_context
*ctx1
;
99 struct stw_context
*ctx2
;
105 pipe_mutex_lock( stw_dev
->ctx_mutex
);
107 ctx1
= stw_lookup_context_locked( dhglrc1
);
108 ctx2
= stw_lookup_context_locked( dhglrc2
);
110 if (ctx1
&& ctx2
&& ctx2
->st
->share
)
111 ret
= ctx2
->st
->share(ctx2
->st
, ctx1
->st
);
113 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
122 return DrvCreateLayerContext( hdc
, 0 );
126 DrvCreateLayerContext(
130 return stw_create_context_attribs(hdc
, iLayerPlane
, 0, 1, 0, 0,
131 WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
,
137 * Called via DrvCreateContext(), DrvCreateLayerContext() and
138 * wglCreateContextAttribsARB() to actually create a rendering context.
139 * \param handle the desired DHGLRC handle to use for the context, or zero
140 * if a new handle should be allocated.
141 * \return the handle for the new context or zero if there was a problem.
144 stw_create_context_attribs(HDC hdc
, INT iLayerPlane
, DHGLRC hShareContext
,
145 int majorVersion
, int minorVersion
,
146 int contextFlags
, int profileMask
,
150 struct stw_framebuffer
*fb
;
151 const struct stw_pixelformat_info
*pfi
;
152 struct st_context_attribs attribs
;
153 struct stw_context
*ctx
= NULL
;
154 struct stw_context
*shareCtx
= NULL
;
155 enum st_context_error ctx_err
= 0;
160 if (iLayerPlane
!= 0)
163 iPixelFormat
= GetPixelFormat(hdc
);
168 * GDI only knows about displayable pixel formats, so determine the pixel
169 * format from the framebuffer.
171 * TODO: Remove the GetPixelFormat() above, and stop relying on GDI.
173 fb
= stw_framebuffer_from_hdc( hdc
);
175 assert(iPixelFormat
== fb
->iDisplayablePixelFormat
);
176 iPixelFormat
= fb
->iPixelFormat
;
177 stw_framebuffer_release(fb
);
180 pfi
= stw_pixelformat_get_info( iPixelFormat
);
182 if (hShareContext
!= 0) {
183 pipe_mutex_lock( stw_dev
->ctx_mutex
);
184 shareCtx
= stw_lookup_context_locked( hShareContext
);
185 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
188 ctx
= CALLOC_STRUCT( stw_context
);
193 ctx
->iPixelFormat
= iPixelFormat
;
195 memset(&attribs
, 0, sizeof(attribs
));
196 attribs
.visual
= pfi
->stvis
;
197 attribs
.major
= majorVersion
;
198 attribs
.minor
= minorVersion
;
199 if (contextFlags
& WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
)
200 attribs
.flags
|= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE
;
201 if (contextFlags
& WGL_CONTEXT_DEBUG_BIT_ARB
)
202 attribs
.flags
|= ST_CONTEXT_FLAG_DEBUG
;
204 switch (profileMask
) {
205 case WGL_CONTEXT_CORE_PROFILE_BIT_ARB
:
206 /* There are no profiles before OpenGL 3.2. The
207 * WGL_ARB_create_context_profile spec says:
209 * "If the requested OpenGL version is less than 3.2,
210 * WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
211 * of the context is determined solely by the requested version."
213 if (majorVersion
> 3 || (majorVersion
== 3 && minorVersion
>= 2)) {
214 attribs
.profile
= ST_PROFILE_OPENGL_CORE
;
218 case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
:
220 * The spec also says:
222 * "If version 3.1 is requested, the context returned may implement
223 * any of the following versions:
225 * * Version 3.1. The GL_ARB_compatibility extension may or may not
226 * be implemented, as determined by the implementation.
227 * * The core profile of version 3.2 or greater."
229 * and because Mesa doesn't support GL_ARB_compatibility, the only chance to
230 * honour a 3.1 context is through core profile.
232 if (majorVersion
== 3 && minorVersion
== 1) {
233 attribs
.profile
= ST_PROFILE_OPENGL_CORE
;
235 attribs
.profile
= ST_PROFILE_DEFAULT
;
238 case WGL_CONTEXT_ES_PROFILE_BIT_EXT
:
239 if (majorVersion
>= 2) {
240 attribs
.profile
= ST_PROFILE_OPENGL_ES2
;
242 attribs
.profile
= ST_PROFILE_OPENGL_ES1
;
250 ctx
->st
= stw_dev
->stapi
->create_context(stw_dev
->stapi
,
251 stw_dev
->smapi
, &attribs
, &ctx_err
, shareCtx
? shareCtx
->st
: NULL
);
255 ctx
->st
->st_manager_private
= (void *) ctx
;
257 if (ctx
->st
->cso_context
) {
258 ctx
->hud
= hud_create(ctx
->st
->pipe
, ctx
->st
->cso_context
);
261 pipe_mutex_lock( stw_dev
->ctx_mutex
);
263 /* We're replacing the context data for this handle. See the
264 * wglCreateContextAttribsARB() function.
266 struct stw_context
*old_ctx
=
267 stw_lookup_context_locked((unsigned) handle
);
269 /* free the old context data associated with this handle */
271 hud_destroy(old_ctx
->hud
);
273 ctx
->st
->destroy(old_ctx
->st
);
277 /* replace table entry */
278 handle_table_set(stw_dev
->ctx_table
, (unsigned) handle
, ctx
);
281 /* create new table entry */
282 handle
= (DHGLRC
) handle_table_add(stw_dev
->ctx_table
, ctx
);
285 ctx
->dhglrc
= handle
;
287 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
295 hud_destroy(ctx
->hud
);
297 ctx
->st
->destroy(ctx
->st
);
308 struct stw_context
*ctx
;
314 pipe_mutex_lock( stw_dev
->ctx_mutex
);
315 ctx
= stw_lookup_context_locked(dhglrc
);
316 handle_table_remove(stw_dev
->ctx_table
, dhglrc
);
317 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
320 struct stw_context
*curctx
= stw_current_context();
322 /* Unbind current if deleting current context. */
324 stw_dev
->stapi
->make_current(stw_dev
->stapi
, NULL
, NULL
, NULL
);
327 hud_destroy(ctx
->hud
);
330 ctx
->st
->destroy(ctx
->st
);
343 struct stw_context
*ctx
;
348 pipe_mutex_lock( stw_dev
->ctx_mutex
);
349 ctx
= stw_lookup_context_locked( dhglrc
);
350 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
355 /* The expectation is that ctx is the same context which is
356 * current for this thread. We should check that and return False
359 if (ctx
!= stw_current_context())
362 if (stw_make_current( NULL
, 0 ) == FALSE
)
370 stw_get_current_context( void )
372 struct stw_context
*ctx
;
374 ctx
= stw_current_context();
382 stw_get_current_dc( void )
384 struct stw_context
*ctx
;
386 ctx
= stw_current_context();
398 struct stw_context
*curctx
= NULL
;
399 struct stw_context
*ctx
= NULL
;
400 struct stw_framebuffer
*fb
= NULL
;
406 curctx
= stw_current_context();
407 if (curctx
!= NULL
) {
408 if (curctx
->dhglrc
== dhglrc
) {
409 if (curctx
->hdc
== hdc
) {
410 /* Return if already current. */
414 curctx
->st
->flush(curctx
->st
, ST_FLUSH_FRONT
, NULL
);
419 pipe_mutex_lock( stw_dev
->ctx_mutex
);
420 ctx
= stw_lookup_context_locked( dhglrc
);
421 pipe_mutex_unlock( stw_dev
->ctx_mutex
);
426 fb
= stw_framebuffer_from_hdc( hdc
);
428 stw_framebuffer_update(fb
);
431 /* Applications should call SetPixelFormat before creating a context,
432 * but not all do, and the opengl32 runtime seems to use a default pixel
433 * format in some cases, so we must create a framebuffer for those here
435 int iPixelFormat
= GetPixelFormat(hdc
);
437 fb
= stw_framebuffer_create( hdc
, iPixelFormat
);
442 if (fb
->iPixelFormat
!= ctx
->iPixelFormat
) {
443 SetLastError(ERROR_INVALID_PIXEL_FORMAT
);
447 /* Bind the new framebuffer */
450 ret
= stw_dev
->stapi
->make_current(stw_dev
->stapi
, ctx
->st
,
452 stw_framebuffer_reference(&ctx
->current_framebuffer
, fb
);
454 ret
= stw_dev
->stapi
->make_current(stw_dev
->stapi
, NULL
, NULL
, NULL
);
460 stw_framebuffer_release(fb
);
463 /* On failure, make the thread's current rendering context not current
464 * before returning */
466 stw_dev
->stapi
->make_current(stw_dev
->stapi
, NULL
, NULL
, NULL
);
470 /* Unreference the previous framebuffer if any. It must be done after
471 * make_current, as it can be referenced inside.
473 if (curctx
&& curctx
!= ctx
) {
474 stw_framebuffer_reference(&curctx
->current_framebuffer
, NULL
);
481 * Flush the current context if it is bound to the framebuffer.
484 stw_flush_current_locked( struct stw_framebuffer
*fb
)
486 struct stw_context
*ctx
= stw_current_context();
488 if (ctx
&& ctx
->current_framebuffer
== fb
) {
489 ctx
->st
->flush(ctx
->st
, ST_FLUSH_FRONT
, NULL
);
494 * Notify the current context that the framebuffer has become invalid.
497 stw_notify_current_locked( struct stw_framebuffer
*fb
)
499 p_atomic_inc(&fb
->stfb
->stamp
);
503 * Although WGL allows different dispatch entrypoints per context
505 static const GLCLTPROCTABLE cpt
=
507 OPENGL_VERSION_110_ENTRIES
,
783 &glGetPolygonStipple
,
791 &glGetTexParameterfv
,
792 &glGetTexParameteriv
,
793 &glGetTexLevelParameterfv
,
794 &glGetTexLevelParameteriv
,
818 &glDisableClientState
,
822 &glEnableClientState
,
826 &glInterleavedArrays
,
831 &glAreTexturesResident
,
834 &glCopyTexSubImage1D
,
835 &glCopyTexSubImage2D
,
840 &glPrioritizeTextures
,
848 PGLCLTPROCTABLE APIENTRY
852 PFN_SETPROCTABLE pfnSetProcTable
)
854 PGLCLTPROCTABLE r
= (PGLCLTPROCTABLE
)&cpt
;
856 if (!stw_make_current( hdc
, dhglrc
))