From c91500a14c8293fe7b1bafb4a76633913e5e4ee6 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Sun, 5 Aug 2018 16:45:56 +0200 Subject: [PATCH] vrend: Enable ARB_texture_storage on GLES glTexStorage*D is more restrictive in supporting texture formats, especially on GLES. Specifically, it doesn't support BGRA textures that are needed to get any useful display, but it is needed to get immutable textures that are required for glTextureView. Check which formats are supported and use glTexStorage*D for these, otherwise fall back to use glTexImage*D. Signed-off-by: Gert Wollny Signed-off-by: Dave Airlie --- src/vrend_formats.c | 20 ++++++++++++++++++++ src/vrend_renderer.c | 17 +++++++++++------ src/vrend_renderer.h | 3 +++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/vrend_formats.c b/src/vrend_formats.c index 2ecdbb4..18e2223 100644 --- a/src/vrend_formats.c +++ b/src/vrend_formats.c @@ -444,6 +444,26 @@ void vrend_build_format_list_gles(void) add_formats(gles_z32_format); } +/* glTexStorage may not support all that is supported by glTexImage, + * so add a flag to indicate when it can be used. + */ +void vrend_check_texture_storage(struct vrend_format_table *table) +{ + int i; + GLuint tex_id; + for (i = 0; i < VIRGL_FORMAT_MAX; i++) { + + if (table[i].internalformat != 0) { + glGenTextures(1, &tex_id); + glBindTexture(GL_TEXTURE_2D, tex_id); + glTexStorage2D(GL_TEXTURE_2D, 1, table[i].internalformat, 32, 32); + if (glGetError() == GL_NO_ERROR) + table[i].bindings |= VIRGL_BIND_CAN_TEXTURE_STORAGE; + glDeleteTextures(1, &tex_id); + } + } +} + unsigned vrend_renderer_query_multisample_caps(unsigned max_samples, struct virgl_caps_v2 *caps) { GLuint tex; diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 9c23e65..f26bfb4 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -191,7 +191,7 @@ static const struct { [feat_texture_buffer_range] = { 43, UNAVAIL, { "GL_ARB_texture_buffer_range" } }, [feat_texture_multisample] = { 32, 30, { "GL_ARB_texture_multisample" } }, [feat_texture_srgb_decode] = { UNAVAIL, UNAVAIL, { "GL_EXT_texture_sRGB_decode" } }, - [feat_texture_storage] = { 42, UNAVAIL, { "GL_ARB_texture_storage" } }, + [feat_texture_storage] = { 42, 30, { "GL_ARB_texture_storage" } }, [feat_texture_view] = { 43, UNAVAIL, { "GL_ARB_texture_view" } }, [feat_transform_feedback] = { 30, 30, { "GL_EXT_transform_feedback" } }, [feat_transform_feedback2] = { 40, 30, { "GL_ARB_transform_feedback2" } }, @@ -5149,6 +5149,8 @@ int vrend_renderer_init(struct vrend_if_cbs *cbs, uint32_t flags) vrend_build_format_list_gl(); } + vrend_check_texture_storage(tex_conv_table); + /* disable for format testing */ if (has_feature(feat_debug_cb)) { glDisable(GL_DEBUG_OUTPUT); @@ -5498,6 +5500,9 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, struct pipe_resource *pr = &gr->base; assert(pr->width0 > 0); + bool format_can_texture_storage = has_feature(feat_texture_storage) && + (tex_conv_table[pr->format].bindings & VIRGL_BIND_CAN_TEXTURE_STORAGE); + gr->target = tgsitargettogltarget(pr->target, pr->nr_samples); /* ugly workaround for texture rectangle missing on GLES */ @@ -5564,7 +5569,7 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, } } else if (gr->target == GL_TEXTURE_CUBE_MAP) { int i; - if (has_feature(feat_texture_storage)) + if (format_can_texture_storage) glTexStorage2D(GL_TEXTURE_CUBE_MAP, pr->last_level + 1, internalformat, pr->width0, pr->height0); else { for (i = 0; i < 6; i++) { @@ -5581,7 +5586,7 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, } else if (gr->target == GL_TEXTURE_3D || gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) { - if (has_feature(feat_texture_storage)) { + if (format_can_texture_storage) { unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? pr->array_size : pr->depth0; glTexStorage3D(gr->target, pr->last_level + 1, internalformat, pr->width0, pr->height0, depth_param); @@ -5598,7 +5603,7 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, } else if (gr->target == GL_TEXTURE_1D && vrend_state.use_gles) { report_gles_missing_func(NULL, "glTexImage1D"); } else if (gr->target == GL_TEXTURE_1D) { - if (has_feature(feat_texture_storage)) { + if (format_can_texture_storage) { glTexStorage1D(gr->target, pr->last_level + 1, internalformat, pr->width0); } else { for (level = 0; level <= pr->last_level; level++) { @@ -5608,7 +5613,7 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, } } } else { - if (has_feature(feat_texture_storage)) + if (format_can_texture_storage) glTexStorage2D(gr->target, pr->last_level + 1, internalformat, pr->width0, gr->target == GL_TEXTURE_1D_ARRAY ? pr->array_size : pr->height0); else { @@ -5622,7 +5627,7 @@ static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr, } } - if (!has_feature(feat_texture_storage)) { + if (!format_can_texture_storage) { glTexParameteri(gr->target, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(gr->target, GL_TEXTURE_MAX_LEVEL, pr->last_level); } diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index 4cdcf66..5879c61 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -71,6 +71,8 @@ struct vrend_resource { }; #define VIRGL_BIND_NEED_SWIZZLE (1 << 28) +#define VIRGL_BIND_CAN_TEXTURE_STORAGE (1 << 29) + struct vrend_format_table { enum virgl_formats format; @@ -330,6 +332,7 @@ GLint64 vrend_renderer_get_timestamp(void); void vrend_build_format_list_common(void); void vrend_build_format_list_gl(void); void vrend_build_format_list_gles(void); +void vrend_check_texture_storage(struct vrend_format_table *table); int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov, int num_iovs);