From f22d37e4dd959b268b7e0823be0f1020ffdcaeee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 12 Feb 2007 19:18:41 +0100 Subject: [PATCH] wined3d: Use the context manager to prepare for blitting. --- dlls/wined3d/context.c | 159 ++++++++++++++++++++++++++++++- dlls/wined3d/surface.c | 168 +-------------------------------- dlls/wined3d/wined3d_private.h | 1 + 3 files changed, 161 insertions(+), 167 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 3090538b0e9..1f6d6934eef 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -27,6 +27,160 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info + +/***************************************************************************** + * SetupForBlit + * + * Sets up a context for DirectDraw blitting. + * All texture units are disabled, except unit 0 + * Texture unit 0 is activted where GL_TEXTURE_2D is activated + * fog, lighting, blending, alpha test, z test, scissor test, culling diabled + * color writing enabled for all channels + * register combiners disabled, shaders disabled + * world matris is set to identity, texture matrix 0 too + * projection matrix is setup for drawing screen coordinates + * + * Params: + * This: Device to activate the context for + * context: Context to setup + * width: render target width + * height: render target height + * + *****************************************************************************/ +static inline void SetupForBlit(IWineD3DDeviceImpl *This, WineD3DContext *context, UINT width, UINT height) { + int i; + + TRACE("Setting up context %p for blitting\n", context); + if(context->last_was_blit) { + TRACE("Context is already set up for blitting, nothing to do\n"); + return; + } + context->last_was_blit = TRUE; + + /* Disable shaders */ + This->shader_backend->shader_cleanup((IWineD3DDevice *) This); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER); + + /* Disable all textures. The caller can then bind a texture it wants to blit + * from + */ + if(GL_SUPPORT(NV_REGISTER_COMBINERS)) { + glDisable(GL_REGISTER_COMBINERS_NV); + checkGLcall("glDisable(GL_REGISTER_COMBINERS_NV)"); + } + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + for(i = GL_LIMITS(samplers) - 1; i > 0 ; i--) { + if (GL_SUPPORT(ARB_MULTITEXTURE)) { + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); + } + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable GL_TEXTURE_3D"); + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable GL_TEXTURE_2D"); + glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable GL_TEXTURE_1D"); + + if(i < MAX_TEXTURES) { + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)); + } + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); + checkGLcall("glActiveTextureARB"); + } + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable GL_TEXTURE_CUBE_MAP_ARB"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable GL_TEXTURE_3D"); + glDisable(GL_TEXTURE_1D); + checkGLcall("glDisable GL_TEXTURE_1D"); + glEnable(GL_TEXTURE_2D); + checkGLcall("glEnable GL_TEXTURE_2D"); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glMatrixMode(GL_TEXTURE); + checkGLcall("glMatrixMode(GL_TEXTURE)"); + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(WINED3DTS_TEXTURE0)); + + if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) { + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, + GL_TEXTURE_LOD_BIAS_EXT, + 0.0); + checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ..."); + } + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0)); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)); + + /* Other misc states */ + glDisable(GL_ALPHA_TEST); + checkGLcall("glDisable(GL_ALPHA_TEST)"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHATESTENABLE)); + glDisable(GL_LIGHTING); + checkGLcall("glDisable GL_LIGHTING"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_LIGHTING)); + glDisable(GL_DEPTH_TEST); + checkGLcall("glDisable GL_DEPTH_TEST"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE)); + glDisable(GL_FOG); + checkGLcall("glDisable GL_FOG"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_FOGENABLE)); + glDisable(GL_BLEND); + checkGLcall("glDisable GL_BLEND"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE)); + glDisable(GL_CULL_FACE); + checkGLcall("glDisable GL_CULL_FACE"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_CULLMODE)); + glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable GL_STENCIL_TEST"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE)); + if(GL_SUPPORT(ARB_POINT_SPRITE)) { + glDisable(GL_POINT_SPRITE_ARB); + checkGLcall("glDisable GL_POINT_SPRITE_ARB"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_POINTSPRITEENABLE)); + } + glColorMask(GL_TRUE, GL_TRUE,GL_TRUE,GL_TRUE); + checkGLcall("glColorMask"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_CLIPPING)); + + /* Setup transforms */ + glMatrixMode(GL_MODELVIEW); + checkGLcall("glMatrixMode(GL_MODELVIEW)"); + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))); + + glMatrixMode(GL_PROJECTION); + checkGLcall("glMatrixMode(GL_PROJECTION)"); + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + glOrtho(0, width, height, 0, 0.0, -1.0); + checkGLcall("glOrtho"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(WINED3DTS_PROJECTION)); + + context->last_was_rhw = TRUE; + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL); /* because of last_was_rhw = TRUE */ + + glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); + glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); + glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); + glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); + glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); + glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_CLIPPING)); + + glViewport(0, 0, width, height); + checkGLcall("glViewport"); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT); +} + /***************************************************************************** * ActivateContext * @@ -70,10 +224,13 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU StateTable[dirtyState].apply(dirtyState, This->stateBlock, context); } context->numDirtyEntries = 0; /* This makes the whole list clean */ + context->last_was_blit = FALSE; break; case CTXUSAGE_BLIT: - FIXME("Setting up for blitting not supported yet\n"); + SetupForBlit(This, context, + ((IWineD3DSurfaceImpl *)target)->currentDesc.Width, + ((IWineD3DSurfaceImpl *)target)->currentDesc.Height); break; default: diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 6b3d200448c..be08c34c8c5 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -853,8 +853,6 @@ static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) { glDisable(GL_TEXTURE_2D); vcheckGLcall("glDisable(GL_TEXTURE_2D)"); - glDisable(GL_TEXTURE_1D); - vcheckGLcall("glDisable(GL_TEXTURE_1D)"); glFlush(); vcheckGLcall("glFlush"); @@ -1039,21 +1037,6 @@ static void flush_to_framebuffer_texture(IWineD3DSurface *iface) { ENTER_GL(); - /* Disable some fancy graphics effects */ - glDisable(GL_LIGHTING); - checkGLcall("glDisable GL_LIGHTING"); - glDisable(GL_DEPTH_TEST); - checkGLcall("glDisable GL_DEPTH_TEST"); - glDisable(GL_FOG); - checkGLcall("glDisable GL_FOG"); - glDisable(GL_CULL_FACE); - checkGLcall("glDisable GL_CULL_FACE"); - glDisable(GL_BLEND); - checkGLcall("glDisable GL_BLEND"); - glDisable(GL_STENCIL_TEST); - checkGLcall("glDisable GL_STENCIL_TEST"); - - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName); checkGLcall("glEnable glBindTexture"); @@ -1160,19 +1143,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain); if ((backbuf || iface == implSwapChain->frontBuffer || iface == myDevice->render_targets[0]) && wined3d_settings.rendertargetlock_mode != RTL_DISABLE) { - int tex; ENTER_GL(); - /* glDrawPixels transforms the raster position as though it was a vertex - - we want to draw at screen position 0,0 - Set up ortho (rhw) mode as - per drawprim (and leave set - it will sort itself out due to last_was_rhw */ - myDevice->contexts[myDevice->activeContext].last_was_rhw = TRUE; - /* Apply the projection and world matrices, it sets up orthogonal projection due to last_was_rhw */ - StateTable[STATE_TRANSFORM(WINED3DTS_PROJECTION)].apply(STATE_TRANSFORM(WINED3DTS_PROJECTION), myDevice->stateBlock, &myDevice->contexts[myDevice->activeContext]); - StateTable[STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))].apply(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), myDevice->stateBlock, &myDevice->contexts[myDevice->activeContext]); - /* Will reapply the projection matrix too */ - IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL); + ActivateContext(myDevice, iface, CTXUSAGE_BLIT); if (iface == implSwapChain->frontBuffer) { glDrawBuffer(GL_FRONT); @@ -1182,31 +1156,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { checkGLcall("glDrawBuffer GL_BACK"); } - /* Disable higher textures before calling glDrawPixels */ - for(tex = 1; tex < GL_LIMITS(samplers); tex++) { - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + tex)); - checkGLcall("glActiveTextureARB"); - } - IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(tex)); - glDisable(GL_TEXTURE_2D); - checkGLcall("glDisable GL_TEXTURE_2D"); - glDisable(GL_TEXTURE_1D); - checkGLcall("glDisable GL_TEXTURE_1D"); - } - /* Activate texture 0, but don't disable it necessarily */ - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); - checkGLcall("glActiveTextureARB"); - } - IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0)); - - /* And back buffers are not blended. Disable the depth test, - that helps performance */ - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - switch(wined3d_settings.rendertargetlock_mode) { case RTL_AUTO: case RTL_READDRAW: @@ -1234,10 +1183,6 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) { glDrawBuffer(GL_BACK); vcheckGLcall("glDrawBuffer"); } - if(myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_TRUE || - myDevice->stateBlock->renderState[WINED3DRS_ZENABLE] == WINED3DZB_USEW) glEnable(GL_DEPTH_TEST); - if (myDevice->stateBlock->renderState[WINED3DRS_ALPHABLENDENABLE]) glEnable(GL_BLEND); - if (myDevice->stateBlock->renderState[WINED3DRS_FOGENABLE]) glEnable(GL_FOG); LEAVE_GL(); @@ -2343,10 +2288,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * float glTexCoord[4]; DWORD oldCKey; DDCOLORKEY oldBltCKey = {0,0}; - GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha; - GLint oldStencil, oldNVRegisterCombiners = 0; - GLint alphafunc; - GLclampf alpharef; RECT SourceRectangle; GLint oldDraw; @@ -2399,23 +2340,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * ENTER_GL(); - /* Save all the old stuff until we have a proper opengl state manager */ - oldLight = glIsEnabled(GL_LIGHTING); - oldFog = glIsEnabled(GL_FOG); - oldDepth = glIsEnabled(GL_DEPTH_TEST); - oldBlend = glIsEnabled(GL_BLEND); - oldCull = glIsEnabled(GL_CULL_FACE); - oldAlpha = glIsEnabled(GL_ALPHA_TEST); - oldStencil = glIsEnabled(GL_STENCIL_TEST); - - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - oldNVRegisterCombiners = glIsEnabled(GL_REGISTER_COMBINERS_NV); - } - - glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc); - checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC"); - glGetFloatv(GL_ALPHA_TEST_REF, &alpharef); - checkGLcall("glGetFloatv GL_ALPHA_TEST_REF"); + ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); glGetIntegerv(GL_DRAW_BUFFER, &oldDraw); if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) { @@ -2424,52 +2349,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * checkGLcall("glDrawBuffer GL_FRONT"); } - /* Unbind the old texture */ - glBindTexture(GL_TEXTURE_2D, 0); - IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0)); - - if (GL_SUPPORT(ARB_MULTITEXTURE)) { - /* We use texture unit 0 for blts */ - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); - checkGLcall("glActiveTextureARB"); - } else { - WARN("Multi-texturing is unsupported in the local OpenGL implementation\n"); - } - - /* Disable some fancy graphics effects */ - glDisable(GL_LIGHTING); - checkGLcall("glDisable GL_LIGHTING"); - glDisable(GL_DEPTH_TEST); - checkGLcall("glDisable GL_DEPTH_TEST"); - glDisable(GL_FOG); - checkGLcall("glDisable GL_FOG"); - glDisable(GL_BLEND); - checkGLcall("glDisable GL_BLEND"); - glDisable(GL_CULL_FACE); - checkGLcall("glDisable GL_CULL_FACE"); - glDisable(GL_STENCIL_TEST); - checkGLcall("glDisable GL_STENCIL_TEST"); - if (GL_SUPPORT(NV_REGISTER_COMBINERS)) { - glDisable(GL_REGISTER_COMBINERS_NV); - checkGLcall("glDisable GL_REGISTER_COMBINERS_NV"); - } - - /* Ok, we need 2d textures, but not 1D or 3D */ - glDisable(GL_TEXTURE_1D); - checkGLcall("glDisable GL_TEXTURE_1D"); - glEnable(GL_TEXTURE_2D); - checkGLcall("glEnable GL_TEXTURE_2D"); - glDisable(GL_TEXTURE_3D); - checkGLcall("glDisable GL_TEXTURE_3D"); - /* Bind the texture */ glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName); checkGLcall("glBindTexture"); - glEnable(GL_SCISSOR_TEST); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - /* No filtering for blts */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -2495,13 +2378,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * /* Draw a textured quad */ - myDevice->contexts[myDevice->activeContext].last_was_rhw = TRUE; - /* Apply the projection matrix, it sets up orthogonal projection due to last_was_rhw */ - StateTable[STATE_TRANSFORM(WINED3DTS_PROJECTION)].apply(STATE_TRANSFORM(WINED3DTS_PROJECTION), myDevice->stateBlock, &myDevice->contexts[myDevice->activeContext]); - StateTable[STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))].apply(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), myDevice->stateBlock, &myDevice->contexts[myDevice->activeContext]); - /* That will reapply the projection matrix too */ - IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_VDECL); - glBegin(GL_QUADS); glColor3d(1.0f, 1.0f, 1.0f); @@ -2529,46 +2405,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * glBindTexture(GL_TEXTURE_2D, 0); checkGLcall("glEnable glBindTexture"); - /* Restore the old settings */ - if(oldLight) { - glEnable(GL_LIGHTING); - checkGLcall("glEnable GL_LIGHTING"); - } - if(oldFog) { - glEnable(GL_FOG); - checkGLcall("glEnable GL_FOG"); - } - if(oldDepth) { - glEnable(GL_DEPTH_TEST); - checkGLcall("glEnable GL_DEPTH_TEST"); - } - if(oldBlend) { - glEnable(GL_BLEND); - checkGLcall("glEnable GL_BLEND"); - } - if(oldCull) { - glEnable(GL_CULL_FACE); - checkGLcall("glEnable GL_CULL_FACE"); - } - if(oldStencil) { - glEnable(GL_STENCIL_TEST); - checkGLcall("glEnable GL_STENCIL_TEST"); - } - if(!oldAlpha) { - glDisable(GL_ALPHA_TEST); - checkGLcall("glDisable GL_ALPHA_TEST"); - } else { - glEnable(GL_ALPHA_TEST); - checkGLcall("glEnable GL_ALPHA_TEST"); - } - if (GL_SUPPORT(NV_REGISTER_COMBINERS) && oldNVRegisterCombiners) { - glEnable(GL_REGISTER_COMBINERS_NV); - checkGLcall("glEnable GL_REGISTER_COMBINERS_NV"); - } - - glAlphaFunc(alphafunc, alpharef); - checkGLcall("glAlphaFunc\n"); - if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) { glDrawBuffer(oldDraw); } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ab3e94793c9..03d575960c8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -477,6 +477,7 @@ struct WineD3DContext { BOOL namedArraysLoaded, numberedArraysLoaded; BOOL lastWasPow2Texture[MAX_TEXTURES]; GLenum tracking_parm; /* Which source is tracking current colour */ + BOOL last_was_blit; }; typedef enum ContextUsage {