[Mesa-dev] [PATCH 16/29] mesa: use master conversion function to implement get_tex_rgba_uncompressed()

Brian Paul brianp at vmware.com
Tue Nov 18 07:00:31 PST 2014


On 11/18/2014 02:23 AM, Iago Toral Quiroga wrote:
> From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
>
> This covers glGetTexImage for uncompressed color formats.
>
> Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
> Signed-off-by: Eduardo Lima Mitev <elima at igalia.com>
> ---
>   src/mesa/main/texgetimage.c | 170 ++++++++++++++++++++++++++++++--------------
>   1 file changed, 117 insertions(+), 53 deletions(-)
>
> diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
> index cb5f793..84cd53e 100644
> --- a/src/mesa/main/texgetimage.c
> +++ b/src/mesa/main/texgetimage.c
> @@ -45,7 +45,8 @@
>   #include "texgetimage.h"
>   #include "teximage.h"
>   #include "texstore.h"
> -
> +#include "format_utils.h"
> +#include "pixeltransfer.h"
>
>
>   /**
> @@ -380,20 +381,10 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
>      GLenum rebaseFormat = GL_NONE;
>      GLuint height = texImage->Height;
>      GLuint depth = texImage->Depth;
> -   GLuint img, row;
> -   GLfloat (*rgba)[4];
> -   GLuint (*rgba_uint)[4];
> -   GLboolean tex_is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
> -   GLboolean tex_is_uint = _mesa_is_format_unsigned(texImage->TexFormat);
> +   GLuint img;
>      GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat);
>
> -   /* Allocate buffer for one row of texels */
> -   rgba = malloc(4 * width * sizeof(GLfloat));
> -   rgba_uint = (GLuint (*)[4]) rgba;
> -   if (!rgba) {
> -      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
> -      return;
> -   }
> +   assert (depth <= 1 || dimensions > 2);
>
>      if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
>         depth = height;
> @@ -413,9 +404,7 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
>                texImage->_BaseFormat == GL_RGB ||
>                texImage->_BaseFormat == GL_RG) &&
>               (destBaseFormat == GL_LUMINANCE ||
> -             destBaseFormat == GL_LUMINANCE_ALPHA ||
> -             destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
> -             destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
> +             destBaseFormat == GL_LUMINANCE_ALPHA)) {
>         /* If we're reading back an RGB(A) texture as luminance then we need
>          * to return L=tex(R).  Note, that's different from glReadPixels which
>          * returns L=R+G+B.
> @@ -467,6 +456,22 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
>         }
>      }
>
> +   /* Describe the dst format */
> +   GLboolean dst_is_integer = _mesa_is_enum_format_integer(format);
> +   uint32_t dst_format = _mesa_format_from_format_and_type(format, type);
> +   int dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type);

This won't build with MSVC.  Declarations cannot follow code.



> +
> +   /* Since _mesa_format_convert does not handle transferOps we need to handle
> +    * them before we call the function. This requires to convert to RGBA float
> +    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
> +    * integer we can ignore transferOps.
> +    *
> +    * Some source formats (Luminance) will also require to be rebased to obtain
> +    * the expected results and this also requires to convert to RGBA first.
> +    */
> +   assert(!transferOps || (transferOps && !dst_is_integer));
> +   bool needs_rgba = (transferOps || rebaseFormat != GL_NONE);
> +
>      for (img = 0; img < depth; img++) {
>         GLubyte *srcMap;
>         GLint rowstride;
> @@ -475,46 +480,105 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
>         ctx->Driver.MapTextureImage(ctx, texImage, img,
>                                     0, 0, width, height, GL_MAP_READ_BIT,
>                                     &srcMap, &rowstride);
> -      if (srcMap) {
> -         for (row = 0; row < height; row++) {
> -            const GLubyte *src = srcMap + row * rowstride;
> -            void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
> -                                             width, height, format, type,
> -                                             img, row, 0);
> -
> -	    if (tex_is_integer) {
> -	       _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
> -               if (rebaseFormat)
> -                  _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat);
> -               if (tex_is_uint) {
> -                  _mesa_pack_rgba_span_from_uints(ctx, width,
> -                                                  (GLuint (*)[4]) rgba_uint,
> -                                                  format, type, dest);
> -               } else {
> -                  _mesa_pack_rgba_span_from_ints(ctx, width,
> -                                                 (GLint (*)[4]) rgba_uint,
> -                                                 format, type, dest);
> -               }
> -	    } else {
> -	       _mesa_unpack_rgba_row(texFormat, width, src, rgba);
> -               if (rebaseFormat)
> -                  _mesa_rebase_rgba_float(width, rgba, rebaseFormat);
> -	       _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
> -					  format, type, dest,
> -					  &ctx->Pack, transferOps);
> -	    }
> -	 }
> -
> -         /* Unmap the src texture buffer */
> -         ctx->Driver.UnmapTextureImage(ctx, texImage, img);
> -      }
> -      else {
> +      if (!srcMap) {
>            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
> -         break;
> +         return;
>         }
> -   }
>
> -   free(rgba);
> +      GLubyte *img_src = srcMap;
> +      void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
> +                                       width, height, format, type,
> +                                       img, 0, 0);
> +
> +      void *rgba = NULL;
> +      void *src;
> +      int src_stride;
> +      uint32_t src_format;
> +      if (needs_rgba) {
> +         uint32_t rgba_format;
> +         int rgba_stride;
> +
> +         /* Convert to RGBA float or (u)int depending on the type of the dst */
> +         if (dst_is_integer) {
> +            /* To avoid losing information because of clamping when converting
> +             * from source to RGBA, check if source's format is signed or not.
> +             */
> +            GLboolean src_is_uint = _mesa_is_format_unsigned(texImage->TexFormat);
> +
> +            if (src_is_uint) {
> +               rgba_format = RGBA8888_UINT.as_uint;
> +               rgba_stride = width * 4 * sizeof(GLuint);
> +            } else {
> +               rgba_format = RGBA8888_INT.as_uint;
> +               rgba_stride = width * 4 * sizeof(GLint);
> +            }
> +         } else {
> +            rgba_format = RGBA8888_FLOAT.as_uint;
> +            rgba_stride = width * 4 * sizeof(GLfloat);
> +         }
> +
> +         /* If we are lucky and the dst format matches the RGBA format we need to
> +          * convert to, then we can convert directly into the dst buffer and avoid
> +          * the final conversion/copy from the rgba buffer to the dst buffer.
> +          */
> +         bool need_convert;
> +         if (format == rgba_format) {
> +            need_convert = false;
> +            rgba = dest;
> +         } else {
> +            need_convert = true;
> +            rgba = malloc(height * rgba_stride);
> +            if (!rgba) {
> +               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
> +               ctx->Driver.UnmapTextureImage(ctx, texImage, img);
> +               return;
> +            }
> +         }
> +
> +         /* Convert to RGBA now */
> +         _mesa_format_convert(rgba, rgba_format, rgba_stride,
> +                              img_src, texFormat, rowstride,
> +                              width, height, GL_RGBA);
> +
> +         /* Rebase and handle transfer ops as necessary */
> +         if (dst_is_integer) {
> +            _mesa_rebase_rgba_uint(width * height, (GLuint (*)[4]) rgba, rebaseFormat);
> +         } else {
> +            _mesa_rebase_rgba_float(width * height, (GLfloat (*)[4]) rgba, rebaseFormat);
> +            if (transferOps)
> +               _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
> +         }
> +
> +         /* If we were lucky and our RGBA conversion matches the dst format, then
> +          * we are done.
> +          */
> +         if (!need_convert)
> +            goto done;
> +
> +         /* Otherwise, we need to convert from RGBA to dst next */
> +         src = rgba;
> +         src_format = rgba_format;
> +         src_stride = rgba_stride;
> +      } else {
> +         /* No RGBA conversion needed, convert directly to dst */
> +         src = img_src;
> +         src_format = texFormat;
> +         src_stride = rowstride;
> +      }
> +
> +      /* Do the conversion to destination format */
> +      _mesa_format_convert(dest, dst_format, dst_stride,
> +                           src, src_format, src_stride,
> +                           width, height,
> +                           _mesa_get_format_base_format(dst_format));
> +
> +      if (rgba)
> +         free(rgba);
> +
> +   done:
> +      /* Unmap the src texture buffer */
> +      ctx->Driver.UnmapTextureImage(ctx, texImage, img);
> +   }
>   }
>
>
>



More information about the mesa-dev mailing list