[Mesa-dev] [PATCH] st/mesa: EGLImageTarget error handling

Philipp Zabel p.zabel at pengutronix.de
Wed Mar 22 10:00:18 UTC 2017


Hi Nicolai,

thank you for the comments.

On Wed, 2017-03-22 at 07:58 +0100, Nicolai Hähnle wrote:
> On 21.03.2017 17:51, Philipp Zabel wrote:
> > Stop trying to specify texture or renderbuffer objects for unsupported
> > EGL images. Generate the error codes specified in the OES_EGL_image
> > extension.
> >
> > Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
> > ---
> > EGLImageTargetTexture2D and EGLImageTargetRenderbuffer would call
> > the pipe driver's create_surface callback without ever checking that
> > the given EGL image is actually compatible with the chosen target
> > texture or renderbuffer. This patch adds a call to the pipe driver's
> > is_format_supported callback and generates an INVALID_OPERATION error
> > for unsupported EGL images. If the EGL image handle does not describe
> > a valid EGL image, an INVALID_VALUE error is generated.
> 
> This description might as well go into the commit message IMO.

Ok. If this is not considered too verbose, I'll move it up next time.

> Do you have test cases for these errors? If so, best to mention it in 
> the commit message as well.

My test case is a GStreamer waylandsink displaying NV12 dmabufs under
weston on etnaviv:

    gst-launch-1.0 v4l2src device=/dev/v4l/by-path/platform-vivid.0-video-index0 io-mode=dmabuf ! video/x-raw,format=NV12 ! waylandsink

weston will create NV12 EGL images from the dmabufs, and pass those to
EGLImageTargetTexture2DOES. Without the is_format_supported check, this
will currently run into an assert in etna_rs_gen_clear_surface, called
from etna_create_surface, because of the unsupported format.

> > ---
> >  src/mesa/state_tracker/st_cb_eglimage.c | 53 +++++++++++++++++++++++++++++++--
> >  src/mesa/state_tracker/st_manager.c     | 27 ++++++-----------
> >  src/mesa/state_tracker/st_manager.h     |  4 ++-
> >  3 files changed, 63 insertions(+), 21 deletions(-)
> >
> > diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
> > index c425154..6810e24 100644
> > --- a/src/mesa/state_tracker/st_cb_eglimage.c
> > +++ b/src/mesa/state_tracker/st_cb_eglimage.c
> > @@ -25,6 +25,7 @@
> >   *    Chia-I Wu <olv at lunarg.com>
> >   */
> >
> > +#include "main/errors.h"
> >  #include "main/texobj.h"
> >  #include "main/teximage.h"
> >  #include "util/u_inlines.h"
> > @@ -74,10 +75,34 @@ st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
> >  					 GLeglImageOES image_handle)
> >  {
> >     struct st_context *st = st_context(ctx);
> > +   struct st_manager *smapi =
> > +      (struct st_manager *) st->iface.st_context_private;
> >     struct st_renderbuffer *strb = st_renderbuffer(rb);
> > +   struct pipe_screen *screen = st->pipe->screen;
> > +   struct st_egl_image stimg;
> >     struct pipe_surface *ps;
> >
> > -   ps = st_manager_get_egl_image_surface(st, (void *) image_handle);
> > +   if (!smapi || !smapi->get_egl_image) {
> > +      _mesa_error(ctx, GL_INVALID_OPERATION, "glEGLImageTargetRenderbufferStorage");
> > +      return NULL;
> > +   }
> 
> This error should be caught by the caller in mesa/main.

How should that be detected?
_mesa_EGLImageTargetRenderbufferStorageOES can't directly access
((struct st_manager *)st_context(ctx)->iface.st_context_private)->get_egl_image.

I suppose checking ctx->Extensions.OES_EGL_image won't suffice, as that
seems to be enabled unconditionally, but osmesa doesn't implement the
get_egl_image callback.

> > +
> > +   memset(&stimg, 0, sizeof(stimg));
> > +   if (!smapi->get_egl_image(smapi, (void *) image_handle, &stimg)) {
> > +      /* image_handle does not refer to a valid EGL image object */
> > +      _mesa_error(ctx, GL_INVALID_VALUE, "glEGLImageTargetRenderbufferStorage");
> > +      return NULL;
> > +   }
> > +
> > +   if (!screen->is_format_supported(screen, stimg.format, PIPE_TEXTURE_2D,
> > +                                    stimg.texture->nr_samples,
> > +                                    PIPE_BIND_RENDER_TARGET)) {
> > +      /* unable to specify a texture object using the specified EGL image */
> > +      _mesa_error(ctx, GL_INVALID_OPERATION, "glEGLImageTargetRenderbufferStorage");
> > +      return NULL;
> > +   }
> > +
> > +   ps = st_manager_get_egl_image_surface(st, &stimg);
> >     if (ps) {
> >        strb->Base.Width = ps->width;
> >        strb->Base.Height = ps->height;
> > @@ -160,9 +185,33 @@ st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target,
> >  			       GLeglImageOES image_handle)
> >  {
> >     struct st_context *st = st_context(ctx);
> > +   struct st_manager *smapi =
> > +      (struct st_manager *) st->iface.st_context_private;
> > +   struct pipe_screen *screen = st->pipe->screen;
> > +   struct st_egl_image stimg;
> >     struct pipe_surface *ps;
> >
> > -   ps = st_manager_get_egl_image_surface(st, (void *) image_handle);
> > +   if (!smapi || !smapi->get_egl_image) {
> > +      _mesa_error(ctx, GL_INVALID_OPERATION, "glEGLImageTargetTexture2D");
> > +      return NULL;
> > +   }
> 
> Same as above: should be caught by the caller.
> 
> 
> > +
> > +   memset(&stimg, 0, sizeof(stimg));
> > +   if (!smapi->get_egl_image(smapi, (void *) image_handle, &stimg)) {
> > +      /* image_handle does not refer to a valid EGL image object */
> > +      _mesa_error(ctx, GL_INVALID_VALUE, "glEGLImageTargetTexture2D");
> > +      return NULL;
> > +   }
> > +
> > +   if (!screen->is_format_supported(screen, stimg.format, PIPE_TEXTURE_2D,
> > +                                    stimg.texture->nr_samples,
> > +                                    PIPE_BIND_SAMPLER_VIEW)) {
> > +      /* unable to specify a texture object using the specified EGL image */
> > +      _mesa_error(ctx, GL_INVALID_OPERATION, "glEGLImageTargetTexture2D");
> > +      return NULL;
> > +   }
> > +
> > +   ps = st_manager_get_egl_image_surface(st, &stimg);
> 
> Since you're pretty much duplicating code here, have you considered 
> adding a helper function that does all the above? Actually, I think 
> st_manager_get_egl_image_surface should then be removed in favor of the 
> helper function in st_cb_eglimage.c.

I considered passing the usage flag and error text into
st_manager_get_egl_image_surface at first, but decided against it
because of the indirection. Also there were no calls to _mesa_error in
st_manager.c, but in there are in other st_cb_* files already.

I could, move st_manager_get_egl_image_surface into st_cb_eglimage.c and
turn it into the helper you suggest.

> 
> >     if (ps) {
> >        st_bind_surface(ctx, target, texObj, texImage, ps);
> >        pipe_surface_reference(&ps, NULL);
> > diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
> > index dad408a..8f16da1 100644
> > --- a/src/mesa/state_tracker/st_manager.c
> > +++ b/src/mesa/state_tracker/st_manager.c
> > @@ -862,27 +862,18 @@ st_manager_flush_frontbuffer(struct st_context *st)
> >   * FIXME: I think this should operate on resources, not surfaces
> >   */
> >  struct pipe_surface *
> > -st_manager_get_egl_image_surface(struct st_context *st, void *eglimg)
> > +st_manager_get_egl_image_surface(struct st_context *st,
> > +                                 struct st_egl_image *stimg)
> >  {
> > -   struct st_manager *smapi =
> > -      (struct st_manager *) st->iface.st_context_private;
> > -   struct st_egl_image stimg;
> >     struct pipe_surface *ps, surf_tmpl;
> >
> > -   if (!smapi || !smapi->get_egl_image)
> > -      return NULL;
> > -
> > -   memset(&stimg, 0, sizeof(stimg));
> > -   if (!smapi->get_egl_image(smapi, eglimg, &stimg))
> > -      return NULL;
> > -
> > -   u_surface_default_template(&surf_tmpl, stimg.texture);
> > -   surf_tmpl.format = stimg.format;
> > -   surf_tmpl.u.tex.level = stimg.level;
> > -   surf_tmpl.u.tex.first_layer = stimg.layer;
> > -   surf_tmpl.u.tex.last_layer = stimg.layer;
> > -   ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
> > -   pipe_resource_reference(&stimg.texture, NULL);
> > +   u_surface_default_template(&surf_tmpl, stimg->texture);
> > +   surf_tmpl.format = stimg->format;
> > +   surf_tmpl.u.tex.level = stimg->level;
> > +   surf_tmpl.u.tex.first_layer = stimg->layer;
> > +   surf_tmpl.u.tex.last_layer = stimg->layer;
> > +   ps = st->pipe->create_surface(st->pipe, stimg->texture, &surf_tmpl);
> > +   pipe_resource_reference(&stimg->texture, NULL);
> 
> Maybe moot if this function is removed anyway, but: the dereference 
> should be moved into the caller, so that referencing/dereferencing 
> logically happens in the same place.

Ok.

regards
Philipp



More information about the mesa-dev mailing list