[Mesa-dev] [PATCH 2/3] st/mesa: fix import of EGL images with non-zero level or layer

Nicolai Hähnle nhaehnle at gmail.com
Fri Oct 6 20:19:00 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

In GL state, textures created from EGL images look like plain 2D textures
with a single level, so we use the existing layer_override facility and
add an analogous level_override one.

Fixes dEQP-EGL.functional.image.create.gles2_cubemap_{positive,negative}_{x,y,z}_rgba_texture
---
 src/mesa/state_tracker/st_cb_eglimage.c  |  3 ++-
 src/mesa/state_tracker/st_cb_texture.c   |  2 ++
 src/mesa/state_tracker/st_sampler_view.c | 16 ++++++++++------
 src/mesa/state_tracker/st_texture.h      | 15 ++++++++++++---
 src/mesa/state_tracker/st_vdpau.c        |  2 ++
 5 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
index e15b32ff199..bb092a2f6ef 100644
--- a/src/mesa/state_tracker/st_cb_eglimage.c
+++ b/src/mesa/state_tracker/st_cb_eglimage.c
@@ -219,26 +219,27 @@ st_bind_egl_image(struct gl_context *ctx,
          break;
       default:
          unreachable("bad YUV format!");
       }
    }
 
    _mesa_init_teximage_fields(ctx, texImage,
                               stimg->texture->width0, stimg->texture->height0,
                               1, 0, internalFormat, texFormat);
 
-   /* FIXME create a non-default sampler view from the stimg? */
    pipe_resource_reference(&stObj->pt, stimg->texture);
    st_texture_release_all_sampler_views(st, stObj);
    pipe_resource_reference(&stImage->pt, stObj->pt);
 
    stObj->surface_format = stimg->format;
+   stObj->level_override = stimg->level;
+   stObj->layer_override = stimg->layer;
 
    _mesa_dirty_texobj(ctx, texObj);
 }
 
 static void
 st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target,
 			       struct gl_texture_object *texObj,
 			       struct gl_texture_image *texImage,
 			       GLeglImageOES image_handle)
 {
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index b0a95ecbc79..25ea52924d2 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -688,20 +688,22 @@ prep_teximage(struct gl_context *ctx, struct gl_texture_image *texImage,
    struct st_texture_object *stObj = st_texture_object(texObj);
 
    /* switch to "normal" */
    if (stObj->surface_based) {
       const GLenum target = texObj->Target;
       const GLuint level = texImage->Level;
       mesa_format texFormat;
 
       assert(!st_texture_image(texImage)->pt);
       _mesa_clear_texture_object(ctx, texObj, texImage);
+      stObj->layer_override = 0;
+      stObj->level_override = 0;
       pipe_resource_reference(&stObj->pt, NULL);
 
       /* oops, need to init this image again */
       texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
                                               texImage->InternalFormat, format,
                                               type);
 
       _mesa_init_teximage_fields(ctx, texImage,
                                  texImage->Width, texImage->Height,
                                  texImage->Depth, texImage->Border,
diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c
index fbf0aaeb03a..014b4d26784 100644
--- a/src/mesa/state_tracker/st_sampler_view.c
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -372,30 +372,34 @@ st_create_texture_sampler_view_from_stobj(struct st_context *st,
 					  struct st_texture_object *stObj,
 					  enum pipe_format format,
                                           bool glsl130_or_later)
 {
    /* There is no need to clear this structure (consider CPU overhead). */
    struct pipe_sampler_view templ;
    unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl130_or_later);
 
    templ.format = format;
 
-   templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
-   templ.u.tex.last_level = last_level(stObj);
-   assert(templ.u.tex.first_level <= templ.u.tex.last_level);
+   if (stObj->level_override) {
+      templ.u.tex.first_level = templ.u.tex.last_level = stObj->level_override;
+   } else {
+      templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
+      templ.u.tex.last_level = last_level(stObj);
+   }
    if (stObj->layer_override) {
       templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override;
    } else {
       templ.u.tex.first_layer = stObj->base.MinLayer;
       templ.u.tex.last_layer = last_layer(stObj);
    }
    assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
+   assert(templ.u.tex.first_level <= templ.u.tex.last_level);
    templ.target = gl_target_to_pipe(stObj->base.Target);
 
    templ.swizzle_r = GET_SWZ(swizzle, 0);
    templ.swizzle_g = GET_SWZ(swizzle, 1);
    templ.swizzle_b = GET_SWZ(swizzle, 2);
    templ.swizzle_a = GET_SWZ(swizzle, 3);
 
    return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ);
 }
 
@@ -412,23 +416,23 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
 
    if (*sv) {
       /* Debug check: make sure that the sampler view's parameters are
        * what they're supposed to be.
        */
       MAYBE_UNUSED struct pipe_sampler_view *view = *sv;
       assert(stObj->pt == view->texture);
       assert(!check_sampler_swizzle(st, stObj, view, glsl130_or_later));
       assert(get_sampler_view_format(st, stObj, samp) == view->format);
       assert(gl_target_to_pipe(stObj->base.Target) == view->target);
-      assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
-             view->u.tex.first_level);
-      assert(last_level(stObj) == view->u.tex.last_level);
+      assert(stObj->level_override ||
+             stObj->base.MinLevel + stObj->base.BaseLevel == view->u.tex.first_level);
+      assert(stObj->level_override || last_level(stObj) == view->u.tex.last_level);
       assert(stObj->layer_override || stObj->base.MinLayer == view->u.tex.first_layer);
       assert(stObj->layer_override || last_layer(stObj) == view->u.tex.last_layer);
       assert(!stObj->layer_override ||
              (stObj->layer_override == view->u.tex.first_layer &&
               stObj->layer_override == view->u.tex.last_layer));
    }
    else {
       /* create new sampler view */
       enum pipe_format format = get_sampler_view_format(st, stObj, samp);
 
diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
index 8448f4c6f02..0cde0c1f409 100644
--- a/src/mesa/state_tracker/st_texture.h
+++ b/src/mesa/state_tracker/st_texture.h
@@ -104,26 +104,35 @@ struct st_texture_object
     * cannot be reallocated and the format can only be changed with a sampler
     * view or a surface.
     */
    GLboolean surface_based;
 
    /* If surface_based is true, this format should be used for all sampler
     * views and surfaces instead of pt->format.
     */
    enum pipe_format surface_format;
 
+   /* When non-zero, samplers should use this level instead of the level
+    * range specified by the GL state.
+    *
+    * This is used for EGL images, which may correspond to a single level out
+    * of an imported pipe_resources with multiple mip levels.
+    */
+   uint level_override;
+
    /* When non-zero, samplers should use this layer instead of the one
     * specified by the GL state.
     *
-    * This is used for VDPAU interop, where imported pipe_resources may be
-    * array textures (containing layers with different fields) even though the
-    * GL state describes one non-array texture per field.
+    * This is used for EGL images and VDPAU interop, where imported
+    * pipe_resources may be cube, 3D, or array textures (containing layers
+    * with different fields in the case of VDPAU) even though the GL state
+    * describes one non-array texture per field.
     */
    uint layer_override;
 
    /** The glsl version of the shader seen during the previous validation */
    bool prev_glsl130_or_later;
    /** The value of the sampler's sRGBDecode state at the previous validation */
    GLenum prev_sRGBDecode;
 
     /**
      * Set when the texture images of this texture object might not all be in
diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c
index bb4070eec34..19611e719a1 100644
--- a/src/mesa/state_tracker/st_vdpau.c
+++ b/src/mesa/state_tracker/st_vdpau.c
@@ -229,40 +229,42 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
 
    _mesa_init_teximage_fields(ctx, texImage,
                               res->width0, res->height0, 1, 0, GL_RGBA,
                               texFormat);
 
    pipe_resource_reference(&stObj->pt, res);
    st_texture_release_all_sampler_views(st, stObj);
    pipe_resource_reference(&stImage->pt, res);
 
    stObj->surface_format = res->format;
+   stObj->level_override = 0;
    stObj->layer_override = layer_override;
 
    _mesa_dirty_texobj(ctx, texObj);
    pipe_resource_reference(&res, NULL);
 }
 
 static void
 st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
                        GLboolean output, struct gl_texture_object *texObj,
                        struct gl_texture_image *texImage,
                        const void *vdpSurface, GLuint index)
 {
    struct st_context *st = st_context(ctx);
    struct st_texture_object *stObj = st_texture_object(texObj);
    struct st_texture_image *stImage = st_texture_image(texImage);
 
    pipe_resource_reference(&stObj->pt, NULL);
    st_texture_release_all_sampler_views(st, stObj);
    pipe_resource_reference(&stImage->pt, NULL);
 
+   stObj->level_override = 0;
    stObj->layer_override = 0;
 
    _mesa_dirty_texobj(ctx, texObj);
 
    st_flush(st, NULL, 0);
 }
 
 #endif
 
 void
-- 
2.11.0



More information about the mesa-dev mailing list