[Mesa-dev] [PATCH] mesa: Fix element count for byte-swaps in texstore, readpix and texgetimage
Iago Toral
itoral at igalia.com
Sun Feb 15 23:13:59 PST 2015
On Fri, 2015-02-13 at 10:18 -0800, Ian Romanick wrote:
> On 02/13/2015 03:56 AM, Iago Toral Quiroga wrote:
> > Some old format conversion code in pack.c implemented byte-swapping like this:
> >
> > GLint comps = _mesa_components_in_format(dstFormat);
> > GLint swapSize = _mesa_sizeof_packed_type(dstType);
> > if (swapSize == 2)
> > _mesa_swap2((GLushort *) dstAddr, n * comps);
> > else if (swapSize == 4)
> > _mesa_swap4((GLuint *) dstAddr, n * comps);
> >
> > where n is the pixel count. But this is incorrect for packed formats,
> > where _mesa_sizeof_packed_type is already returning the size of a pixel
> > instead of the size of a single component, so multiplying this by the
> > number of components in the format results in a larger element count
> > for _mesa_swap than we want.
> >
> > Unfortunately, we followed the same implementation for byte-swapping
> > in the rewrite of the format conversion code for texstore, readpixels
> > and texgetimage.
> >
> > This patch computes the correct element counts for _mesa_swap calls
> > by computing the bytes per pixel in the image and dividing that by the
> > swap size to obtain the number of swaps required per pixel. Then multiplies
> > that by the number of pixels in the image to obtain the swap count that
> > we need to use.
> >
> > Also, when handling byte-swapping in texstore_rgba, we were ignoring
> > the image's depth. This patch fixes this too.
>
> Are there any paths that need to handle
> GL_FLOAT_32_UNSIGNED_INT_24_8_REV? In those paths _mesa_sizeof_packed_type
I think this got cut... anyway, this patch handles swapping on color
data uploads and downloads, so I think none of these need to handle
GL_FLOAT_32_UNSIGNED_INT_24_8_REV.
Looking at get_tex_depth_stencil() in texgetimage.c it looks like we
always call _mesa_swap4 . For the readpixels path we call
_mesa_pack_depth_stencil_span() which seems to do the same. We don't use
_mesa_sizeof_packed_type in these cases, so I guess this is fine.
Iago
> > ---
> > src/mesa/main/readpix.c | 13 ++++++++-----
> > src/mesa/main/texgetimage.c | 13 ++++++++-----
> > src/mesa/main/texstore.c | 14 +++++++++-----
> > 3 files changed, 25 insertions(+), 15 deletions(-)
> >
> > diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c
> > index 85f900d..ca4b943 100644
> > --- a/src/mesa/main/readpix.c
> > +++ b/src/mesa/main/readpix.c
> > @@ -605,12 +605,15 @@ read_rgba_pixels( struct gl_context *ctx,
> > done_swap:
> > /* Handle byte swapping if required */
> > if (packing->SwapBytes) {
> > - int components = _mesa_components_in_format(format);
> > GLint swapSize = _mesa_sizeof_packed_type(type);
>
> It's challenging to understand why this code is correct because
> _mesa_sizeof_packed_type is a misleading name. It determines the size
> of packed types (e.g., GL_UNSIGNED_BYTE_3_3_2) and non-packed types
> (e.g., GL_UNSIGNED_BYTE)... and thus the original bug.
>
> You don't need to change anything here. This is just commentary that
> naming matters.
>
> > - if (swapSize == 2)
> > - _mesa_swap2((GLushort *) dst, width * height * components);
> > - else if (swapSize == 4)
> > - _mesa_swap4((GLuint *) dst, width * height * components);
> > + if (swapSize == 2 || swapSize == 4) {
> > + int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
> > + assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
> > + if (swapSize == 2)
> > + _mesa_swap2((GLushort *) dst, width * height * swapsPerPixel);
> > + else if (swapSize == 4)
> > + _mesa_swap4((GLuint *) dst, width * height * swapsPerPixel);
> > + }
> > }
> >
> > done_unmap:
> > diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c
> > index ee465e6..405f085 100644
> > --- a/src/mesa/main/texgetimage.c
> > +++ b/src/mesa/main/texgetimage.c
> > @@ -511,12 +511,15 @@ get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
> > do_swap:
> > /* Handle byte swapping if required */
> > if (ctx->Pack.SwapBytes) {
> > - int components = _mesa_components_in_format(format);
> > GLint swapSize = _mesa_sizeof_packed_type(type);
> > - if (swapSize == 2)
> > - _mesa_swap2((GLushort *) dest, width * height * components);
> > - else if (swapSize == 4)
> > - _mesa_swap4((GLuint *) dest, width * height * components);
> > + if (swapSize == 2 || swapSize == 4) {
> > + int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
> > + assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
> > + if (swapSize == 2)
> > + _mesa_swap2((GLushort *) dest, width * height * swapsPerPixel);
> > + else if (swapSize == 4)
> > + _mesa_swap4((GLuint *) dest, width * height * swapsPerPixel);
> > + }
> > }
> >
> > /* Unmap the src texture buffer */
> > diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
> > index 4d32659..227693d 100644
> > --- a/src/mesa/main/texstore.c
> > +++ b/src/mesa/main/texstore.c
> > @@ -721,15 +721,19 @@ texstore_rgba(TEXSTORE_PARAMS)
> > */
> > GLint swapSize = _mesa_sizeof_packed_type(srcType);
> > if (swapSize == 2 || swapSize == 4) {
> > - int components = _mesa_components_in_format(srcFormat);
> > - int elementCount = srcWidth * srcHeight * components;
> > - tempImage = malloc(elementCount * swapSize);
> > + int bytesPerPixel = _mesa_bytes_per_pixel(srcFormat, srcType);
> > + assert(bytesPerPixel % swapSize == 0);
> > + int swapsPerPixel = bytesPerPixel / swapSize;
> > + int elementCount = srcWidth * srcHeight * srcDepth;
> > + tempImage = malloc(elementCount * bytesPerPixel);
> > if (!tempImage)
> > return GL_FALSE;
> > if (swapSize == 2)
> > - _mesa_swap2_copy(tempImage, (GLushort *) srcAddr, elementCount);
> > + _mesa_swap2_copy(tempImage, (GLushort *) srcAddr,
> > + elementCount * swapsPerPixel);
> > else
> > - _mesa_swap4_copy(tempImage, (GLuint *) srcAddr, elementCount);
> > + _mesa_swap4_copy(tempImage, (GLuint *) srcAddr,
> > + elementCount * swapsPerPixel);
> > srcAddr = tempImage;
> > }
> > }
> >
>
>
More information about the mesa-dev
mailing list