static void slow_read_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels, const struct gl_pixelstore_attrib *packing, GLbitfield transferOps ) { struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format); void *rgba; GLubyte *dst, *map; int dstStride, stride, j; dstStride = _mesa_image_row_stride(packing, width, format, type); dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, format, type, 0, 0); ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, &map, &stride); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); return; } rgba = malloc(width * MAX_PIXEL_BYTES); if (!rgba) goto done; for (j = 0; j < height; j++) { if (_mesa_is_integer_format(format)) { _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba); _mesa_pack_rgba_span_int(ctx, width, (GLuint (*)[4]) rgba, format, type, dst); } else { _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba); _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, type, dst, packing, transferOps); } dst += dstStride; map += stride; } free(rgba); done: ctx->Driver.UnmapRenderbuffer(ctx, rb); }
/** * Get an uncompressed color texture image. */ static void get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, GLenum format, GLenum type, GLvoid *pixels, struct gl_texture_image *texImage, GLbitfield transferOps) { /* don't want to apply sRGB -> RGB conversion here so override the format */ const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); const GLuint width = texImage->Width; const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format); 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); /* Allocate buffer for one row of texels */ rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); rgba_uint = (GLuint (*)[4]) rgba; if (!rgba) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); return; } if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { depth = height; height = 1; } if (texImage->_BaseFormat == GL_LUMINANCE || texImage->_BaseFormat == GL_INTENSITY || texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { /* If a luminance (or intensity) texture is read back as RGB(A), the * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat * here to get G=B=0. */ rebaseFormat = texImage->_BaseFormat; } else if ((texImage->_BaseFormat == GL_RGBA || 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)) { /* 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. */ rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */ } for (img = 0; img < depth; img++) { GLubyte *srcMap; GLint rowstride; /* map src texture buffer */ 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 { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); break; } } free(rgba); }