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; }
/** * Flush the current context if it is bound to the framebuffer. */ void stw_flush_current_locked( struct stw_framebuffer *fb ) { struct stw_context *ctx = stw_current_context(); if (ctx && ctx->current_framebuffer == fb) { ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); } }
HDC stw_get_current_dc( void ) { struct stw_context *ctx; ctx = stw_current_context(); if(!ctx) return NULL; return ctx->hdc; }
DHGLRC stw_get_current_context( void ) { struct stw_context *ctx; ctx = stw_current_context(); if(!ctx) return 0; return ctx->dhglrc; }
BOOL APIENTRY DrvSwapBuffers(HDC hdc) { struct stw_context *ctx; struct stw_framebuffer *fb; if (!stw_dev) return FALSE; fb = stw_framebuffer_from_hdc( hdc ); if (fb == NULL) return FALSE; if (!(fb->pfi->pfd.dwFlags & PFD_DOUBLEBUFFER)) { stw_framebuffer_unlock(fb); return TRUE; } ctx = stw_current_context(); if (ctx) { if (ctx->hud) { /* Display the HUD */ struct pipe_resource *back = stw_get_framebuffer_resource(fb->stfb, ST_ATTACHMENT_BACK_LEFT); if (back) { hud_draw(ctx->hud, back); } } if (ctx->current_framebuffer == fb) { /* flush current context */ ctx->st->flush(ctx->st, ST_FLUSH_END_OF_FRAME, NULL); } } if (stw_dev->swap_interval != 0) { wait_swap_interval(fb); } return stw_st_swap_framebuffer_locked(hdc, fb->stfb); }
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; }
BOOL WINAPI wglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer) { HDC prevDrawable = stw_get_current_dc(); HDC prevReadable = stw_get_current_read_dc(); HDC dc; struct stw_context *curctx = stw_current_context(); struct stw_framebuffer *fb; GLenum texFormat, srcBuffer, target; boolean retVal; int pixelFormatSave; /* * Implementation notes: * Ideally, we'd implement this function with the * st_context_iface::teximage() function which replaces a specific * texture image with a different resource (the pbuffer). * The main problem however, is the pbuffer image is upside down relative * to the texture image. * Window system drawing surfaces (windows & pbuffers) are "top to bottom" * while OpenGL texture images are "bottom to top". One possible solution * to this is to invert rendering to pbuffers (as we do for renderbuffers) * but that could lead to other issues (and would require extensive * testing). * * The simple alternative is to use a copy-based approach which copies the * pbuffer image into the texture via glCopyTex[Sub]Image. That's what * we do here. */ if (!curctx) { debug_printf("No rendering context in wglBindTexImageARB()\n"); SetLastError(ERROR_INVALID_OPERATION); return FALSE; } fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer); if (!fb) { debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n"); SetLastError(ERROR_INVALID_HANDLE); return FALSE; } srcBuffer = translate_ibuffer(iBuffer); if (srcBuffer == GL_NONE) { debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer); SetLastError(ERROR_INVALID_DATA); return FALSE; } target = translate_target(fb->textureTarget); if (target == GL_NONE) { debug_printf("no texture target in wglBindTexImageARB()\n"); return FALSE; } texFormat = translate_texture_format(fb->textureFormat); if (texFormat == GL_NONE) { debug_printf("no texture format in wglBindTexImageARB()\n"); return FALSE; } /* * Bind the pbuffer surface so we can read/copy from it. * * Before we can call stw_make_current() we have to temporarily * change the pbuffer's pixel format to match the context to avoid * an error condition. After the stw_make_current() we restore the * buffer's pixel format. */ pixelFormatSave = fb->iPixelFormat; fb->iPixelFormat = curctx->iPixelFormat; dc = wglGetPbufferDCARB(hPbuffer); retVal = stw_make_current(dc, dc, curctx->dhglrc); fb->iPixelFormat = pixelFormatSave; if (!retVal) { debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n"); wglReleasePbufferDCARB(hPbuffer, dc); return FALSE; } st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height, target, fb->textureLevel, fb->textureFace, texFormat); /* rebind previous drawing surface */ retVal = stw_make_current(prevDrawable, prevReadable, curctx->dhglrc); if (!retVal) { debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n"); } wglReleasePbufferDCARB(hPbuffer, dc); return retVal; }