From 0d446053da05567177da12371633336ed2add9d0 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 11 May 2009 16:43:49 +0200 Subject: [PATCH] wined3d: Don't create more than WINED3D_MAX_FBO_ENTRIES FBO entries. This essentially turns the FBO entry list into an LRU cache. --- dlls/wined3d/context.c | 44 ++++++++++++++++++++++++++++++---- dlls/wined3d/wined3d_private.h | 3 +++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 2c6703f360..8a4296d26a 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -53,12 +53,10 @@ void context_bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) checkGLcall("glBindFramebuffer()"); } -static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) +static void context_clean_fbo_attachments(IWineD3DDeviceImpl *This) { unsigned int i; - GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fbo)); - checkGLcall("glBindFramebuffer()"); for (i = 0; i < GL_LIMITS(buffers); ++i) { GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, 0, 0)); @@ -66,6 +64,15 @@ static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) } GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0)); checkGLcall("glFramebufferTexture2D()"); +} + +static void context_destroy_fbo(IWineD3DDeviceImpl *This, const GLuint *fbo) +{ + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fbo)); + checkGLcall("glBindFramebuffer()"); + + context_clean_fbo_attachments(This); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); checkGLcall("glBindFramebuffer()"); GL_EXTCALL(glDeleteFramebuffersEXT(1, fbo)); @@ -230,6 +237,19 @@ static struct fbo_entry *context_create_fbo_entry(IWineD3DDevice *iface) return entry; } +static void context_reuse_fbo_entry(IWineD3DDevice *iface, struct fbo_entry *entry) +{ + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, entry->id)); + checkGLcall("glBindFramebuffer()"); + context_clean_fbo_attachments(This); + + memcpy(entry->render_targets, This->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)); + entry->depth_stencil = This->stencilBufferTarget; + entry->attached = FALSE; +} + static void context_destroy_fbo_entry(IWineD3DDeviceImpl *This, struct fbo_entry *entry) { if (entry->id) @@ -253,12 +273,26 @@ static struct fbo_entry *context_find_fbo_entry(IWineD3DDevice *iface, WineD3DCo if (!memcmp(entry->render_targets, This->render_targets, GL_LIMITS(buffers) * sizeof(*entry->render_targets)) && entry->depth_stencil == This->stencilBufferTarget) { + list_remove(&entry->entry); + list_add_head(&context->fbo_list, &entry->entry); return entry; } } - entry = context_create_fbo_entry(iface); - list_add_head(&context->fbo_list, &entry->entry); + if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES) + { + entry = context_create_fbo_entry(iface); + list_add_head(&context->fbo_list, &entry->entry); + ++context->fbo_entry_count; + } + else + { + entry = LIST_ENTRY(list_tail(&context->fbo_list), struct fbo_entry, entry); + context_reuse_fbo_entry(iface, entry); + list_remove(&entry->entry); + list_add_head(&context->fbo_list, &entry->entry); + } + return entry; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c227e9cbe6..cbefa9ab6b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1167,6 +1167,8 @@ enum fogsource { FOGSOURCE_COORD, }; +#define WINED3D_MAX_FBO_ENTRIES 64 + /* The new context manager that should deal with onscreen and offscreen rendering */ struct WineD3DContext { /* State dirtification @@ -1214,6 +1216,7 @@ struct WineD3DContext { GLint aux_buffers; /* FBOs */ + UINT fbo_entry_count; struct list fbo_list; struct fbo_entry *current_fbo; GLuint src_fbo;