[PATCH 2/6] wined3d: Keep track of FBOs through the GL names (v2).

Stefan Dösinger stefan at codeweavers.com
Wed Oct 28 09:29:18 CDT 2015


Version 2: Don't use fbo_entry->d3d_* for logging, plan for it to go
away. The disadvantage is now that we don't know the d3d properties once
we find out that an FBO doesn't work and need a full TRACE log for this
information, but I think that's something we can live with.

If there is a prettier way to find the texture target of a GL texture
name please advise. I couldn't find any.

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
---
 dlls/wined3d/context.c         | 393 +++++++++++++++++++++++++++--------------
 dlls/wined3d/wined3d_private.h |  17 +-
 2 files changed, 279 insertions(+), 131 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 978f7d7..2bd9eb0 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -120,57 +120,39 @@ static void context_attach_depth_stencil_rb(const struct wined3d_gl_info *gl_inf
 
 /* Context activation is done by the caller. */
 static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
-        GLenum fbo_target, struct wined3d_surface *depth_stencil, DWORD location)
+        GLenum fbo_target, const struct wined3d_fbo_resource *resource, BOOL rb_namespace,
+        DWORD format_flags, GLuint rb_override)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
-    TRACE("Attach depth stencil %p\n", depth_stencil);
-
-    if (depth_stencil)
+    if (resource->object)
     {
-        DWORD format_flags = depth_stencil->container->resource.format_flags;
+        TRACE("Attach depth stencil %u.\n", resource->object);
 
-        if (depth_stencil->current_renderbuffer)
+        if (rb_override)
         {
             context_attach_depth_stencil_rb(gl_info, fbo_target,
-                    format_flags, depth_stencil->current_renderbuffer->id);
+                    format_flags, rb_override);
+        }
+        else if (rb_namespace)
+        {
+            context_attach_depth_stencil_rb(gl_info, fbo_target,
+                    format_flags, resource->object);
         }
         else
         {
-            switch (location)
+            if (format_flags & WINED3DFMT_FLAG_DEPTH)
             {
-                case WINED3D_LOCATION_TEXTURE_RGB:
-                case WINED3D_LOCATION_TEXTURE_SRGB:
-                    if (format_flags & WINED3DFMT_FLAG_DEPTH)
-                    {
-                        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
-                                depth_stencil->texture_target, depth_stencil->container->texture_rgb.name,
-                                depth_stencil->texture_level);
-                        checkGLcall("glFramebufferTexture2D()");
-                    }
-
-                    if (format_flags & WINED3DFMT_FLAG_STENCIL)
-                    {
-                        gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
-                                depth_stencil->texture_target, depth_stencil->container->texture_rgb.name,
-                                depth_stencil->texture_level);
-                        checkGLcall("glFramebufferTexture2D()");
-                    }
-                    break;
-
-                case WINED3D_LOCATION_RB_MULTISAMPLE:
-                    context_attach_depth_stencil_rb(gl_info, fbo_target,
-                            format_flags, depth_stencil->rb_multisample);
-                    break;
-
-                case WINED3D_LOCATION_RB_RESOLVED:
-                    context_attach_depth_stencil_rb(gl_info, fbo_target,
-                            format_flags, depth_stencil->rb_resolved);
-                    break;
+                gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT,
+                        resource->target, resource->object, resource->level);
+                checkGLcall("glFramebufferTexture2D()");
+            }
 
-                default:
-                    ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location);
-                    break;
+            if (format_flags & WINED3DFMT_FLAG_STENCIL)
+            {
+                gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_STENCIL_ATTACHMENT,
+                        resource->target, resource->object, resource->level);
+                checkGLcall("glFramebufferTexture2D()");
             }
         }
 
@@ -188,6 +170,8 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
     }
     else
     {
+        TRACE("Attach depth stencil 0.\n");
+
         gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
         checkGLcall("glFramebufferTexture2D()");
 
@@ -198,42 +182,26 @@ static void context_attach_depth_stencil_fbo(struct wined3d_context *context,
 
 /* Context activation is done by the caller. */
 static void context_attach_surface_fbo(struct wined3d_context *context,
-        GLenum fbo_target, DWORD idx, struct wined3d_surface *surface, DWORD location)
+        GLenum fbo_target, DWORD idx, const struct wined3d_fbo_resource *resource, BOOL rb_namespace)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
-    TRACE("Attach surface %p to %u\n", surface, idx);
+    TRACE("Attach GL object %u to %u.\n", resource->object, idx);
 
-    if (surface && surface->resource.format->id != WINED3DFMT_NULL)
+    if (resource->object)
     {
-        BOOL srgb;
 
-        switch (location)
+        if (rb_namespace)
         {
-            case WINED3D_LOCATION_TEXTURE_RGB:
-            case WINED3D_LOCATION_TEXTURE_SRGB:
-                srgb = location == WINED3D_LOCATION_TEXTURE_SRGB;
-                gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
-                        surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
-                        surface->texture_level);
-                checkGLcall("glFramebufferTexture2D()");
-                break;
-
-            case WINED3D_LOCATION_RB_MULTISAMPLE:
-                gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
-                        GL_RENDERBUFFER, surface->rb_multisample);
-                checkGLcall("glFramebufferRenderbuffer()");
-                break;
-
-            case WINED3D_LOCATION_RB_RESOLVED:
-                gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
-                        GL_RENDERBUFFER, surface->rb_resolved);
-                checkGLcall("glFramebufferRenderbuffer()");
-                break;
-
-            default:
-                ERR("Unsupported location %s (%#x).\n", wined3d_debug_location(location), location);
-                break;
+            gl_info->fbo_ops.glFramebufferRenderbuffer(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+                    GL_RENDERBUFFER, resource->object);
+            checkGLcall("glFramebufferRenderbuffer()");
+        }
+        else
+        {
+            gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
+                    resource->target, resource->object, resource->level);
+            checkGLcall("glFramebufferTexture2D()");
         }
     }
     else
@@ -243,6 +211,94 @@ static void context_attach_surface_fbo(struct wined3d_context *context,
     }
 }
 
+static void context_dump_fbo_attachment(const struct wined3d_gl_info *gl_info, GLenum target,
+        GLenum attachment, const char *name_string)
+{
+    GLint type, name, samples, width, height, old_texture, level, face, fmt, tex_target;
+
+    gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment,
+            GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &name);
+    gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment,
+            GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type);
+
+    if (type == GL_RENDERBUFFER)
+    {
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, name);
+        gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
+        gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
+        if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
+            gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
+        else
+            samples = 1;
+        gl_info->fbo_ops.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_INTERNAL_FORMAT, &fmt);
+        FIXME("\t%s: renderbuffer %d, %dx%d, %d samples, format %x.\n",
+                name_string, name, width, height, samples, fmt);
+    }
+    else if (type == GL_TEXTURE)
+    {
+        const char *tex_type_str;
+
+        gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment,
+                GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &level);
+        gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv(target, attachment,
+                GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &face);
+
+        if (face)
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP, &old_texture);
+
+            glBindTexture(GL_TEXTURE_CUBE_MAP, name);
+            glGetTexLevelParameteriv(face, level, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+            glGetTexLevelParameteriv(face, level, GL_TEXTURE_WIDTH, &width);
+            glGetTexLevelParameteriv(face, level, GL_TEXTURE_HEIGHT, &height);
+
+            tex_target = GL_TEXTURE_CUBE_MAP;
+            tex_type_str = "cube";
+        }
+        else
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture);
+            while (gl_info->gl_ops.gl.p_glGetError());
+
+            glBindTexture(GL_TEXTURE_2D, name);
+            if (!gl_info->gl_ops.gl.p_glGetError())
+            {
+                tex_target = GL_TEXTURE_2D;
+                tex_type_str = "2d";
+            }
+            else
+            {
+                glBindTexture(GL_TEXTURE_2D, old_texture);
+                gl_info->gl_ops.gl.p_glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture);
+
+                glBindTexture(GL_TEXTURE_RECTANGLE_ARB, name);
+                if (gl_info->gl_ops.gl.p_glGetError())
+                {
+                    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture);
+                    FIXME("Cannot find type of texture %d.\n", name);
+                    return;
+                }
+                tex_target = GL_TEXTURE_RECTANGLE_ARB;
+                tex_type_str = "rectangle";
+            }
+
+            glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+            glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_WIDTH, &width);
+            glGetTexLevelParameteriv(tex_target, level, GL_TEXTURE_HEIGHT, &height);
+        }
+
+        FIXME("\t%s: %s texture %d, %dx%d, format %x.\n", name_string, tex_type_str, name, width, height, fmt);
+
+        glBindTexture(tex_target, old_texture);
+    }
+    else if (type == GL_NONE)
+    {
+        FIXME("\t%s: NONE.\n", name_string);
+    }
+    else
+        ERR("\t%s: Unknown attachment %x.\n", name_string, type);
+}
+
 /* Context activation is done by the caller. */
 void context_check_fbo_status(const struct wined3d_context *context, GLenum target)
 {
@@ -258,7 +314,6 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ
     }
     else
     {
-        const struct wined3d_surface *attachment;
         unsigned int i;
 
         FIXME("FBO status %s (%#x)\n", debug_fbostatus(status), status);
@@ -269,29 +324,16 @@ void context_check_fbo_status(const struct wined3d_context *context, GLenum targ
             return;
         }
 
-        FIXME("\tColor Location %s (%#x).\n", wined3d_debug_location(context->current_fbo->color_location),
-                context->current_fbo->color_location);
-        FIXME("\tDepth Stencil Location %s (%#x).\n", wined3d_debug_location(context->current_fbo->ds_location),
-                context->current_fbo->ds_location);
+        context_dump_fbo_attachment(gl_info, target, GL_DEPTH_ATTACHMENT, "Depth attachment");
+        context_dump_fbo_attachment(gl_info, target, GL_STENCIL_ATTACHMENT, "Stencil attachment");
 
-        /* Dump the FBO attachments */
         for (i = 0; i < gl_info->limits.buffers; ++i)
         {
-            attachment = context->current_fbo->render_targets[i];
-            if (attachment)
-            {
-                FIXME("\tColor attachment %d: (%p) %s %ux%u %u samples.\n",
-                        i, attachment, debug_d3dformat(attachment->resource.format->id),
-                        attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type);
-            }
-        }
-        attachment = context->current_fbo->depth_stencil;
-        if (attachment)
-        {
-            FIXME("\tDepth attachment: (%p) %s %ux%u %u samples.\n",
-                    attachment, debug_d3dformat(attachment->resource.format->id),
-                    attachment->pow2Width, attachment->pow2Height, attachment->resource.multisample_type);
+            char name[32];
+            sprintf(name, "Color attachment %u", i);
+            context_dump_fbo_attachment(gl_info, target, GL_COLOR_ATTACHMENT0 + i, name);
         }
+        checkGLcall("Dump FBO attachments");
     }
 }
 
@@ -306,19 +348,74 @@ static inline DWORD context_generate_rt_mask_from_surface(const struct wined3d_s
     return (1u << 31) | surface_get_gl_buffer(target);
 }
 
+static inline void context_set_fbo_key_for_surface(struct wined3d_fbo_entry_key *key, UINT idx,
+        struct wined3d_surface *surface, DWORD location)
+{
+    if (!surface)
+    {
+        key->objects[idx].object = 0;
+        key->objects[idx].level = key->objects[idx].target = 0;
+    }
+    else
+    {
+        switch (location)
+        {
+            case WINED3D_LOCATION_TEXTURE_RGB:
+                key->objects[idx].object = surface->container->texture_rgb.name;
+                key->objects[idx].level = surface->texture_level;
+                key->objects[idx].target = surface->texture_target;
+                break;
+
+            case WINED3D_LOCATION_TEXTURE_SRGB:
+                key->objects[idx].object = surface->container->texture_srgb.name;
+                key->objects[idx].level = surface->texture_level;
+                key->objects[idx].target = surface->texture_target;
+                break;
+
+            case WINED3D_LOCATION_RB_MULTISAMPLE:
+                key->objects[idx].object = surface->rb_multisample;
+                key->objects[idx].level = key->objects[idx].target = 0;
+                key->rb_namespace |= 1 << idx;
+                break;
+
+            case WINED3D_LOCATION_RB_RESOLVED:
+                key->objects[idx].object = surface->rb_resolved;
+                key->objects[idx].level = key->objects[idx].target = 0;
+                key->rb_namespace |= 1 << idx;
+                break;
+        }
+    }
+}
+
+static inline void context_create_fbo_key(struct wined3d_fbo_entry_key *key,
+        struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil,
+        DWORD color_location, DWORD ds_location, UINT color_buffers)
+{
+    UINT i;
+
+    key->rb_namespace = 0;
+    context_set_fbo_key_for_surface(key, 0, depth_stencil, ds_location);
+
+    for (i = 0; i < color_buffers; ++i)
+        context_set_fbo_key_for_surface(key, i + 1, render_targets[i], color_location);
+}
+
 static struct fbo_entry *context_create_fbo_entry(const struct wined3d_context *context,
         struct wined3d_surface **render_targets, struct wined3d_surface *depth_stencil,
         DWORD color_location, DWORD ds_location)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct fbo_entry *entry;
-
-    entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
-    entry->render_targets = HeapAlloc(GetProcessHeap(), 0, gl_info->limits.buffers * sizeof(*entry->render_targets));
-    memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
-    entry->depth_stencil = depth_stencil;
-    entry->color_location = color_location;
-    entry->ds_location = ds_location;
+    UINT object_count = gl_info->limits.buffers + 1;
+
+    entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            FIELD_OFFSET(struct fbo_entry, key.objects[object_count]));
+    entry->d3d_render_targets = HeapAlloc(GetProcessHeap(), 0,
+            gl_info->limits.buffers * sizeof(*entry->d3d_render_targets));
+    context_create_fbo_key(&entry->key, render_targets, depth_stencil, color_location, ds_location,
+            gl_info->limits.buffers);
+    memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers);
+    entry->d3d_depth_stencil = depth_stencil;
     entry->rt_mask = context_generate_rt_mask(GL_COLOR_ATTACHMENT0);
     entry->attached = FALSE;
     gl_info->fbo_ops.glGenFramebuffers(1, &entry->id);
@@ -338,10 +435,10 @@ static void context_reuse_fbo_entry(struct wined3d_context *context, GLenum targ
     context_bind_fbo(context, target, entry->id);
     context_clean_fbo_attachments(gl_info, target);
 
-    memcpy(entry->render_targets, render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets));
-    entry->depth_stencil = depth_stencil;
-    entry->color_location = color_location;
-    entry->ds_location = ds_location;
+    context_create_fbo_key(&entry->key, render_targets, depth_stencil, color_location, ds_location,
+            gl_info->limits.buffers);
+    memcpy(entry->d3d_render_targets, render_targets, sizeof(*entry->d3d_render_targets) * gl_info->limits.buffers);
+    entry->d3d_depth_stencil = depth_stencil;
     entry->attached = FALSE;
 }
 
@@ -355,7 +452,7 @@ static void context_destroy_fbo_entry(struct wined3d_context *context, struct fb
     }
     --context->fbo_entry_count;
     list_remove(&entry->entry);
-    HeapFree(GetProcessHeap(), 0, entry->render_targets);
+    HeapFree(GetProcessHeap(), 0, entry->d3d_render_targets);
     HeapFree(GetProcessHeap(), 0, entry);
 }
 
@@ -366,6 +463,8 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct fbo_entry *entry;
+    UINT object_count = gl_info->limits.buffers + 1;
+    unsigned int i;
 
     if (depth_stencil && render_targets && render_targets[0])
     {
@@ -377,19 +476,44 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
         }
     }
 
-    LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
+    context_create_fbo_key(context->fbo_key, render_targets, depth_stencil, color_location,
+            ds_location, gl_info->limits.buffers);
+
+    if (TRACE_ON(d3d))
     {
-        if (!memcmp(entry->render_targets,
-                render_targets, gl_info->limits.buffers * sizeof(*entry->render_targets))
-                && entry->depth_stencil == depth_stencil && entry->color_location == color_location
-                && entry->ds_location == ds_location)
+        TRACE("Dumping FBO attachments:\n");
+        for (i = 0; i < gl_info->limits.buffers; ++i)
         {
-            list_remove(&entry->entry);
-            list_add_head(&context->fbo_list, &entry->entry);
-            return entry;
+            if (render_targets[i])
+            {
+                TRACE("\tColor attachment %u: (%p) %s gl obj %u(%s) %ux%u %u samples.\n",
+                        i, render_targets[i], debug_d3dformat(render_targets[i]->resource.format->id),
+                        context->fbo_key->objects[i + 1].object,
+                        context->fbo_key->rb_namespace & (1 << (i + 1)) ? "rb" : "texure",
+                        render_targets[i]->pow2Width, render_targets[i]->pow2Height,
+                        render_targets[i]->resource.multisample_type);
+            }
+        }
+        if (depth_stencil)
+        {
+            TRACE("\tDepth attachment: (%p) %s gl obj %u(%s) %ux%u %u samples.\n",
+                    depth_stencil, debug_d3dformat(depth_stencil->resource.format->id),
+                    context->fbo_key->objects[0].object,
+                    context->fbo_key->rb_namespace & (1 << 0) ? "rb" : "texure",
+                    depth_stencil->pow2Width, depth_stencil->pow2Height, depth_stencil->resource.multisample_type);
         }
     }
 
+    LIST_FOR_EACH_ENTRY(entry, &context->fbo_list, struct fbo_entry, entry)
+    {
+        if (memcmp(context->fbo_key, &entry->key, FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[object_count])))
+            continue;
+
+        list_remove(&entry->entry);
+        list_add_head(&context->fbo_list, &entry->entry);
+        return entry;
+    }
+
     if (context->fbo_entry_count < WINED3D_MAX_FBO_ENTRIES)
     {
         entry = context_create_fbo_entry(context, render_targets, depth_stencil, color_location, ds_location);
@@ -413,7 +537,7 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
     const struct wined3d_gl_info *gl_info = context->gl_info;
     unsigned int i;
     GLuint read_binding, draw_binding;
-    struct wined3d_surface *depth_stencil = entry->depth_stencil;
+    struct wined3d_surface *depth_stencil = entry->d3d_depth_stencil;
 
     if (entry->attached)
     {
@@ -428,25 +552,36 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
     /* Apply render targets */
     for (i = 0; i < gl_info->limits.buffers; ++i)
     {
-        context_attach_surface_fbo(context, target, i, entry->render_targets[i], entry->color_location);
+        context_attach_surface_fbo(context, target, i, &entry->key.objects[i + 1],
+                entry->key.rb_namespace & (1 << (i + 1)));
     }
 
-    if (depth_stencil && entry->render_targets[0]
+    if (depth_stencil && entry->d3d_render_targets[0]
             && (depth_stencil->resource.multisample_type
-            != entry->render_targets[0]->resource.multisample_type
+            != entry->d3d_render_targets[0]->resource.multisample_type
             || depth_stencil->resource.multisample_quality
-            != entry->render_targets[0]->resource.multisample_quality))
+            != entry->d3d_render_targets[0]->resource.multisample_quality))
     {
         WARN("Color multisample type %u and quality %u, depth stencil has %u and %u, disabling ds buffer.\n",
-                entry->render_targets[0]->resource.multisample_quality,
-                entry->render_targets[0]->resource.multisample_type,
+                entry->d3d_render_targets[0]->resource.multisample_quality,
+                entry->d3d_render_targets[0]->resource.multisample_type,
                 depth_stencil->resource.multisample_quality, depth_stencil->resource.multisample_type);
         depth_stencil = NULL;
     }
 
     if (depth_stencil)
-        surface_set_compatible_renderbuffer(depth_stencil, entry->render_targets[0]);
-    context_attach_depth_stencil_fbo(context, target, depth_stencil, entry->ds_location);
+    {
+        DWORD format_flags = depth_stencil->container->resource.format_flags;
+        surface_set_compatible_renderbuffer(depth_stencil, entry->d3d_render_targets[0]);
+        context_attach_depth_stencil_fbo(context, target, &entry->key.objects[0],
+                entry->key.rb_namespace & 0x1, format_flags,
+                depth_stencil->current_renderbuffer ? depth_stencil->current_renderbuffer->id : 0);
+    }
+    else
+    {
+        struct wined3d_fbo_resource resource = {0};
+        context_attach_depth_stencil_fbo(context, target, &resource, FALSE, 0, 0);
+    }
 
     /* Set valid read and draw buffer bindings to satisfy pedantic pre-ES2_compatibility
      * GL contexts requirements. */
@@ -695,7 +830,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device
         {
             UINT j;
 
-            if (entry->depth_stencil == surface)
+            if (entry->d3d_depth_stencil == surface)
             {
                 callback(context, entry);
                 continue;
@@ -703,7 +838,7 @@ static void context_enum_surface_fbo_entries(const struct wined3d_device *device
 
             for (j = 0; j < gl_info->limits.buffers; ++j)
             {
-                if (entry->render_targets[j] == surface)
+                if (entry->d3d_render_targets[j] == surface)
                 {
                     callback(context, entry);
                     break;
@@ -764,21 +899,16 @@ void context_surface_update(struct wined3d_context *context, const struct wined3
 
     if (!entry || context->rebind_fbo) return;
 
-    for (i = 0; i < gl_info->limits.buffers; ++i)
+    for (i = 0; i < gl_info->limits.buffers + 1; ++i)
     {
-        if (surface == entry->render_targets[i])
+        if (surface->container->texture_rgb.name == entry->key.objects[i].object ||
+                surface->container->texture_srgb.name == entry->key.objects[i].object)
         {
-            TRACE("Updated surface %p is bound as color attachment %u to the current FBO.\n", surface, i);
+            TRACE("Updated surface %p is bound as attachment %u to the current FBO.\n", surface, i);
             context->rebind_fbo = TRUE;
             return;
         }
     }
-
-    if (surface == entry->depth_stencil)
-    {
-        TRACE("Updated surface %p is bound as depth attachment to the current FBO.\n", surface);
-        context->rebind_fbo = TRUE;
-    }
 }
 
 static BOOL context_restore_pixel_format(struct wined3d_context *ctx)
@@ -1480,6 +1610,11 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
     if (!ret->draw_buffers)
         goto out;
 
+    ret->fbo_key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+            FIELD_OFFSET(struct wined3d_fbo_entry_key, objects[gl_info->limits.buffers + 1]));
+    if (!ret->fbo_key)
+        goto out;
+
     ret->free_timestamp_query_size = 4;
     ret->free_timestamp_queries = HeapAlloc(GetProcessHeap(), 0,
             ret->free_timestamp_query_size * sizeof(*ret->free_timestamp_queries));
@@ -1832,6 +1967,7 @@ out:
     HeapFree(GetProcessHeap(), 0, ret->free_event_queries);
     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
     HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries);
+    HeapFree(GetProcessHeap(), 0, ret->fbo_key);
     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
     HeapFree(GetProcessHeap(), 0, ret->blit_targets);
     HeapFree(GetProcessHeap(), 0, ret);
@@ -1863,6 +1999,7 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont
 
     device->shader_backend->shader_free_context_data(context);
     device->adapter->fragment_pipe->free_context_data(context);
+    HeapFree(GetProcessHeap(), 0, context->fbo_key);
     HeapFree(GetProcessHeap(), 0, context->draw_buffers);
     HeapFree(GetProcessHeap(), 0, context->blit_targets);
     device_context_remove(device, context);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index fd7bbc8..50952db 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1229,6 +1229,7 @@ struct wined3d_context
     GLuint                  fbo_read_binding;
     GLuint                  fbo_draw_binding;
     struct wined3d_surface **blit_targets;
+    struct wined3d_fbo_entry_key *fbo_key;
     GLenum *draw_buffers;
     DWORD draw_buffers_mask; /* Enabled draw buffers, 31 max. */
 
@@ -2374,15 +2375,25 @@ struct wined3d_renderbuffer_entry
     UINT height;
 };
 
+struct wined3d_fbo_resource
+{
+    GLuint object;
+    GLuint level, target;
+};
+
 struct fbo_entry
 {
     struct list entry;
-    struct wined3d_surface **render_targets;
-    struct wined3d_surface *depth_stencil;
-    DWORD color_location, ds_location;
+    struct wined3d_surface **d3d_render_targets;
+    struct wined3d_surface *d3d_depth_stencil;
     DWORD rt_mask;
     BOOL attached;
     GLuint id;
+    struct wined3d_fbo_entry_key
+    {
+        DWORD rb_namespace;
+        struct wined3d_fbo_resource objects[1];
+    } key;
 };
 
 struct wined3d_surface_ops
-- 
2.4.10




More information about the wine-patches mailing list