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

Iago Toral itoral at igalia.com
Tue Nov 18 23:21:30 PST 2014


On Tue, 2014-11-18 at 08:00 -0700, Brian Paul wrote:
> 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.

Ooops! I think I have done this in a number of patches..
Noted, I'll clean these up. thanks!

> 
> 
> > +
> > +   /* 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