[virglrenderer-devel] [PATCH] vrend: Enable ARB_texture_storage on GLES

Gert Wollny gert.wollny at collabora.com
Wed Jul 25 11:14:02 UTC 2018


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 glTexStorage*D 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 <gert.wollny at collabora.com>
---
 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 4647c43..b9f85a0 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 b56092f..2c58e1a 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -172,7 +172,7 @@ static const  struct {
    [feat_texture_array] = { 30, 30, { "GL_EXT_texture_array" } },
    [feat_texture_buffer_range] = { 43, UNAVAIL, { "GL_ARB_texture_buffer_range" } },
    [feat_texture_multisample] = { 32, 30, { "GL_ARB_texture_multisample" } },
-   [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" } },
@@ -4762,6 +4762,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);
@@ -5109,6 +5111,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 */
@@ -5175,7 +5180,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++) {
@@ -5192,7 +5197,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);
@@ -5209,7 +5214,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++) {
@@ -5219,7 +5224,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 {
@@ -5233,7 +5238,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 8f1192e..36a0d3d 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;
@@ -314,6 +316,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);
-- 
2.16.4



More information about the virglrenderer-devel mailing list