From 3d21ea0807a95f504f2bef102e447a40e61c0c0d Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 6 Mar 2018 10:08:26 +0330 Subject: [PATCH] wined3d: Store the EXT_fbo "renderbuffers" list in the texture instead of the surface. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/context.c | 23 ++--- dlls/wined3d/surface.c | 84 ------------------- dlls/wined3d/texture.c | 148 +++++++++++++++++++++++++-------- dlls/wined3d/wined3d_private.h | 10 +-- 4 files changed, 126 insertions(+), 139 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index c9efad03db1..60bf52ba129 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 8d6712b2988..5a2bf52af74 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 0c0e434a875..8c0333115d5 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,24 +1932,18 @@ 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); wined3d_texture_force_reload(texture); @@ -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 db9dd967bbc..d7895b5bfc3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3155,6 +3155,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; @@ -3252,6 +3255,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; @@ -3317,9 +3322,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) @@ -3339,8 +3341,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,