[virglrenderer-devel] [RFC PATCH 1/5] vrend: Enable ARB_texture_storage on GLES

Gert Wollny gert.wollny at collabora.com
Thu Aug 2 08:48:23 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 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 <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 392c909..02d413b 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -189,7 +189,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" } },
@@ -5146,6 +5146,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);
@@ -5495,6 +5497,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 */
@@ -5561,7 +5566,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++) {
@@ -5578,7 +5583,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);
@@ -5595,7 +5600,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++) {
@@ -5605,7 +5610,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 {
@@ -5619,7 +5624,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 93185c1..380fbdc 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);
-- 
2.17.1



More information about the virglrenderer-devel mailing list