[PATCH 1/4] wined3d: Verify we have at least one framebuffer attachment before doing clears or draws.

Henri Verbeet hverbeet at codeweavers.com
Wed Jan 26 12:45:02 CST 2011


---
 dlls/wined3d/context.c         |   32 ++++++++++++++++++++++++++++++--
 dlls/wined3d/device.c          |    7 ++++++-
 dlls/wined3d/drawprim.c        |    7 ++++++-
 dlls/wined3d/wined3d_private.h |    4 ++--
 4 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 5ecd748..d9bb5d8 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -2053,13 +2053,33 @@ void context_apply_blit_state(struct wined3d_context *context, IWineD3DDeviceImp
     SetupForBlit(device, context);
 }
 
+static BOOL context_validate_rt_config(UINT rt_count,
+        IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *ds)
+{
+    unsigned int i;
+
+    if (ds) return TRUE;
+
+    for (i = 0; i < rt_count; ++i)
+    {
+        if (rts[i]) return TRUE;
+    }
+
+    WARN("Invalid render target config, need at least one attachment.\n");
+    return FALSE;
+}
+
 /* Context activation is done by the caller. */
-void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device,
+BOOL context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device,
         UINT rt_count, IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *depth_stencil)
 {
     const struct StateEntry *state_table = device->StateTable;
     UINT i;
 
+    if (!context_validate_rt_config(rt_count, rts, depth_stencil))
+        return FALSE;
+
+
     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
     {
         context_validate_onscreen_formats(device, context, depth_stencil);
@@ -2108,14 +2128,20 @@ void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceIm
     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_table);
     Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_table);
     Context_MarkStateDirty(context, STATE_SCISSORRECT, state_table);
+
+    return TRUE;
 }
 
 /* Context activation is done by the caller. */
-void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device)
+BOOL context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device)
 {
     const struct StateEntry *state_table = device->StateTable;
     unsigned int i;
 
+    if (!context_validate_rt_config(context->gl_info->limits.buffers,
+            device->render_targets, device->depth_stencil))
+        return FALSE;
+
     /* Preload resources before FBO setup. Texture preload in particular may
      * result in changes to the current FBO, due to using e.g. FBO blits for
      * updating a resource location. */
@@ -2166,6 +2192,8 @@ void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImp
     LEAVE_GL();
     context->numDirtyEntries = 0; /* This makes the whole list clean */
     context->last_was_blit = FALSE;
+
+    return TRUE;
 }
 
 static void context_setup_target(IWineD3DDeviceImpl *device,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 71c63b2..92bc151 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -686,7 +686,12 @@ HRESULT device_clear_render_targets(IWineD3DDeviceImpl *device, UINT rt_count, I
         return WINED3D_OK;
     }
 
-    context_apply_clear_state(context, device, rt_count, rts, depth_stencil);
+    if (!context_apply_clear_state(context, device, rt_count, rts, depth_stencil))
+    {
+        context_release(context);
+        WARN("Failed to apply clear state, skipping clear.\n");
+        return WINED3D_OK;
+    }
 
     target->get_drawable_size(context, &drawable_width, &drawable_height);
 
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index a3b0053..e476d64 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -591,7 +591,12 @@ void drawPrimitive(IWineD3DDeviceImpl *device, UINT index_count, UINT StartIdx,
         return;
     }
 
-    context_apply_draw_state(context, device);
+    if (!context_apply_draw_state(context, device))
+    {
+        context_release(context);
+        WARN("Unable to apply draw state, skipping draw.\n");
+        return;
+    }
 
     if (device->depth_stencil)
     {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 96b845f..2ec621a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1212,9 +1212,9 @@ void context_alloc_event_query(struct wined3d_context *context,
 void context_alloc_occlusion_query(struct wined3d_context *context,
         struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
 void context_apply_blit_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
-void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device,
+BOOL context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceImpl *device,
         UINT rt_count, IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN;
-void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
+BOOL context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
 void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
         IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil, DWORD location) DECLSPEC_HIDDEN;
 void context_attach_depth_stencil_fbo(struct wined3d_context *context,
-- 
1.7.3.4




More information about the wine-patches mailing list