From fc6b9774862e62cfbd38f31374073957007e62d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Fri, 1 Aug 2008 13:21:10 -0500 Subject: [PATCH] wined3d: Start a framework for color conversion shaders in blits. --- dlls/wined3d/device.c | 23 ++++++++++++++++++-- dlls/wined3d/directx.c | 10 +++++++++ dlls/wined3d/surface.c | 39 ++++++++++++++++++++++++++++++---- dlls/wined3d/wined3d_private.h | 12 +++++++++++ 4 files changed, 78 insertions(+), 6 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 43837b28d3b..e1e01e2af17 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2170,6 +2170,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR TRACE("Fragment pipeline private data couldn't be allocated\n"); goto err_out; } + hr = This->blitter->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Blitter private data couldn't be allocated\n"); + goto err_out; + } /* Set up some starting GL setup */ @@ -2254,6 +2259,7 @@ err_out: IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->stateBlock); This->stateBlock = NULL; } + This->blitter->free_private(iface); This->frag_pipe->free_private(iface); This->shader_backend->shader_free_private(iface); return hr; @@ -2371,6 +2377,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D } /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */ + This->blitter->free_private(iface); This->frag_pipe->free_private(iface); This->shader_backend->shader_free_private(iface); @@ -7220,6 +7227,7 @@ void delete_opengl_contexts(IWineD3DDevice *iface, IWineD3DSwapChain *swapchain_ This->depth_blt_rb_w = 0; This->depth_blt_rb_h = 0; } + This->blitter->free_private(iface); This->frag_pipe->free_private(iface); This->shader_backend->shader_free_private(iface); @@ -7263,15 +7271,26 @@ HRESULT create_primary_opengl_context(IWineD3DDevice *iface, IWineD3DSwapChain * hr = This->shader_backend->shader_alloc_private(iface); if(FAILED(hr)) { ERR("Failed to recreate shader private data\n"); - return hr; + goto err_out; } hr = This->frag_pipe->alloc_private(iface); if(FAILED(hr)) { TRACE("Fragment pipeline private data couldn't be allocated\n"); - return hr; + goto err_out; + } + hr = This->blitter->alloc_private(iface); + if(FAILED(hr)) { + TRACE("Blitter private data couldn't be allocated\n"); + goto err_out; } return WINED3D_OK; + +err_out: + This->blitter->free_private(iface); + This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); + return hr; } static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) { diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index b5bc44d9283..de4e1b983da 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2933,6 +2933,15 @@ static const struct fragment_pipeline *select_fragment_implementation(UINT Adapt } } +static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) { + int vs_selected_mode; + int ps_selected_mode; + + select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); + return &ffp_blit; + +} + /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true subset of a D3DCAPS9 structure. However, it has to come via a void * as the d3d8 interface cannot import the d3d9 header */ @@ -3568,6 +3577,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, object->frag_pipe = frag_pipeline; compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION, ffp_vertexstate_template, frag_pipeline, misc_state_template); + object->blitter = select_blit_implementation(Adapter, DeviceType); /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader * model can deal with that. It is essentially the same, just with adjusted diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index a1149215345..197ff168e69 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -3467,8 +3467,8 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * glDrawBuffer(buffer); checkGLcall("glDrawBuffer"); - glEnable(Src->glDescription.target); - checkGLcall("glEnable(Src->glDescription.target)"); + myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format, + Src->glDescription.target, Src->pow2Width, Src->pow2Height); /* Bind the texture */ glBindTexture(Src->glDescription.target, Src->glDescription.textureName); @@ -3537,8 +3537,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * glBindTexture(Src->glDescription.target, 0); checkGLcall("glBindTexture(Src->glDescription.target, 0)"); /* Leave the opengl state valid for blitting */ - glDisable(Src->glDescription.target); - checkGLcall("glDisable(Src->glDescription.target)"); + myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice); /* The draw buffer should only need to be restored if we were drawing to the front buffer, and there is a back buffer. * otherwise the context manager should choose between GL_BACK / offscreenDrawBuffer @@ -4623,3 +4622,35 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_GetImplType, IWineD3DSurfaceImpl_DrawOverlay }; +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION device->adapter->gl_info +static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; } +static void ffp_blit_free(IWineD3DDevice *iface) { } + +static HRESULT ffp_blit_set(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height) { + glEnable(textype); + checkGLcall("glEnable(textype)"); + return WINED3D_OK; +} + +static void ffp_blit_unset(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface; + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } +} + +const struct blit_shader ffp_blit = { + ffp_blit_alloc, + ffp_blit_free, + ffp_blit_set, + ffp_blit_unset +}; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6f1479032b3..70bac96019d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -575,6 +575,16 @@ void compile_state_table(struct StateEntry *StateTable, const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc); +/* Shaders for color conversions in blits */ +struct blit_shader { + HRESULT (*alloc_private)(IWineD3DDevice *iface); + void (*free_private)(IWineD3DDevice *iface); + HRESULT (*set_shader)(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height); + void (*unset_shader)(IWineD3DDevice *iface); +}; + +extern const struct blit_shader ffp_blit; + /* The new context manager that should deal with onscreen and offscreen rendering */ struct WineD3DContext { /* State dirtification @@ -829,10 +839,12 @@ struct IWineD3DDeviceImpl const shader_backend_t *shader_backend; void *shader_priv; void *fragment_priv; + void *blit_priv; struct StateEntry StateTable[STATE_HIGHEST + 1]; /* Array of functions for states which are handled by more than one pipeline part */ APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1]; const struct fragment_pipeline *frag_pipe; + const struct blit_shader *blitter; /* To store */ BOOL view_ident; /* true iff view matrix is identity */