[PATCH 1/5] wined3d: Store the EXT_fbo "renderbuffers" list in the texture instead of the surface.

Henri Verbeet hverbeet at codeweavers.com
Tue Mar 6 00:38:26 CST 2018


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/context.c         |  23 +++----
 dlls/wined3d/surface.c         |  84 ------------------------
 dlls/wined3d/texture.c         | 146 +++++++++++++++++++++++++++++++----------
 dlls/wined3d/wined3d_private.h |  10 +--
 4 files changed, 125 insertions(+), 138 deletions(-)

diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index c9efad0..60bf52b 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -445,19 +445,15 @@ static inline void context_set_fbo_key_for_render_target(const struct wined3d_co
     }
 
     texture = wined3d_texture_from_resource(resource);
-    if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
+    if (texture->current_renderbuffer)
     {
-        struct wined3d_surface *surface = texture->sub_resources[sub_resource_idx].u.surface;
-
-        if (surface->current_renderbuffer)
-        {
-            key->objects[idx].object = surface->current_renderbuffer->id;
-            key->objects[idx].target = 0;
-            key->objects[idx].level = key->objects[idx].layer = 0;
-            key->rb_namespace |= 1 << idx;
-            return;
-        }
+        key->objects[idx].object = texture->current_renderbuffer->id;
+        key->objects[idx].target = 0;
+        key->objects[idx].level = key->objects[idx].layer = 0;
+        key->rb_namespace |= 1 << idx;
+        return;
     }
+
     key->objects[idx].target = wined3d_texture_get_sub_resource_target(texture, sub_resource_idx);
     key->objects[idx].level = sub_resource_idx % texture->level_count;
     key->objects[idx].layer = sub_resource_idx / texture->level_count;
@@ -604,10 +600,7 @@ static struct fbo_entry *context_find_fbo_entry(struct wined3d_context *context,
         }
         else if (depth_stencil->resource->type == WINED3D_RTYPE_TEXTURE_2D)
         {
-            struct wined3d_surface *surface;
-
-            surface = ds_texture->sub_resources[depth_stencil->sub_resource_idx].u.surface;
-            surface_set_compatible_renderbuffer(surface, &render_targets[0]);
+            wined3d_texture_set_compatible_renderbuffer(ds_texture, ds_level, &render_targets[0]);
         }
     }
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 8d6712b..5a2bf52 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -975,90 +975,6 @@ static HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface,
     return WINED3D_OK;
 }
 
-/* In D3D the depth stencil dimensions have to be greater than or equal to the
- * render target dimensions. With FBOs, the dimensions have to be an exact match. */
-/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
-/* Context activation is done by the caller. */
-void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, const struct wined3d_rendertarget_info *rt)
-{
-    unsigned int sub_resource_idx, width, height, level;
-    struct wined3d_renderbuffer_entry *entry;
-    const struct wined3d_texture *texture;
-    const struct wined3d_gl_info *gl_info;
-    unsigned int src_width, src_height;
-    GLuint renderbuffer = 0;
-
-    texture = surface->container;
-    gl_info = &texture->resource.device->adapter->gl_info;
-    sub_resource_idx = surface_get_sub_resource_idx(surface);
-    level = sub_resource_idx % texture->level_count;
-
-    if (rt && rt->resource->format->id != WINED3DFMT_NULL)
-    {
-        struct wined3d_texture *rt_texture;
-        unsigned int rt_level;
-
-        if (rt->resource->type == WINED3D_RTYPE_BUFFER)
-        {
-            FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
-            return;
-        }
-        rt_texture = wined3d_texture_from_resource(rt->resource);
-        rt_level = rt->sub_resource_idx % rt_texture->level_count;
-
-        width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
-        height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
-    }
-    else
-    {
-        width = wined3d_texture_get_level_pow2_width(texture, level);
-        height = wined3d_texture_get_level_pow2_height(texture, level);
-    }
-
-    src_width = wined3d_texture_get_level_pow2_width(texture, level);
-    src_height = wined3d_texture_get_level_pow2_height(texture, level);
-
-    /* A depth stencil smaller than the render target is not valid */
-    if (width > src_width || height > src_height) return;
-
-    /* Remove any renderbuffer set if the sizes match */
-    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
-            || (width == src_width && height == src_height))
-    {
-        surface->current_renderbuffer = NULL;
-        return;
-    }
-
-    /* Look if we've already got a renderbuffer of the correct dimensions */
-    LIST_FOR_EACH_ENTRY(entry, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-    {
-        if (entry->width == width && entry->height == height)
-        {
-            renderbuffer = entry->id;
-            surface->current_renderbuffer = entry;
-            break;
-        }
-    }
-
-    if (!renderbuffer)
-    {
-        gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
-        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
-        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
-                texture->resource.format->glInternal, width, height);
-
-        entry = heap_alloc(sizeof(*entry));
-        entry->width = width;
-        entry->height = height;
-        entry->id = renderbuffer;
-        list_add_head(&surface->renderbuffers, &entry->entry);
-
-        surface->current_renderbuffer = entry;
-    }
-
-    checkGLcall("set_compatible_renderbuffer");
-}
-
 /* See also float_16_to_32() in wined3d_private.h */
 static inline unsigned short float_32_to_16(const float *in)
 {
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 0c0e434..8c03331 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -418,6 +418,8 @@ static HRESULT wined3d_texture_init(struct wined3d_texture *texture, const struc
             texture->flags |= WINED3D_TEXTURE_GENERATE_MIPMAPS;
     }
 
+    list_init(&texture->renderbuffers);
+
     return WINED3D_OK;
 }
 
@@ -654,8 +656,9 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
     struct wined3d_device *device = texture->resource.device;
+    struct wined3d_renderbuffer_entry *entry, *entry2;
+    const struct wined3d_gl_info *gl_info = NULL;
     struct wined3d_context *context = NULL;
-    const struct wined3d_gl_info *gl_info;
     GLuint buffer_object;
     unsigned int i;
 
@@ -678,6 +681,21 @@ static void wined3d_texture_cleanup(struct wined3d_texture *texture)
 
         GL_EXTCALL(glDeleteBuffers(1, &buffer_object));
     }
+
+    if (!context && !list_empty(&texture->renderbuffers))
+    {
+        context = context_acquire(device, NULL, 0);
+        gl_info = context->gl_info;
+    }
+
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        TRACE("Deleting renderbuffer %u.\n", entry->id);
+        context_gl_resource_released(device, entry->id, TRUE);
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+        heap_free(entry);
+    }
+
     if (context)
         context_release(context);
 
@@ -1233,6 +1251,89 @@ HRESULT CDECL wined3d_texture_set_color_key(struct wined3d_texture *texture,
     return WINED3D_OK;
 }
 
+/* In D3D the depth stencil dimensions have to be greater than or equal to the
+ * render target dimensions. With FBOs, the dimensions have to be an exact match. */
+/* TODO: We should synchronize the renderbuffer's content with the texture's content. */
+/* Context activation is done by the caller. */
+void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
+        unsigned int level, const struct wined3d_rendertarget_info *rt)
+{
+    struct wined3d_renderbuffer_entry *entry;
+    const struct wined3d_gl_info *gl_info;
+    unsigned int src_width, src_height;
+    unsigned int width, height;
+    GLuint renderbuffer = 0;
+
+    gl_info = &texture->resource.device->adapter->gl_info;
+    if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
+        return;
+
+    if (rt && rt->resource->format->id != WINED3DFMT_NULL)
+    {
+        struct wined3d_texture *rt_texture;
+        unsigned int rt_level;
+
+        if (rt->resource->type == WINED3D_RTYPE_BUFFER)
+        {
+            FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt->resource->type));
+            return;
+        }
+        rt_texture = wined3d_texture_from_resource(rt->resource);
+        rt_level = rt->sub_resource_idx % rt_texture->level_count;
+
+        width = wined3d_texture_get_level_pow2_width(rt_texture, rt_level);
+        height = wined3d_texture_get_level_pow2_height(rt_texture, rt_level);
+    }
+    else
+    {
+        width = wined3d_texture_get_level_pow2_width(texture, level);
+        height = wined3d_texture_get_level_pow2_height(texture, level);
+    }
+
+    src_width = wined3d_texture_get_level_pow2_width(texture, level);
+    src_height = wined3d_texture_get_level_pow2_height(texture, level);
+
+    /* A depth stencil smaller than the render target is not valid */
+    if (width > src_width || height > src_height)
+        return;
+
+    /* Remove any renderbuffer set if the sizes match */
+    if (width == src_width && height == src_height)
+    {
+        texture->current_renderbuffer = NULL;
+        return;
+    }
+
+    /* Look if we've already got a renderbuffer of the correct dimensions */
+    LIST_FOR_EACH_ENTRY(entry, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        if (entry->width == width && entry->height == height)
+        {
+            renderbuffer = entry->id;
+            texture->current_renderbuffer = entry;
+            break;
+        }
+    }
+
+    if (!renderbuffer)
+    {
+        gl_info->fbo_ops.glGenRenderbuffers(1, &renderbuffer);
+        gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+        gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER,
+                texture->resource.format->glInternal, width, height);
+
+        entry = heap_alloc(sizeof(*entry));
+        entry->width = width;
+        entry->height = height;
+        entry->id = renderbuffer;
+        list_add_head(&texture->renderbuffers, &entry->entry);
+
+        texture->current_renderbuffer = entry;
+    }
+
+    checkGLcall("set_compatible_renderbuffer");
+}
+
 static void texture2d_create_dc(void *object)
 {
     struct wined3d_surface *surface = object;
@@ -1738,10 +1839,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi
 static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
 {
     unsigned int sub_count = texture->level_count * texture->layer_count;
-    struct wined3d_device *device = texture->resource.device;
     struct wined3d_texture_sub_resource *sub_resource;
-    struct wined3d_renderbuffer_entry *entry, *entry2;
-    const struct wined3d_gl_info *gl_info = NULL;
     struct wined3d_context *context = NULL;
     struct wined3d_surface *surface;
     unsigned int i;
@@ -1754,20 +1852,6 @@ static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)
 
         TRACE("surface %p.\n", surface);
 
-        if (!context && !list_empty(&surface->renderbuffers))
-        {
-            context = context_acquire(device, NULL, 0);
-            gl_info = context->gl_info;
-        }
-
-        LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-        {
-            TRACE("Deleting renderbuffer %u.\n", entry->id);
-            context_gl_resource_released(device, entry->id, TRUE);
-            gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
-            heap_free(entry);
-        }
-
         if (surface->dc)
             texture2d_destroy_dc(surface);
     }
@@ -1813,6 +1897,7 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
 {
     struct wined3d_texture *texture = texture_from_resource(resource);
     UINT sub_count = texture->level_count * texture->layer_count;
+    struct wined3d_renderbuffer_entry *entry, *entry2;
     struct wined3d_device *device = resource->device;
     const struct wined3d_gl_info *gl_info;
     struct wined3d_context *context;
@@ -1847,23 +1932,17 @@ static void wined3d_texture_unload(struct wined3d_resource *resource)
 
         if (sub_resource->buffer_object)
             wined3d_texture_remove_buffer_object(texture, i, context->gl_info);
+    }
 
-        if (resource->type == WINED3D_RTYPE_TEXTURE_2D)
-        {
-            struct wined3d_surface *surface = sub_resource->u.surface;
-            struct wined3d_renderbuffer_entry *entry, *entry2;
-
-            LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &surface->renderbuffers, struct wined3d_renderbuffer_entry, entry)
-            {
-                context_gl_resource_released(device, entry->id, TRUE);
-                gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
-                list_remove(&entry->entry);
-                heap_free(entry);
-            }
-            list_init(&surface->renderbuffers);
-            surface->current_renderbuffer = NULL;
-        }
+    LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &texture->renderbuffers, struct wined3d_renderbuffer_entry, entry)
+    {
+        context_gl_resource_released(device, entry->id, TRUE);
+        gl_info->fbo_ops.glDeleteRenderbuffers(1, &entry->id);
+        list_remove(&entry->entry);
+        heap_free(entry);
     }
+    list_init(&texture->renderbuffers);
+    texture->current_renderbuffer = NULL;
 
     context_release(context);
 
@@ -2247,7 +2326,6 @@ static HRESULT texture_init(struct wined3d_texture *texture, const struct wined3
             surface->container = texture;
             surface->texture_level = i;
             surface->texture_layer = j;
-            list_init(&surface->renderbuffers);
 
             sub_resource = &texture->sub_resources[idx];
             sub_resource->locations = WINED3D_LOCATION_DISCARDED;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a78055a..d92193d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3154,6 +3154,9 @@ struct wined3d_texture
         RECT dst_rect;
     } *overlay_info;
 
+    struct list renderbuffers;
+    const struct wined3d_renderbuffer_entry *current_renderbuffer;
+
     struct wined3d_texture_sub_resource
     {
         void *parent;
@@ -3251,6 +3254,8 @@ BOOL wined3d_texture_prepare_location(struct wined3d_texture *texture, unsigned
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
 void wined3d_texture_prepare_texture(struct wined3d_texture *texture,
         struct wined3d_context *context, BOOL srgb) DECLSPEC_HIDDEN;
+void wined3d_texture_set_compatible_renderbuffer(struct wined3d_texture *texture,
+        unsigned int level, const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
 void wined3d_texture_set_map_binding(struct wined3d_texture *texture, DWORD map_binding) DECLSPEC_HIDDEN;
 void wined3d_texture_set_swapchain(struct wined3d_texture *texture,
         struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
@@ -3316,9 +3321,6 @@ struct wined3d_surface
     /* For GetDC */
     HBITMAP bitmap;
     HDC dc;
-
-    struct list               renderbuffers;
-    const struct wined3d_renderbuffer_entry *current_renderbuffer;
 };
 
 static inline unsigned int surface_get_sub_resource_idx(const struct wined3d_surface *surface)
@@ -3338,8 +3340,6 @@ void surface_load_fb_texture(struct wined3d_surface *surface, BOOL srgb,
         struct wined3d_context *context) DECLSPEC_HIDDEN;
 BOOL surface_load_location(struct wined3d_surface *surface,
         struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN;
-void surface_set_compatible_renderbuffer(struct wined3d_surface *surface,
-        const struct wined3d_rendertarget_info *rt) DECLSPEC_HIDDEN;
 void wined3d_surface_upload_data(struct wined3d_texture *texture, unsigned int sub_resource_idx,
         const struct wined3d_gl_info *gl_info, const struct wined3d_format *format, const RECT *src_rect,
         unsigned int src_pitch, const POINT *dst_point, BOOL srgb,
-- 
2.1.4




More information about the wine-devel mailing list