/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include <windows.h>
#define WGL_WGLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/wglext.h>
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "util/u_memory.h"
#include "util/u_atomic.h"
#include "state_tracker/st_api.h"
#include "stw_icd.h"
#include "stw_device.h"
#include "stw_winsys.h"
#include "stw_framebuffer.h"
#include "stw_pixelformat.h"
#include "stw_context.h"
#include "stw_tls.h"
static INLINE struct stw_context *
stw_current_context(void)
{
struct st_context_iface *st;
st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL;
return (struct stw_context *) ((st) ? st->st_manager_private : NULL);
}
BOOL APIENTRY
DrvCopyContext(
DHGLRC dhrcSource,
DHGLRC dhrcDest,
UINT fuMask )
{
struct stw_context *src;
struct stw_context *dst;
BOOL ret = FALSE;
if (!stw_dev)
return FALSE;
pipe_mutex_lock( stw_dev->ctx_mutex );
src = stw_lookup_context_locked( dhrcSource );
dst = stw_lookup_context_locked( dhrcDest );
if (src && dst) {
/* FIXME */
assert(0);
(void) src;
(void) dst;
(void) fuMask;
}
pipe_mutex_unlock( stw_dev->ctx_mutex );
return ret;
}
BOOL APIENTRY
DrvShareLists(
DHGLRC dhglrc1,
DHGLRC dhglrc2 )
{
struct stw_context *ctx1;
struct stw_context *ctx2;
BOOL ret = FALSE;
if (!stw_dev)
return FALSE;
pipe_mutex_lock( stw_dev->ctx_mutex );
ctx1 = stw_lookup_context_locked( dhglrc1 );
ctx2 = stw_lookup_context_locked( dhglrc2 );
if (ctx1 && ctx2 && ctx2->st->share)
ret = ctx2->st->share(ctx2->st, ctx1->st);
pipe_mutex_unlock( stw_dev->ctx_mutex );
return ret;
}
DHGLRC APIENTRY
DrvCreateContext(
HDC hdc )
{
return DrvCreateLayerContext( hdc, 0 );
}
DHGLRC APIENTRY
DrvCreateLayerContext(
HDC hdc,
INT iLayerPlane )
{
return stw_create_context_attribs(hdc, iLayerPlane, 0, 1, 0, 0,
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
}
DHGLRC
stw_create_context_attribs(
HDC hdc,
INT iLayerPlane,
DHGLRC hShareContext,
int majorVersion, int minorVersion,
int contextFlags, int profileMask)
{
int iPixelFormat;
struct stw_framebuffer *fb;
const struct stw_pixelformat_info *pfi;
struct st_context_attribs attribs;
struct stw_context *ctx = NULL;
struct stw_context *shareCtx = NULL;
enum st_context_error ctx_err = 0;
if (!stw_dev)
return 0;
if (iLayerPlane != 0)
return 0;
iPixelFormat = GetPixelFormat(hdc);
if(!iPixelFormat)
return 0;
/*
* GDI only knows about displayable pixel formats, so determine the pixel
* format from the framebuffer.
*
* TODO: Remove the GetPixelFormat() above, and stop relying on GDI.
*/
fb = stw_framebuffer_from_hdc( hdc );
if (fb) {
assert(iPixelFormat == fb->iDisplayablePixelFormat);
iPixelFormat = fb->iPixelFormat;
stw_framebuffer_release(fb);
}
pfi = stw_pixelformat_get_info( iPixelFormat );
if (hShareContext != 0) {
pipe_mutex_lock( stw_dev->ctx_mutex );
shareCtx = stw_lookup_context_locked( hShareContext );
pipe_mutex_unlock( stw_dev->ctx_mutex );
}
ctx = CALLOC_STRUCT( stw_context );
if (ctx == NULL)
goto no_ctx;
ctx->hdc = hdc;
ctx->iPixelFormat = iPixelFormat;
memset(&attribs, 0, sizeof(attribs));
attribs.visual = pfi->stvis;
attribs.major = majorVersion;
attribs.minor = minorVersion;
if (contextFlags & WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
if (contextFlags & WGL_CONTEXT_DEBUG_BIT_ARB)
attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
/* There are no profiles before OpenGL 3.2. The
* WGL_ARB_create_context_profile spec says:
*
* "If the requested OpenGL version is less than 3.2,
* WGL_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality of the
* context is determined solely by the requested version."
*
* The spec also says:
*
* "The default value for WGL_CONTEXT_PROFILE_MASK_ARB is
* WGL_CONTEXT_CORE_PROFILE_BIT_ARB."
*/
attribs.profile = ST_PROFILE_DEFAULT;
if ((majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2))
&& ((profileMask & WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) == 0))
attribs.profile = ST_PROFILE_OPENGL_CORE;
ctx->st = stw_dev->stapi->create_context(stw_dev->stapi,
stw_dev->smapi, &attribs, &ctx_err, shareCtx ? shareCtx->st : NULL);
if (ctx->st == NULL)
goto no_st_ctx;
ctx->st->st_manager_private = (void *) ctx;
pipe_mutex_lock( stw_dev->ctx_mutex );
ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx);
pipe_mutex_unlock( stw_dev->ctx_mutex );
if (!ctx->dhglrc)
goto no_hglrc;
return ctx->dhglrc;
no_hglrc:
ctx->st->destroy(ctx->st);
no_st_ctx:
FREE(ctx);
no_ctx:
return 0;
}
BOOL APIENTRY
DrvDeleteContext(
DHGLRC dhglrc )
{
struct stw_context *ctx ;
BOOL ret = FALSE;
if (!stw_dev)
return FALSE;
pipe_mutex_lock( stw_dev->ctx_mutex );
ctx = stw_lookup_context_locked(dhglrc);
handle_table_remove(stw_dev->ctx_table, dhglrc);
pipe_mutex_unlock( stw_dev->ctx_mutex );
if (ctx) {
struct stw_context *curctx = stw_current_context();
/* Unbind current if deleting current context. */
if (curctx == ctx)
stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL);
ctx->st->destroy(ctx->st);
FREE(ctx);
ret = TRUE;
}
return ret;
}
BOOL APIENTRY
DrvReleaseContext(
DHGLRC dhglrc )
{
struct stw_context *ctx;
if (!stw_dev)
return FALSE;
pipe_mutex_lock( stw_dev->ctx_mutex );
ctx = stw_lookup_context_locked( dhglrc );
pipe_mutex_unlock( stw_dev->ctx_mutex );
if (!ctx)
return FALSE;
/* The expectation is that ctx is the same context which is
* current for this thread. We should check that and return False
* if not the case.
*/
if (ctx != stw_current_context())
return FALSE;
if (stw_make_current( NULL, 0 ) == FALSE)
return FALSE;
return TRUE;
}
DHGLRC
stw_get_current_context( void )
{
struct stw_context *ctx;
ctx = stw_current_context();
if(!ctx)
return 0;
return ctx->dhglrc;
}
HDC
stw_get_current_dc( void )
{
struct stw_context *ctx;
ctx = stw_current_context();
if(!ctx)
return NULL;
return ctx->hdc;
}
BOOL
stw_make_current(
HDC hdc,
DHGLRC dhglrc )
{
struct stw_context *curctx = NULL;
str