From 1ddf2e47e252fd30976237bd190a98b310909301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Thu, 26 May 2016 00:08:27 +0200 Subject: [PATCH] wined3d: Use immutable storage for 2D textures. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/directx.c | 15 ++++-- dlls/wined3d/texture.c | 114 ++++++++++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 39 deletions(-) diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 140c6a7fa4a..92330164620 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3834,6 +3834,17 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, DWORD adapter->d3d_info.wined3d_creation_flags = wined3d_creation_flags; TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages); + adapter->d3d_info.valid_rt_mask = 0; + for (i = 0; i < gl_info->limits.buffers; ++i) + adapter->d3d_info.valid_rt_mask |= (1u << i); + + if (!adapter->d3d_info.shader_color_key) + { + /* We do not want to deal with re-creating immutable texture storage for color keying emulation. */ + WARN("Disabling ARB_texture_storage because fragment pipe doesn't support color keying.\n"); + gl_info->supported[ARB_TEXTURE_STORAGE] = FALSE; + } + if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]) { gl_info->fbo_ops.glIsRenderbuffer = gl_info->gl_ops.ext.p_glIsRenderbuffer; @@ -3911,10 +3922,6 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, DWORD gl_info->wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP] = gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE] ? GL_MIRROR_CLAMP_TO_EDGE : GL_REPEAT; - adapter->d3d_info.valid_rt_mask = 0; - for (i = 0; i < gl_info->limits.buffers; ++i) - adapter->d3d_info.valid_rt_mask |= (1u << i); - if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]) { GLuint vao; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index a7f28d54848..26ddda794de 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -39,6 +39,15 @@ static BOOL wined3d_texture_use_pbo(const struct wined3d_texture *texture, const && !(texture->flags & (WINED3D_TEXTURE_PIN_SYSMEM | WINED3D_TEXTURE_COND_NP2_EMULATED)); } +static BOOL wined3d_texture_use_immutable_storage(const struct wined3d_texture *texture, + const struct wined3d_gl_info *gl_info) +{ + /* We don't expect to create texture views for textures with height-scaled formats. + * Besides, ARB_texture_storage doesn't allow to specify exact sizes for all levels. */ + return gl_info->supported[ARB_TEXTURE_STORAGE] + && !(texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE); +} + GLenum wined3d_texture_get_gl_buffer(const struct wined3d_texture *texture) { const struct wined3d_swapchain *swapchain = texture->swapchain; @@ -351,6 +360,72 @@ static void gltexture_delete(struct wined3d_device *device, const struct wined3d tex->name = 0; } +/* Context activation is done by the caller. */ +/* The caller is responsible for binding the correct texture. */ +static void wined3d_texture_allocate_gl_mutable_storage(struct wined3d_texture *texture, + GLenum gl_internal_format, const struct wined3d_format *format, + const struct wined3d_gl_info *gl_info) +{ + unsigned int i, sub_call_count; + + sub_call_count = texture->level_count; + if (texture->target != GL_TEXTURE_2D_ARRAY) + sub_call_count *= texture->layer_count; + + for (i = 0; i < sub_call_count; ++i) + { + struct wined3d_surface *surface = texture->sub_resources[i].u.surface; + GLsizei width, height; + + width = wined3d_texture_get_level_pow2_width(texture, surface->texture_level); + height = wined3d_texture_get_level_pow2_height(texture, surface->texture_level); + if (texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE) + { + height *= format->height_scale.numerator; + height /= format->height_scale.denominator; + } + + TRACE("surface %p, target %#x, level %u, width %u, height %u.\n", + surface, surface->texture_target, surface->texture_level, width, height); + + if (texture->target == GL_TEXTURE_2D_ARRAY) + { + GL_EXTCALL(glTexImage3D(surface->texture_target, surface->texture_level, + gl_internal_format, width, height, texture->layer_count, 0, + format->glFormat, format->glType, NULL)); + checkGLcall("glTexImage3D"); + } + else + { + gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, + gl_internal_format, width, height, 0, format->glFormat, format->glType, NULL); + checkGLcall("glTexImage2D"); + } + } +} + +/* Context activation is done by the caller. */ +/* The caller is responsible for binding the correct texture. */ +static void wined3d_texture_allocate_gl_immutable_storage(struct wined3d_texture *texture, + GLenum gl_internal_format, const struct wined3d_gl_info *gl_info) +{ + GLsizei width = wined3d_texture_get_level_pow2_width(texture, 0); + GLsizei height = wined3d_texture_get_level_pow2_height(texture, 0); + + if (texture->target == GL_TEXTURE_2D_ARRAY) + { + GL_EXTCALL(glTexStorage3D(texture->target, texture->level_count, gl_internal_format, + width, height, texture->layer_count)); + checkGLcall("glTexStorage3D"); + } + else + { + GL_EXTCALL(glTexStorage2D(texture->target, texture->level_count, gl_internal_format, + width, height)); + checkGLcall("glTexStorage2D"); + } +} + static void wined3d_texture_unload_gl_texture(struct wined3d_texture *texture) { struct wined3d_device *device = texture->resource.device; @@ -1362,9 +1437,7 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi const struct wined3d_format *format = texture->resource.format; const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_color_key_conversion *conversion; - unsigned int sub_call_count; GLenum internal; - UINT i; TRACE("texture %p, context %p, format %s.\n", texture, context, debug_d3dformat(format->id)); @@ -1394,39 +1467,10 @@ static void texture2d_prepare_texture(struct wined3d_texture *texture, struct wi TRACE("internal %#x, format %#x, type %#x.\n", internal, format->glFormat, format->glType); - sub_call_count = texture->level_count; - if (texture->target != GL_TEXTURE_2D_ARRAY) - sub_call_count *= texture->layer_count; - for (i = 0; i < sub_call_count; ++i) - { - struct wined3d_surface *surface = texture->sub_resources[i].u.surface; - GLsizei width, height; - - width = wined3d_texture_get_level_pow2_width(texture, surface->texture_level); - height = wined3d_texture_get_level_pow2_height(texture, surface->texture_level); - if (texture->resource.format_flags & WINED3DFMT_FLAG_HEIGHT_SCALE) - { - height *= format->height_scale.numerator; - height /= format->height_scale.denominator; - } - - TRACE("surface %p, target %#x, level %u, width %u, height %u.\n", - surface, surface->texture_target, surface->texture_level, width, height); - - if (texture->target == GL_TEXTURE_2D_ARRAY) - { - GL_EXTCALL(glTexImage3D(surface->texture_target, surface->texture_level, - internal, width, height, texture->layer_count, 0, - format->glFormat, format->glType, NULL)); - checkGLcall("glTexImage3D"); - } - else - { - gl_info->gl_ops.gl.p_glTexImage2D(surface->texture_target, surface->texture_level, - internal, width, height, 0, format->glFormat, format->glType, NULL); - checkGLcall("glTexImage2D"); - } - } + if (wined3d_texture_use_immutable_storage(texture, gl_info)) + wined3d_texture_allocate_gl_immutable_storage(texture, internal, gl_info); + else + wined3d_texture_allocate_gl_mutable_storage(texture, internal, format, gl_info); } static void texture2d_cleanup_sub_resources(struct wined3d_texture *texture)