[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