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);