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 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; }
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); if (ctx->hud) { hud_destroy(ctx->hud); } ctx->st->destroy(ctx->st); FREE(ctx); ret = TRUE; } 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; }
BOOL stw_make_current( HDC hdc, DHGLRC dhglrc ) { struct stw_context *curctx = NULL; struct stw_context *ctx = NULL; struct stw_framebuffer *fb = NULL; BOOL ret = FALSE; if (!stw_dev) return FALSE; curctx = stw_current_context(); if (curctx != NULL) { if (curctx->dhglrc == dhglrc) { if (curctx->hdc == hdc) { /* Return if already current. */ return TRUE; } } else { curctx->st->flush(curctx->st, ST_FLUSH_FRONT, NULL); } } if (dhglrc) { pipe_mutex_lock( stw_dev->ctx_mutex ); ctx = stw_lookup_context_locked( dhglrc ); pipe_mutex_unlock( stw_dev->ctx_mutex ); if (!ctx) { goto fail; } fb = stw_framebuffer_from_hdc( hdc ); if (fb) { stw_framebuffer_update(fb); } else { /* Applications should call SetPixelFormat before creating a context, * but not all do, and the opengl32 runtime seems to use a default pixel * format in some cases, so we must create a framebuffer for those here */ int iPixelFormat = GetPixelFormat(hdc); if (iPixelFormat) fb = stw_framebuffer_create( hdc, iPixelFormat ); if (!fb) goto fail; } if (fb->iPixelFormat != ctx->iPixelFormat) { SetLastError(ERROR_INVALID_PIXEL_FORMAT); goto fail; } /* Bind the new framebuffer */ ctx->hdc = hdc; ret = stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb); stw_framebuffer_reference(&ctx->current_framebuffer, fb); } else { ret = stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); } fail: if (fb) { stw_framebuffer_release(fb); } /* On failure, make the thread's current rendering context not current * before returning */ if (!ret) { stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); ctx = NULL; } /* Unreference the previous framebuffer if any. It must be done after * make_current, as it can be referenced inside. */ if (curctx && curctx != ctx) { stw_framebuffer_reference(&curctx->current_framebuffer, NULL); } return ret; }
/** * Called via DrvCreateContext(), DrvCreateLayerContext() and * wglCreateContextAttribsARB() to actually create a rendering context. * \param handle the desired DHGLRC handle to use for the context, or zero * if a new handle should be allocated. * \return the handle for the new context or zero if there was a problem. */ DHGLRC stw_create_context_attribs(HDC hdc, INT iLayerPlane, DHGLRC hShareContext, int majorVersion, int minorVersion, int contextFlags, int profileMask, DHGLRC handle) { 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; switch (profileMask) { case WGL_CONTEXT_CORE_PROFILE_BIT_ARB: /* 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." */ if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2)) { attribs.profile = ST_PROFILE_OPENGL_CORE; break; } /* fall-through */ case WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: /* * The spec also says: * * "If version 3.1 is requested, the context returned may implement * any of the following versions: * * * Version 3.1. The GL_ARB_compatibility extension may or may not * be implemented, as determined by the implementation. * * The core profile of version 3.2 or greater." * * and because Mesa doesn't support GL_ARB_compatibility, the only chance to * honour a 3.1 context is through core profile. */ if (majorVersion == 3 && minorVersion == 1) { attribs.profile = ST_PROFILE_OPENGL_CORE; } else { attribs.profile = ST_PROFILE_DEFAULT; } break; case WGL_CONTEXT_ES_PROFILE_BIT_EXT: if (majorVersion >= 2) { attribs.profile = ST_PROFILE_OPENGL_ES2; } else { attribs.profile = ST_PROFILE_OPENGL_ES1; } break; default: assert(0); goto no_st_ctx; } 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; if (ctx->st->cso_context) { ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context); } pipe_mutex_lock( stw_dev->ctx_mutex ); if (handle) { /* We're replacing the context data for this handle. See the * wglCreateContextAttribsARB() function. */ struct stw_context *old_ctx = stw_lookup_context_locked((unsigned) handle); if (old_ctx) { /* free the old context data associated with this handle */ if (old_ctx->hud) { hud_destroy(old_ctx->hud); } ctx->st->destroy(old_ctx->st); FREE(old_ctx); } /* replace table entry */ handle_table_set(stw_dev->ctx_table, (unsigned) handle, ctx); } else { /* create new table entry */ handle = (DHGLRC) handle_table_add(stw_dev->ctx_table, ctx); } ctx->dhglrc = handle; pipe_mutex_unlock( stw_dev->ctx_mutex ); if (!ctx->dhglrc) goto no_hglrc; return ctx->dhglrc; no_hglrc: if (ctx->hud) { hud_destroy(ctx->hud); } ctx->st->destroy(ctx->st); no_st_ctx: FREE(ctx); no_ctx: return 0; }
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; }