[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