[Mesa-dev] [PATCH] st/mesa: optimize 4-component ubyte glDrawPixels

Jose Fonseca jfonseca at vmware.com
Mon Oct 19 04:19:41 PDT 2015


On 17/10/15 03:56, Brian Paul wrote:
> If we didn't find a gallium surface format that exactly matched the
> glDrawPixels format/type combination, we used some other 32-bit packed
> RGBA format and swizzled the whole image in the mesa texstore/format code.
>
> That slow path can be avoided in some common cases by using the
> pipe_samper_view's swizzle terms to do the swizzling at texture sampling
> time instead.
>
> For now, only GL_RGBA/ubyte and GL_BGRA/ubyte combinations are supported.
> In the future other formats and types like GL_UNSIGNED_INT_8_8_8_8 could
> be added.
>
> v2: fix incorrect swizzle setup (need to invert the tex format's swizzle)
> ---
>   src/mesa/state_tracker/st_cb_drawpixels.c | 104 +++++++++++++++++++++++++++---
>   1 file changed, 95 insertions(+), 9 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
> index 79fb9ec..000d4f2 100644
> --- a/src/mesa/state_tracker/st_cb_drawpixels.c
> +++ b/src/mesa/state_tracker/st_cb_drawpixels.c
> @@ -395,15 +395,35 @@ make_texture(struct st_context *st,
>          * Note that the image is actually going to be upside down in
>          * the texture.  We deal with that with texcoords.
>          */
> -      success = _mesa_texstore(ctx, 2,           /* dims */
> -                               baseInternalFormat, /* baseInternalFormat */
> -                               mformat,          /* mesa_format */
> -                               transfer->stride, /* dstRowStride, bytes */
> -                               &dest,            /* destSlices */
> -                               width, height, 1, /* size */
> -                               format, type,     /* src format/type */
> -                               pixels,           /* data source */
> -                               unpack);
> +      if ((format == GL_RGBA || format == GL_BGRA)
> +          && type == GL_UNSIGNED_BYTE) {
> +         /* Use a memcpy-based texstore to avoid software pixel swizzling.
> +          * We'll do the necessary swizzling with the pipe_sampler_view to
> +          * give much better performance.
> +          * XXX in the future, expand this to accomodate more format and
> +          * type combinations.
> +          */
> +         _mesa_memcpy_texture(ctx, 2,
> +                              mformat,          /* mesa_format */
> +                              transfer->stride, /* dstRowStride, bytes */
> +                              &dest,            /* destSlices */
> +                              width, height, 1, /* size */
> +                              format, type,     /* src format/type */
> +                              pixels,           /* data source */
> +                              unpack);
> +         success = GL_TRUE;
> +      }
> +      else {
> +         success = _mesa_texstore(ctx, 2,           /* dims */
> +                                  baseInternalFormat, /* baseInternalFormat */
> +                                  mformat,          /* mesa_format */
> +                                  transfer->stride, /* dstRowStride, bytes */
> +                                  &dest,            /* destSlices */
> +                                  width, height, 1, /* size */
> +                                  format, type,     /* src format/type */
> +                                  pixels,           /* data source */
> +                                  unpack);
> +      }
>
>         /* unmap */
>         pipe_transfer_unmap(pipe, transfer);
> @@ -958,6 +978,69 @@ clamp_size(struct pipe_context *pipe, GLsizei *width, GLsizei *height,
>
>
>   /**
> + * Search the array of 4 swizzle components for the named component and return
> + * its position.
> + */
> +static int

Return type and `i` should be unsigned to avoid sign conversion. 
Otherwise looks great.

Reviewed by: Jose Fonseca <jfonseca at vmware.com>


> +search_swizzle(const unsigned char swizzle[4], unsigned component)
> +{
> +   int i;
> +   for (i = 0; i < 4; i++) {
> +      if (swizzle[i] == component)
> +         return i;
> +   }
> +   assert(!"search_swizzle() failed");
> +   return 0;
> +}
> +
> +
> +/**
> + * Set the sampler view's swizzle terms.  This is used to handle RGBA
> + * swizzling when the incoming image format isn't an exact match for
> + * the actual texture format.  For example, if we have glDrawPixels(
> + * GL_RGBA, GL_UNSIGNED_BYTE) and we chose the texture format
> + * PIPE_FORMAT_B8G8R8A8 then we can do use the sampler view swizzle to
> + * avoid swizzling all the pixels in software in the texstore code.
> + */
> +static void
> +setup_sampler_swizzle(struct pipe_sampler_view *sv, GLenum format, GLenum type)
> +{
> +   if ((format == GL_RGBA || format == GL_BGRA) && type == GL_UNSIGNED_BYTE) {
> +      const struct util_format_description *desc =
> +         util_format_description(sv->texture->format);
> +      unsigned c0, c1, c2, c3;
> +
> +      /* Every gallium driver supports at least one 32-bit packed RGBA format.
> +       * We must have chosen one for (GL_RGBA, GL_UNSIGNED_BYTE).
> +       */
> +      assert(desc->block.bits == 32);
> +
> +      /* invert the format's swizzle to setup the sampler's swizzle */
> +      if (format == GL_RGBA) {
> +         c0 = UTIL_FORMAT_SWIZZLE_X;
> +         c1 = UTIL_FORMAT_SWIZZLE_Y;
> +         c2 = UTIL_FORMAT_SWIZZLE_Z;
> +         c3 = UTIL_FORMAT_SWIZZLE_W;
> +      }
> +      else {
> +         assert(format == GL_BGRA);
> +         c0 = UTIL_FORMAT_SWIZZLE_Z;
> +         c1 = UTIL_FORMAT_SWIZZLE_Y;
> +         c2 = UTIL_FORMAT_SWIZZLE_X;
> +         c3 = UTIL_FORMAT_SWIZZLE_W;
> +      }
> +      sv->swizzle_r = search_swizzle(desc->swizzle, c0);
> +      sv->swizzle_g = search_swizzle(desc->swizzle, c1);
> +      sv->swizzle_b = search_swizzle(desc->swizzle, c2);
> +      sv->swizzle_a = search_swizzle(desc->swizzle, c3);
> +   }
> +   else {
> +      /* use the default sampler swizzle */
> +   }
> +}
> +
> +
> +/**
>    * Called via ctx->Driver.DrawPixels()
>    */
>   static void
> @@ -1046,6 +1129,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
>         return;
>      }
>
> +   /* Set up the sampler view's swizzle */
> +   setup_sampler_swizzle(sv[0], format, type);
> +
>      /* Create a second sampler view to read stencil.  The stencil is
>       * written using the shader stencil export functionality.
>       */
>



More information about the mesa-dev mailing list