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/compiler.h"
39
#include "util/u_memory.h"
40
#include "util/u_atomic.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
struct stw_context *ctx = stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0,
130
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
135
DHGLRC ret = stw_create_context_handle(ctx, 0);
137
stw_destroy_context(ctx);
144
* Return the stw pixel format that most closely matches the pixel format
146
* Used to get a pixel format when SetPixelFormat() hasn't been called before.
149
get_matching_pixel_format(HDC hdc)
151
int iPixelFormat = GetPixelFormat(hdc);
152
PIXELFORMATDESCRIPTOR pfd;
156
if (!DescribePixelFormat(hdc, iPixelFormat, sizeof(pfd), &pfd))
158
return stw_pixelformat_choose(hdc, &pfd);
163
* Called via DrvCreateContext(), DrvCreateLayerContext() and
164
* wglCreateContextAttribsARB() to actually create a rendering context.
167
stw_create_context_attribs(HDC hdc, INT iLayerPlane, struct stw_context *shareCtx,
168
int majorVersion, int minorVersion,
169
int contextFlags, int profileMask,
172
const struct stw_pixelformat_info *pfi;
173
struct st_context_attribs attribs;
174
struct stw_context *ctx = NULL;
175
enum st_context_error ctx_err = 0;
180
if (iLayerPlane != 0)
185
* GDI only knows about displayable pixel formats, so determine the pixel
186
* format from the framebuffer.
188
* This also allows to use a OpenGL DLL / ICD without installing.
190
struct stw_framebuffer *fb;
191
fb = stw_framebuffer_from_hdc(hdc);
193
iPixelFormat = fb->iPixelFormat;
194
stw_framebuffer_unlock(fb);
197
/* Applications should call SetPixelFormat before creating a context,
198
* but not all do, and the opengl32 runtime seems to use a default
199
* pixel format in some cases, so use that.
201
iPixelFormat = get_matching_pixel_format(hdc);
207
pfi = stw_pixelformat_get_info( iPixelFormat );
209
if (shareCtx != NULL)
210
shareCtx->shared = TRUE;
212
ctx = CALLOC_STRUCT( stw_context );
218
ctx->iPixelFormat = iPixelFormat;
219
ctx->shared = shareCtx != NULL;
221
memset(&attribs, 0, sizeof(attribs));
222
attribs.visual = pfi->stvis;
223
attribs.major = majorVersion;
224
attribs.minor = minorVersion;
225
if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
226
attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
227
if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
228
attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
230
switch (profileMask) {
231
case WGL_CONTEXT_CORE_PROFILE_BIT_ARB:
232
/* There are no profiles before OpenGL 3.2. The
233
* WGL_ARB_create_context_profile spec says:
235
* "If the requested OpenGL version is less than 3.2,
236
* WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
237
* of the context is determined solely by the requested version."
239
if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) {
240
attribs.profile = ST_PROFILE_OPENGL_CORE;
244
case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
246
* The spec also says:
248
* "If version 3.1 is requested, the context returned may implement
249
* any of the following versions:
251
* * Version 3.1. The GL_ARB_compatibility extension may or may not
252
* be implemented, as determined by the implementation.
253
* * The core profile of version 3.2 or greater."
255
* But Mesa doesn't support GL_ARB_compatibility, while most prevalent
256
* Windows OpenGL implementations do, and unfortunately many Windows
257
* applications don't check whether they receive or not a context with
258
* GL_ARB_compatibility, so returning a core profile here does more harm
261
attribs.profile = ST_PROFILE_DEFAULT;
263
case WGL_CONTEXT_ES_PROFILE_BIT_EXT:
264
if (majorVersion >= 2) {
265
attribs.profile = ST_PROFILE_OPENGL_ES2;
267
attribs.profile = ST_PROFILE_OPENGL_ES1;
275
attribs.options = stw_dev->st_options;
277
ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
278
stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
282
ctx->st->st_manager_private = (void *) ctx;
284
if (ctx->st->cso_context) {
285
ctx->hud = hud_create(ctx->st->cso_context, ctx->st, NULL);
297
stw_create_context_handle(struct stw_context *ctx, DHGLRC handle)
299
assert(ctx->dhglrc == 0);
301
stw_lock_contexts(stw_dev);
303
/* We're replacing the context data for this handle. See the
304
* wglCreateContextAttribsARB() function.
306
struct stw_context *old_ctx =
307
stw_lookup_context_locked((unsigned) handle);
309
stw_destroy_context(old_ctx);
312
/* replace table entry */
313
handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx);
316
/* create new table entry */
317
handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx);
320
ctx->dhglrc = handle;
322
stw_unlock_contexts(stw_dev);
328
stw_destroy_context(struct stw_context *ctx)
331
hud_destroy(ctx->hud, NULL);
334
ctx->st->destroy(ctx->st);
340
DrvDeleteContext(DHGLRC dhglrc)
342
struct stw_context *ctx ;
348
stw_lock_contexts(stw_dev);
349
ctx = stw_lookup_context_locked(dhglrc);
350
handle_table_remove(stw_dev->ctx_table, dhglrc);
351
stw_unlock_contexts(stw_dev);
354
struct stw_context *curctx = stw_current_context();
356
/* Unbind current if deleting current context. */
358
stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
360
stw_destroy_context(ctx);
368
stw_unbind_context(struct stw_context *ctx)
373
/* The expectation is that ctx is the same context which is
374
* current for this thread. We should check that and return False
377
if (ctx != stw_current_context())
380
if (stw_make_current( NULL, NULL, NULL ) == FALSE)
387
DrvReleaseContext(DHGLRC dhglrc)
389
struct stw_context *ctx;
394
stw_lock_contexts(stw_dev);
395
ctx = stw_lookup_context_locked( dhglrc );
396
stw_unlock_contexts(stw_dev);
398
return stw_unbind_context(ctx);
403
stw_get_current_context( void )
405
struct stw_context *ctx;
407
ctx = stw_current_context();
416
stw_get_current_dc( void )
418
struct stw_context *ctx;
420
ctx = stw_current_context();
428
stw_get_current_read_dc( void )
430
struct stw_context *ctx;
432
ctx = stw_current_context();
440
release_old_framebuffers(struct stw_framebuffer *old_fb, struct stw_framebuffer *old_fbRead,
441
struct stw_context *old_ctx)
443
if (old_fb || old_fbRead) {
444
stw_lock_framebuffers(stw_dev);
446
stw_framebuffer_lock(old_fb);
447
stw_framebuffer_release_locked(old_fb, old_ctx->st);
450
stw_framebuffer_lock(old_fbRead);
451
stw_framebuffer_release_locked(old_fbRead, old_ctx->st);
453
stw_unlock_framebuffers(stw_dev);
458
stw_make_current(struct stw_framebuffer *fb, struct stw_framebuffer *fbRead, struct stw_context *ctx)
460
struct stw_context *old_ctx = NULL;
466
old_ctx = stw_current_context();
467
if (old_ctx != NULL) {
468
if (old_ctx == ctx) {
469
if (old_ctx->current_framebuffer == fb && old_ctx->current_read_framebuffer == fbRead) {
470
/* Return if already current. */
474
if (old_ctx->shared) {
475
if (old_ctx->current_framebuffer) {
476
stw_st_flush(old_ctx->st, old_ctx->current_framebuffer->stfb,
477
ST_FLUSH_FRONT | ST_FLUSH_WAIT);
479
struct pipe_fence_handle *fence = NULL;
480
old_ctx->st->flush(old_ctx->st,
481
ST_FLUSH_FRONT | ST_FLUSH_WAIT, &fence,
485
if (old_ctx->current_framebuffer)
486
stw_st_flush(old_ctx->st, old_ctx->current_framebuffer->stfb,
489
old_ctx->st->flush(old_ctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
498
if (fb->iPixelFormat != ctx->iPixelFormat) {
499
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
502
if (fbRead->iPixelFormat != ctx->iPixelFormat) {
503
SetLastError(ERROR_INVALID_PIXEL_FORMAT);
507
stw_framebuffer_lock(fb);
508
stw_framebuffer_update(fb);
509
stw_framebuffer_reference_locked(fb);
510
stw_framebuffer_unlock(fb);
512
stw_framebuffer_lock(fbRead);
514
stw_framebuffer_update(fbRead);
515
stw_framebuffer_reference_locked(fbRead);
516
stw_framebuffer_unlock(fbRead);
518
struct stw_framebuffer *old_fb = ctx->current_framebuffer;
519
struct stw_framebuffer *old_fbRead = ctx->current_read_framebuffer;
520
ctx->current_framebuffer = fb;
521
ctx->current_read_framebuffer = fbRead;
523
ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st,
524
fb->stfb, fbRead->stfb);
526
/* Release the old framebuffers from this context. */
527
release_old_framebuffers(old_fb, old_fbRead, ctx);
530
/* fb and fbRead must be unlocked at this point. */
532
assert(!stw_own_mutex(&fb->mutex));
534
assert(!stw_own_mutex(&fbRead->mutex));
536
/* On failure, make the thread's current rendering context not current
540
stw_make_current(NULL, NULL, NULL);
543
ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
546
/* Unreference the previous framebuffer if any. It must be done after
547
* make_current, as it can be referenced inside.
549
if (old_ctx && old_ctx != ctx) {
550
release_old_framebuffers(old_ctx->current_framebuffer, old_ctx->current_read_framebuffer, old_ctx);
551
old_ctx->current_framebuffer = NULL;
552
old_ctx->current_read_framebuffer = NULL;
558
static struct stw_framebuffer *
559
get_unlocked_refd_framebuffer_from_dc(HDC hDC)
564
/* This call locks fb's mutex */
565
struct stw_framebuffer *fb = stw_framebuffer_from_hdc(hDC);
567
/* Applications should call SetPixelFormat before creating a context,
568
* but not all do, and the opengl32 runtime seems to use a default
569
* pixel format in some cases, so we must create a framebuffer for
572
int iPixelFormat = get_matching_pixel_format(hDC);
574
fb = stw_framebuffer_create(WindowFromDC(hDC), iPixelFormat, STW_FRAMEBUFFER_WGL_WINDOW);
578
stw_framebuffer_reference_locked(fb);
579
stw_framebuffer_unlock(fb);
584
stw_make_current_by_handles(HDC hDrawDC, HDC hReadDC, DHGLRC dhglrc)
586
struct stw_context *ctx = stw_lookup_context(dhglrc);
587
if (dhglrc && !ctx) {
588
stw_make_current_by_handles(NULL, NULL, 0);
592
struct stw_framebuffer *fb = get_unlocked_refd_framebuffer_from_dc(hDrawDC);
594
stw_make_current_by_handles(NULL, NULL, 0);
598
struct stw_framebuffer *fbRead = (hDrawDC == hReadDC || hReadDC == NULL) ?
599
fb : get_unlocked_refd_framebuffer_from_dc(hReadDC);
600
if (ctx && !fbRead) {
601
release_old_framebuffers(fb, NULL, ctx);
602
stw_make_current_by_handles(NULL, NULL, 0);
606
BOOL success = stw_make_current(fb, fbRead, ctx);
610
ctx->hDrawDC = hDrawDC;
611
ctx->hReadDC = hReadDC;
617
assert(fb && fbRead);
618
/* In the success case, the context took extra references on these framebuffers,
619
* so release our local references.
621
stw_lock_framebuffers(stw_dev);
622
stw_framebuffer_lock(fb);
623
stw_framebuffer_release_locked(fb, ctx->st);
625
stw_framebuffer_lock(fbRead);
626
stw_framebuffer_release_locked(fbRead, ctx->st);
628
stw_unlock_framebuffers(stw_dev);
635
* Notify the current context that the framebuffer has become invalid.
638
stw_notify_current_locked( struct stw_framebuffer *fb )
640
p_atomic_inc(&fb->stfb->stamp);
645
* Although WGL allows different dispatch entrypoints per context
647
static const GLCLTPROCTABLE cpt =
649
OPENGL_VERSION_110_ENTRIES,
925
&glGetPolygonStipple,
933
&glGetTexParameterfv,
934
&glGetTexParameteriv,
935
&glGetTexLevelParameterfv,
936
&glGetTexLevelParameteriv,
960
&glDisableClientState,
964
&glEnableClientState,
968
&glInterleavedArrays,
973
&glAreTexturesResident,
976
&glCopyTexSubImage1D,
977
&glCopyTexSubImage2D,
982
&glPrioritizeTextures,
991
PGLCLTPROCTABLE APIENTRY
992
DrvSetContext(HDC hdc, DHGLRC dhglrc, PFN_SETPROCTABLE pfnSetProcTable)
994
PGLCLTPROCTABLE r = (PGLCLTPROCTABLE)&cpt;
996
if (!stw_make_current_by_handles(hdc, hdc, dhglrc))