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

Adam Martinson amartinson at codeweavers.com
Thu Apr 7 11:57:00 CDT 2011


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

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index be2ad3c..70a0f6f 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)
 {
@@ -1404,6 +1425,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;
@@ -2109,7 +2131,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);
+            }
             glReadBuffer(GL_NONE);
             checkGLcall("glReadBuffer");
         }
@@ -2184,8 +2224,16 @@ BOOL context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImp
         else
         {
             ENTER_GL();
-            context_apply_fbo_state(context, GL_FRAMEBUFFER, device->render_targets,
-                    device->depth_stencil, SFLAG_INTEXTURE);
+            if (context->device_fbo != NULL)
+            {
+                context_apply_device_fbo(context);
+            }
+            else
+            {
+                context_apply_fbo_state(context, GL_FRAMEBUFFER, device->render_targets,
+                                        device->depth_stencil, SFLAG_INTEXTURE);
+                context->device_fbo = context->current_fbo;
+            }
             glReadBuffer(GL_NONE);
             checkGLcall("glReadBuffer");
             LEAVE_GL();
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 7b4ad8a..076d632 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->context_count; ++i)
+    {
+        This->contexts[i]->device_fbo = NULL;
+    }
+}
+
 static void device_preload_texture(const struct wined3d_state *state, unsigned int idx)
 {
     struct wined3d_texture *texture;
@@ -5879,6 +5888,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);
@@ -5938,6 +5948,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);
 
@@ -6712,6 +6723,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;
@@ -6722,6 +6734,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;
                     }
                 }
 
@@ -6729,7 +6742,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 79b7f57..932dee1 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


--------------000206080807090606070809--



More information about the wine-devel mailing list