[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