From 99bfd817141ca32f9c50e539aa4d0dcbfded24b7 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 5 Apr 2011 19:01:30 +0200 Subject: [PATCH] wined3d: Allow depth and stencil clears on surfaces other than the current depth / stencil buffer. --- dlls/wined3d/context.c | 8 ++++---- dlls/wined3d/device.c | 32 ++++++++++++++++++++++---------- dlls/wined3d/surface.c | 18 ++++++------------ dlls/wined3d/wined3d_private.h | 4 ++-- 4 files changed, 34 insertions(+), 28 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 8ffb30c6c16..5b5ae5a98d5 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2,7 +2,7 @@ * Context and render target management in wined3d * * Copyright 2007-2008 Stefan Dösinger for CodeWeavers - * Copyright 2009-2010 Henri Verbeet for CodeWeavers + * Copyright 2009-2011 Henri Verbeet for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1915,7 +1915,7 @@ static struct wined3d_context *FindContext(IWineD3DDeviceImpl *This, IWineD3DSur /* Context activation is done by the caller. */ static void context_apply_draw_buffers(struct wined3d_context *context, UINT rt_count, IWineD3DSurfaceImpl **rts) { - if (!surface_is_offscreen(rts[0])) + if (rt_count && !surface_is_offscreen(rts[0])) { ENTER_GL(); glDrawBuffer(surface_get_gl_buffer(rts[0])); @@ -1951,7 +1951,7 @@ static void context_apply_draw_buffers(struct wined3d_context *context, UINT rt_ } else { - glDrawBuffer(rts[0]->resource.device->offscreenBuffer); + glDrawBuffer(rt_count ? rts[0]->resource.device->offscreenBuffer : GL_NONE); checkGLcall("glDrawBuffer()"); } LEAVE_GL(); @@ -2086,7 +2086,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceIm ENTER_GL(); - if (surface_is_offscreen(rts[0])) + if (!rt_count || surface_is_offscreen(rts[0])) { for (i = 0; i < rt_count; ++i) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2d50caab838..5e9f04ebf00 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -652,15 +652,15 @@ static void prepare_ds_clear(IWineD3DSurfaceImpl *ds, struct wined3d_context *co /* Do not call while under the GL lock. */ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, IWineD3DSurfaceImpl **rts, - UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags, - const WINED3DCOLORVALUE *color, float depth, DWORD stencil) + IWineD3DSurfaceImpl *depth_stencil, UINT rect_count, const RECT *rects, const RECT *draw_rect, + DWORD flags, const WINED3DCOLORVALUE *color, float depth, DWORD stencil) { const RECT *clear_rect = (rect_count > 0 && rects) ? (const RECT *)rects : NULL; - IWineD3DSurfaceImpl *depth_stencil = device->depth_stencil; - IWineD3DSurfaceImpl *target = rts[0]; + IWineD3DSurfaceImpl *target = rt_count ? rts[0] : NULL; UINT drawable_width, drawable_height; struct wined3d_context *context; GLbitfield clear_mask = 0; + BOOL render_offscreen; unsigned int i; /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the @@ -694,7 +694,17 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I return WINED3D_OK; } - target->get_drawable_size(context, &drawable_width, &drawable_height); + if (target) + { + render_offscreen = context->render_offscreen; + target->get_drawable_size(context, &drawable_width, &drawable_height); + } + else + { + render_offscreen = FALSE; + drawable_width = depth_stencil->pow2Width; + drawable_height = depth_stencil->pow2Height; + } ENTER_GL(); @@ -715,7 +725,7 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I if (flags & WINED3DCLEAR_ZBUFFER) { - DWORD location = context->render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; + DWORD location = render_offscreen ? SFLAG_DS_OFFSCREEN : SFLAG_DS_ONSCREEN; if (location == SFLAG_DS_ONSCREEN && depth_stencil != device->onscreen_depth_stencil) { @@ -752,7 +762,7 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I if (!clear_rect) { - if (context->render_offscreen) + if (render_offscreen) { glScissor(draw_rect->left, draw_rect->top, draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top); @@ -789,7 +799,7 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I continue; } - if (context->render_offscreen) + if (render_offscreen) { glScissor(current_rect.left, current_rect.top, current_rect.right - current_rect.left, current_rect.bottom - current_rect.top); @@ -808,7 +818,8 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I LEAVE_GL(); - if (wined3d_settings.strict_draw_ordering || (target->container.type == WINED3D_CONTAINER_SWAPCHAIN + if (wined3d_settings.strict_draw_ordering || (flags & WINED3DCLEAR_TARGET + && target->container.type == WINED3D_CONTAINER_SWAPCHAIN && target->container.u.swapchain->front_buffer == target)) wglFlush(); /* Flush to ensure ordering across contexts. */ @@ -4816,7 +4827,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD rect device_get_draw_rect(device, &draw_rect); return device_clear_render_targets(device, device->adapter->gl_info.limits.buffers, - device->render_targets, rect_count, rects, &draw_rect, flags, &c, depth, stencil); + device->render_targets, device->depth_stencil, rect_count, rects, + &draw_rect, flags, &c, depth, stencil); } /***** diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index e62f1f372f2..58cd1972daf 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1112,7 +1112,7 @@ void surface_set_compatible_renderbuffer(IWineD3DSurfaceImpl *surface, IWineD3DS unsigned int src_width, src_height; unsigned int width, height; - if (rt->resource.format->id != WINED3DFMT_NULL) + if (rt && rt->resource.format->id != WINED3DFMT_NULL) { width = rt->pow2Width; height = rt->pow2Height; @@ -3897,16 +3897,10 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *dst_surface, /* Do not call while under the GL lock. */ static HRESULT wined3d_surface_depth_fill(IWineD3DSurfaceImpl *surface, const RECT *rect, float depth) { - IWineD3DDeviceImpl *device = surface->resource.device; + const RECT draw_rect = {0, 0, surface->resource.width, surface->resource.height}; - if (surface != device->depth_stencil) - { - FIXME("Depth fill is only implemented for the current depth / stencil buffer.\n"); - return WINED3DERR_INVALIDCALL; - } - - return IWineD3DDevice_Clear((IWineD3DDevice *)device, !!rect, rect, - WINED3DCLEAR_ZBUFFER, 0x00000000, depth, 0); + return device_clear_render_targets(surface->resource.device, 0, NULL, surface, + !!rect, rect, &draw_rect, WINED3DCLEAR_ZBUFFER, 0, depth, 0); } /* Do not call while under the GL lock. */ @@ -4921,8 +4915,8 @@ static HRESULT ffp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceIm { const RECT draw_rect = {0, 0, dst_surface->resource.width, dst_surface->resource.height}; - return device_clear_render_targets(device, 1 /* rt_count */, &dst_surface, 1 /* rect_count */, - dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f /* depth */, 0 /* stencil */); + return device_clear_render_targets(device, 1, &dst_surface, NULL, + 1, dst_rect, &draw_rect, WINED3DCLEAR_TARGET, color, 0.0f, 0); } const struct blit_shader ffp_blit = { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 15a18ddc23e..eb015eb2541 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1769,8 +1769,8 @@ struct IWineD3DDeviceImpl }; HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, IWineD3DSurfaceImpl **rts, - UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags, - const WINED3DCOLORVALUE *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; + IWineD3DSurfaceImpl *depth_stencil, UINT rect_count, const RECT *rects, const RECT *draw_rect, + DWORD flags, const WINED3DCOLORVALUE *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; 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;