[PATCH 2/3] wined3d: Track when the FBO is dirty.

Adam Martinson amartinson at codeweavers.com
Wed Apr 6 23:28:25 CDT 2011


---
 dlls/wined3d/context.c         |   49 +++++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/device.c          |   16 +++++++++++++
 dlls/wined3d/wined3d_private.h |    1 +
 3 files changed, 65 insertions(+), 1 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 5b5ae5a..a074fa7 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -374,6 +374,9 @@ static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum targ
     entry->depth_stencil = depth_stencil;
     entry->location = location;
     entry->attached = FALSE;
+
+    if (entry == context->device_fbo)
+        context->device_fbo = NULL;
 }
 
 /* GL locking is done by the caller */
@@ -473,6 +476,24 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
 }
 
 /* GL locking is done by the caller */
+static void context_apply_device_fbo(struct wined3d_context *context)
+{
+    struct fbo_entry *entry = context->device_fbo;
+    if (context->rebind_fbo)
+    {
+        context_bind_fbo(context, GL_FRAMEBUFFER, NULL);
+        context->rebind_fbo = FALSE;
+    }
+
+    list_remove(&entry->entry);
+    list_add_head(&context->fbo_list, &entry->entry);
+
+    context->current_fbo = entry;
+    context_apply_fbo_entry(context, GL_FRAMEBUFFER, entry);
+    context_check_fbo_status(context, GL_FRAMEBUFFER);
+}
+
+/* GL locking is done by the caller */
 static void context_apply_fbo_state(struct wined3d_context *context, GLenum target,
         IWineD3DSurfaceImpl **render_targets, IWineD3DSurfaceImpl *depth_stencil, DWORD location)
 {
@@ -1406,6 +1427,7 @@ struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain,
 
     ret->render_offscreen = surface_is_offscreen(target);
     ret->draw_buffer_dirty = TRUE;
+    ret->device_fbo = NULL;
     ret->valid = 1;
 
     ret->glCtx = ctx;
@@ -2097,7 +2119,25 @@ BOOL context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceIm
                 context->blit_targets[i] = NULL;
                 ++i;
             }
-            context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, depth_stencil, SFLAG_INTEXTURE);
+
+            if (rt_count == device->adapter->gl_info.limits.buffers &&
+                rts == device->render_targets &&
+                depth_stencil == device->depth_stencil)
+            {
+                if (context->device_fbo != NULL)
+                {
+                    context_apply_device_fbo(context);
+                }
+                else
+                {
+                    context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, depth_stencil, SFLAG_INTEXTURE);
+                    context->device_fbo = context->current_fbo;
+                }
+            }
+            else
+            {
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, context->blit_targets, depth_stencil, SFLAG_INTEXTURE);
+            }
         }
         else
         {
@@ -2160,12 +2200,19 @@ BOOL context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImp
             context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
             LEAVE_GL();
         }
+        else if (context->device_fbo != NULL)
+        {
+            ENTER_GL();
+            context_apply_device_fbo(context);
+            LEAVE_GL();
+        }
         else
         {
             ENTER_GL();
             context_apply_fbo_state(context, GL_FRAMEBUFFER, device->render_targets,
                     device->depth_stencil, SFLAG_INTEXTURE);
             LEAVE_GL();
+            context->device_fbo = context->current_fbo;
         }
     }
 
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index e91a078..11a395e 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -453,6 +453,15 @@ void device_update_stream_info(IWineD3DDeviceImpl *device, const struct wined3d_
     }
 }
 
+static inline void IWineD3DDeviceImpl_MarkFBODirty(IWineD3DDeviceImpl *This)
+{
+    UINT i;
+    for (i = 0; i < This->numContexts; ++i)
+    {
+        This->contexts[i]->device_fbo = NULL;
+    }
+}
+
 static void device_preload_texture(const struct wined3d_state *state, unsigned int idx)
 {
     struct wined3d_texture *texture;
@@ -5866,6 +5875,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface,
 
     if (render_target) IWineD3DSurface_AddRef(render_target);
     device->render_targets[render_target_idx] = (IWineD3DSurfaceImpl *)render_target;
+    IWineD3DDeviceImpl_MarkFBODirty(device);
     /* Release after the assignment, to prevent device_resource_released()
      * from seeing the surface as still in use. */
     if (prev) IWineD3DSurface_Release((IWineD3DSurface *)prev);
@@ -5925,6 +5935,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *
 
     tmp = This->depth_stencil;
     This->depth_stencil = (IWineD3DSurfaceImpl *)depth_stencil;
+    IWineD3DDeviceImpl_MarkFBODirty(This);
     if (This->depth_stencil) IWineD3DSurface_AddRef((IWineD3DSurface *)This->depth_stencil);
     if (tmp) IWineD3DSurface_Release((IWineD3DSurface *)tmp);
 
@@ -6699,6 +6710,7 @@ void device_resource_released(struct IWineD3DDeviceImpl *device, struct wined3d_
     {
         case WINED3DRTYPE_SURFACE:
             {
+                BOOL fbo_dirty = FALSE;
                 IWineD3DSurfaceImpl *surface = surface_from_resource(resource);
 
                 if (!device->d3d_initialized) break;
@@ -6709,6 +6721,7 @@ void device_resource_released(struct IWineD3DDeviceImpl *device, struct wined3d_
                     {
                         ERR("Surface %p is still in use as render target %u.\n", surface, i);
                         device->render_targets[i] = NULL;
+                        fbo_dirty = TRUE;
                     }
                 }
 
@@ -6716,7 +6729,10 @@ void device_resource_released(struct IWineD3DDeviceImpl *device, struct wined3d_
                 {
                     ERR("Surface %p is still in use as depth/stencil buffer.\n", surface);
                     device->depth_stencil = NULL;
+                    fbo_dirty = TRUE;
                 }
+
+                if (fbo_dirty) IWineD3DDeviceImpl_MarkFBODirty(device);
             }
             break;
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 95baf38..97a07f6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1094,6 +1094,7 @@ struct wined3d_context
     struct list             fbo_list;
     struct list             fbo_destroy_list;
     struct fbo_entry        *current_fbo;
+    struct fbo_entry        *device_fbo;
     GLuint                  dst_fbo;
     GLuint                  fbo_read_binding;
     GLuint                  fbo_draw_binding;
-- 
1.7.1


--------------000503060008050103090709--



More information about the wine-devel mailing list