From f09b8e454d932f3768c8ad5f6f4658ee587f291e Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Thu, 29 Apr 2010 00:08:59 +0200 Subject: [PATCH] wined3d: Avoid some needless depth buffer copies. If an application switches between render targets of a different size, but with the same depth/stencil surface it'll typically clear the depth/stencil surface before drawing. However, in case of the smaller render target that wouldn't be a full clear, so we'd have to do a depth copy if we also switched between onscreen and offscreen rendering. Keeping track of which part of the depth/stencil surface is current for onscreen/offscreen allows us to avoid most of these kinds of copies. The current scheme requires the current/dirty rectangle to have an origin at (0,0). This could be extended to an arbitrary rectangle, but the bookkeeping becomes somewhat more complex in that case, and it's not clear that there would be much of a benefit at this point. --- dlls/wined3d/arb_program_shader.c | 78 ++++++++++++++++++++++++----- dlls/wined3d/device.c | 70 +++++++++++++++++++++++--- dlls/wined3d/drawprim.c | 23 +++++++-- dlls/wined3d/glsl_shader.c | 83 ++++++++++++++++++++++++++----- dlls/wined3d/shader.c | 2 +- dlls/wined3d/surface.c | 21 ++++++-- dlls/wined3d/swapchain.c | 4 +- dlls/wined3d/wined3d_private.h | 6 ++- 8 files changed, 243 insertions(+), 44 deletions(-) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index db4324d309..f0db9cf696 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -287,7 +287,8 @@ struct shader_arb_priv const struct arb_ps_compiled_shader *compiled_fprog; const struct arb_vs_compiled_shader *compiled_vprog; GLuint depth_blt_vprogram_id; - GLuint depth_blt_fprogram_id[tex_type_count]; + GLuint depth_blt_fprogram_id_full[tex_type_count]; + GLuint depth_blt_fprogram_id_masked[tex_type_count]; BOOL use_arbfp_fixed_func; struct wine_rb_tree fragment_shaders; BOOL last_ps_const_clamped; @@ -3103,12 +3104,14 @@ static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_inf } /* GL locking is done by the caller */ -static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) +static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info, + enum tex_types tex_type, BOOL masked) { GLuint program_id = 0; + const char *fprogram; GLint pos; - static const char * const blt_fprograms[tex_type_count] = + static const char * const blt_fprograms_full[tex_type_count] = { /* tex_1d */ NULL, @@ -3134,7 +3137,46 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i "END\n", }; - if (!blt_fprograms[tex_type]) + static const char * const blt_fprograms_masked[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" + "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" + "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + /* tex_rect */ + "!!ARBfp1.0\n" + "PARAM mask = program.local[0];\n" + "TEMP R0;\n" + "SLT R0.xy, fragment.position, mask.zwzw;\n" + "MUL R0.x, R0.x, R0.y;\n" + "KIL -R0.x;\n" + "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n" + "MOV result.depth.z, R0.x;\n" + "END\n", + }; + + fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type]; + if (!fprogram) { FIXME("tex_type %#x not supported\n", tex_type); tex_type = tex_2d; @@ -3142,8 +3184,7 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i GL_EXTCALL(glGenProgramsARB(1, &program_id)); GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id)); - GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, - strlen(blt_fprograms[tex_type]), blt_fprograms[tex_type])); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fprogram), fprogram)); checkGLcall("glProgramStringARB()"); glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); @@ -3151,7 +3192,7 @@ static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_i { FIXME("Fragment program error at position %d: %s\n\n", pos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); - shader_arb_dump_program_source(blt_fprograms[tex_type]); + shader_arb_dump_program_source(fprogram); } else { @@ -4444,18 +4485,23 @@ static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, } /* GL locking is done by the caller */ -static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { +static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size) +{ + const float mask[] = {0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy}; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + BOOL masked = ds_mask_size->cx && ds_mask_size->cy; struct shader_arb_priv *priv = This->shader_priv; - GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type]; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + GLuint *blt_fprogram; if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info); GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id)); glEnable(GL_VERTEX_PROGRAM_ARB); - if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type); + blt_fprogram = masked ? &priv->depth_blt_fprogram_id_masked[tex_type] : &priv->depth_blt_fprogram_id_full[tex_type]; + if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type, masked); GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram)); + if (masked) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, mask)); glEnable(GL_FRAGMENT_PROGRAM_ARB); } @@ -4595,9 +4641,15 @@ static void shader_arb_free(IWineD3DDevice *iface) { if(priv->depth_blt_vprogram_id) { GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id)); } - for (i = 0; i < tex_type_count; ++i) { - if (priv->depth_blt_fprogram_id[i]) { - GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i])); + for (i = 0; i < tex_type_count; ++i) + { + if (priv->depth_blt_fprogram_id_full[i]) + { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_full[i])); + } + if (priv->depth_blt_fprogram_id_masked[i]) + { + GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_masked[i])); } } LEAVE_GL(); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index f28505313d..20c509d6dc 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -563,7 +563,7 @@ void device_context_remove(IWineD3DDeviceImpl *device, struct wined3d_context *c device->contexts = new_array; } -static void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect) +void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect) { IWineD3DStateBlockImpl *stateblock = device->stateBlock; WINED3DVIEWPORT *vp = &stateblock->viewport; @@ -582,7 +582,9 @@ void device_switch_onscreen_ds(IWineD3DDeviceImpl *device, if (device->onscreen_depth_stencil) { surface_load_ds_location(device->onscreen_depth_stencil, context, SFLAG_DS_OFFSCREEN); - surface_modify_ds_location(device->onscreen_depth_stencil, SFLAG_DS_OFFSCREEN); + surface_modify_ds_location(device->onscreen_depth_stencil, SFLAG_DS_OFFSCREEN, + device->onscreen_depth_stencil->ds_current_size.cx, + device->onscreen_depth_stencil->ds_current_size.cy); IWineD3DSurface_Release((IWineD3DSurface *)device->onscreen_depth_stencil); } device->onscreen_depth_stencil = depth_stencil; @@ -4371,6 +4373,61 @@ static BOOL is_full_clear(IWineD3DSurfaceImpl *target, const RECT *draw_rect, co return TRUE; } +static void prepare_ds_clear(IWineD3DSurfaceImpl *ds, struct wined3d_context *context, + DWORD location, const RECT *draw_rect, UINT rect_count, const RECT *clear_rect) +{ + RECT current_rect, r; + + if (ds->Flags & location) + SetRect(¤t_rect, 0, 0, + ds->ds_current_size.cx, + ds->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); + + IntersectRect(&r, draw_rect, ¤t_rect); + if (EqualRect(&r, draw_rect)) + { + /* current_rect ⊇ draw_rect, modify only. */ + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); + return; + } + + if (EqualRect(&r, ¤t_rect)) + { + /* draw_rect ⊇ current_rect, test if we're doing a full clear. */ + + if (!clear_rect) + { + /* Full clear, modify only. */ + surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom); + return; + } + + if (rect_count > 1) + { + /* Multiple clear rects, full load. Strictly speaking this can + * also be a full draw_rect clear, but it's probably rare enough + * that we don't care. */ + surface_load_ds_location(ds, context, location); + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); + return; + } + + IntersectRect(&r, draw_rect, clear_rect); + if (EqualRect(&r, draw_rect)) + { + /* clear_rect ⊇ draw_rect, modify only. */ + surface_modify_ds_location(ds, location, draw_rect->right, draw_rect->bottom); + return; + } + } + + /* Full load. */ + surface_load_ds_location(ds, context, location); + surface_modify_ds_location(ds, location, ds->ds_current_size.cx, ds->ds_current_size.cy); +} + /* Not called from the VTable (internal subroutine) */ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *target, DWORD Count, const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) @@ -4456,10 +4513,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfac if (location == SFLAG_DS_ONSCREEN && depth_stencil != This->onscreen_depth_stencil) device_switch_onscreen_ds(This, context, depth_stencil); - - if (!(depth_stencil->Flags & location) && !is_full_clear(depth_stencil, &draw_rect, clear_rect)) - surface_load_ds_location(depth_stencil, context, location); - surface_modify_ds_location(depth_stencil, location); + prepare_ds_clear(depth_stencil, context, location, &draw_rect, Count, clear_rect); glDepthMask(GL_TRUE); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE)); @@ -5941,7 +5995,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice * if (((IWineD3DSwapChainImpl *)This->swapchains[0])->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || This->depth_stencil->Flags & SFLAG_DISCARD) { - surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED); + surface_modify_ds_location(This->depth_stencil, SFLAG_DS_DISCARDED, + This->depth_stencil->currentDesc.Width, + This->depth_stencil->currentDesc.Height); if (This->depth_stencil == This->onscreen_depth_stencil) { IWineD3DSurface_Release((IWineD3DSurface *)This->onscreen_depth_stencil); diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 146d73a8f2..5f88f4ebbe 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -613,12 +613,29 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE] || This->stateBlock->renderState[WINED3DRS_ZENABLE]) { + RECT current_rect, draw_rect, r; + if (location == SFLAG_DS_ONSCREEN && This->depth_stencil != This->onscreen_depth_stencil) device_switch_onscreen_ds(This, context, This->depth_stencil); - surface_load_ds_location(This->depth_stencil, context, location); + + if (This->depth_stencil->Flags & location) + SetRect(¤t_rect, 0, 0, + This->depth_stencil->ds_current_size.cx, + This->depth_stencil->ds_current_size.cy); + else + SetRectEmpty(¤t_rect); + + device_get_draw_rect(This, &draw_rect); + + IntersectRect(&r, &draw_rect, ¤t_rect); + if (!EqualRect(&r, &draw_rect)) + surface_load_ds_location(This->depth_stencil, context, location); + + if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) + surface_modify_ds_location(This->depth_stencil, location, + This->depth_stencil->ds_current_size.cx, + This->depth_stencil->ds_current_size.cy); } - if (This->stateBlock->renderState[WINED3DRS_ZWRITEENABLE]) - surface_modify_ds_location(This->depth_stencil, location); } /* Ok, we will be updating the screen from here onwards so grab the lock */ diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 7648d153f7..aca9d0e27a 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -89,7 +89,8 @@ struct shader_glsl_priv { struct constant_heap vconst_heap; struct constant_heap pconst_heap; unsigned char *stack; - GLhandleARB depth_blt_program[tex_type_count]; + GLhandleARB depth_blt_program_full[tex_type_count]; + GLhandleARB depth_blt_program_masked[tex_type_count]; UINT next_constant_version; }; @@ -4463,10 +4464,12 @@ static void set_glsl_shader_program(const struct wined3d_context *context, } /* GL locking is done by the caller */ -static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type) +static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, enum tex_types tex_type, BOOL masked) { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; + const char *blt_pshader; + static const char *blt_vshader[] = { "#version 120\n" @@ -4478,7 +4481,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, "}\n" }; - static const char *blt_pshaders[tex_type_count] = + static const char *blt_pshaders_full[tex_type_count] = { /* tex_1d */ NULL, @@ -4508,7 +4511,44 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, "}\n", }; - if (!blt_pshaders[tex_type]) + static const char *blt_pshaders_masked[tex_type_count] = + { + /* tex_1d */ + NULL, + /* tex_2d */ + "#version 120\n" + "uniform sampler2D sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + /* tex_3d */ + NULL, + /* tex_cube */ + "#version 120\n" + "uniform samplerCube sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = textureCube(sampler, gl_TexCoord[0].xyz).x;\n" + "}\n", + /* tex_rect */ + "#version 120\n" + "#extension GL_ARB_texture_rectangle : enable\n" + "uniform sampler2DRect sampler;\n" + "uniform vec4 mask;\n" + "void main(void)\n" + "{\n" + " if (all(lessThan(gl_FragCoord.xy, mask.zw))) discard;\n" + " gl_FragDepth = texture2DRect(sampler, gl_TexCoord[0].xy).x;\n" + "}\n", + }; + + blt_pshader = masked ? blt_pshaders_masked[tex_type] : blt_pshaders_full[tex_type]; + if (!blt_pshader) { FIXME("tex_type %#x not supported\n", tex_type); tex_type = tex_2d; @@ -4519,7 +4559,7 @@ static GLhandleARB create_glsl_blt_shader(const struct wined3d_gl_info *gl_info, GL_EXTCALL(glCompileShaderARB(vshader_id)); pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB)); - GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshaders[tex_type], NULL)); + GL_EXTCALL(glShaderSourceARB(pshader_id, 1, &blt_pshader, NULL)); GL_EXTCALL(glCompileShaderARB(pshader_id)); program_id = GL_EXTCALL(glCreateProgramObjectARB()); @@ -4581,21 +4621,34 @@ static void shader_glsl_select(const struct wined3d_context *context, BOOL usePS } /* GL locking is done by the caller */ -static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) { +static void shader_glsl_select_depth_blt(IWineD3DDevice *iface, + enum tex_types tex_type, const SIZE *ds_mask_size) +{ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; + BOOL masked = ds_mask_size->cx && ds_mask_size->cy; struct shader_glsl_priv *priv = This->shader_priv; - GLhandleARB *blt_program = &priv->depth_blt_program[tex_type]; + GLhandleARB *blt_program; + GLint loc; - if (!*blt_program) { - GLint loc; - *blt_program = create_glsl_blt_shader(gl_info, tex_type); + blt_program = masked ? &priv->depth_blt_program_masked[tex_type] : &priv->depth_blt_program_full[tex_type]; + if (!*blt_program) + { + *blt_program = create_glsl_blt_shader(gl_info, tex_type, masked); loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "sampler")); GL_EXTCALL(glUseProgramObjectARB(*blt_program)); GL_EXTCALL(glUniform1iARB(loc, 0)); - } else { + } + else + { GL_EXTCALL(glUseProgramObjectARB(*blt_program)); } + + if (masked) + { + loc = GL_EXTCALL(glGetUniformLocationARB(*blt_program, "mask")); + GL_EXTCALL(glUniform4fARB(loc, 0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy)); + } } /* GL locking is done by the caller */ @@ -4831,9 +4884,13 @@ static void shader_glsl_free(IWineD3DDevice *iface) { ENTER_GL(); for (i = 0; i < tex_type_count; ++i) { - if (priv->depth_blt_program[i]) + if (priv->depth_blt_program_full[i]) + { + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_full[i])); + } + if (priv->depth_blt_program_masked[i]) { - GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program[i])); + GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_program_masked[i])); } } LEAVE_GL(); diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 683653245d..b0151788fe 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -1403,7 +1403,7 @@ static void shader_cleanup(IWineD3DBaseShader *iface) static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {} static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {} -static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {} +static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size) {} static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {} static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {} static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {} diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 8a934a8209..6ec3ed9f54 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -4092,7 +4092,8 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl glGetIntegerv(info.binding, &old_binding); glBindTexture(info.bind_target, texture); - device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, info.tex_type); + device->shader_backend->shader_select_depth_blt((IWineD3DDevice *)device, + info.tex_type, &This->ds_current_size); glBegin(GL_TRIANGLE_STRIP); glTexCoord3fv(info.coords[0]); @@ -4112,13 +4113,16 @@ static void surface_depth_blt(IWineD3DSurfaceImpl *This, const struct wined3d_gl device->shader_backend->shader_deselect_depth_blt((IWineD3DDevice *)device); } -void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, DWORD location) +void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, + DWORD location, UINT w, UINT h) { - TRACE("surface %p, new location %#x.\n", surface, location); + TRACE("surface %p, new location %#x, w %u, h %u.\n", surface, location, w, h); if (location & ~SFLAG_DS_LOCATIONS) FIXME("Invalid location (%#x) specified.\n", location); + surface->ds_current_size.cx = w; + surface->ds_current_size.cy = h; surface->Flags &= ~SFLAG_DS_LOCATIONS; surface->Flags |= location; } @@ -4134,7 +4138,14 @@ void surface_load_ds_location(IWineD3DSurfaceImpl *surface, struct wined3d_conte /* TODO: Make this work for modes other than FBO */ if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return; - if (surface->Flags & location) + if (!(surface->Flags & location)) + { + surface->ds_current_size.cx = 0; + surface->ds_current_size.cy = 0; + } + + if (surface->ds_current_size.cx == surface->currentDesc.Width + && surface->ds_current_size.cy == surface->currentDesc.Height) { TRACE("Location (%#x) is already up to date.\n", location); return; @@ -4250,6 +4261,8 @@ void surface_load_ds_location(IWineD3DSurfaceImpl *surface, struct wined3d_conte } surface->Flags |= location; + surface->ds_current_size.cx = surface->currentDesc.Width; + surface->ds_current_size.cy = surface->currentDesc.Height; } static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index e1cb2ad74a..a7b6a70ab4 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -468,7 +468,9 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO if (This->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || This->device->depth_stencil->Flags & SFLAG_DISCARD) { - surface_modify_ds_location(This->device->depth_stencil, SFLAG_DS_DISCARDED); + surface_modify_ds_location(This->device->depth_stencil, SFLAG_DS_DISCARDED, + This->device->depth_stencil->currentDesc.Width, + This->device->depth_stencil->currentDesc.Height); if (This->device->depth_stencil == This->device->onscreen_depth_stencil) { IWineD3DSurface_Release((IWineD3DSurface *)This->device->onscreen_depth_stencil); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3e54ad8a5c..c2e17b1d9c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -713,7 +713,7 @@ struct wined3d_context; typedef struct { void (*shader_handle_instruction)(const struct wined3d_shader_instruction *); void (*shader_select)(const struct wined3d_context *context, BOOL usePS, BOOL useVS); - void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type); + void (*shader_select_depth_blt)(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size); void (*shader_deselect_depth_blt)(IWineD3DDevice *iface); void (*shader_update_float_vertex_constants)(IWineD3DDevice *iface, UINT start, UINT count); void (*shader_update_float_pixel_constants)(IWineD3DDevice *iface, UINT start, UINT count); @@ -1725,6 +1725,7 @@ struct IWineD3DDeviceImpl BOOL device_context_add(IWineD3DDeviceImpl *device, struct wined3d_context *context) DECLSPEC_HIDDEN; void device_context_remove(IWineD3DDeviceImpl *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void device_get_draw_rect(IWineD3DDeviceImpl *device, RECT *rect) DECLSPEC_HIDDEN; HRESULT device_init(IWineD3DDeviceImpl *device, IWineD3DImpl *wined3d, UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent, IWineD3DDeviceParent *device_parent) DECLSPEC_HIDDEN; @@ -2090,6 +2091,7 @@ struct IWineD3DSurfaceImpl struct list renderbuffers; renderbuffer_entry_t *current_renderbuffer; + SIZE ds_current_size; /* DirectDraw clippers */ IWineD3DClipper *clipper; @@ -2677,7 +2679,7 @@ void surface_add_dirty_rect(IWineD3DSurfaceImpl *surface, const RECT *dirty_rect GLenum surface_get_gl_buffer(IWineD3DSurfaceImpl *surface) DECLSPEC_HIDDEN; void surface_load_ds_location(IWineD3DSurfaceImpl *surface, struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; -void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, DWORD location) DECLSPEC_HIDDEN; +void surface_modify_ds_location(IWineD3DSurfaceImpl *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; void surface_set_compatible_renderbuffer(IWineD3DSurfaceImpl *surface, unsigned int width, unsigned int height) DECLSPEC_HIDDEN; void surface_set_texture_name(IWineD3DSurfaceImpl *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN; -- 2.32.0.93.g670b81a890