aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/texgetimage.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main/texgetimage.c')
-rw-r--r--mesalib/src/mesa/main/texgetimage.c334
1 files changed, 182 insertions, 152 deletions
diff --git a/mesalib/src/mesa/main/texgetimage.c b/mesalib/src/mesa/main/texgetimage.c
index 3f2418729..738c18112 100644
--- a/mesalib/src/mesa/main/texgetimage.c
+++ b/mesalib/src/mesa/main/texgetimage.c
@@ -216,183 +216,213 @@ get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
/**
- * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
- * Compressed textures are handled here as well.
+ * Get a color texture image with decompression.
*/
static void
-get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
- GLenum format, GLenum type, GLvoid *pixels,
- struct gl_texture_image *texImage)
+get_tex_rgba_compressed(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 gl_format texFormat =
+ _mesa_get_srgb_format_linear(texImage->TexFormat);
+ const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
const GLuint width = texImage->Width;
const GLuint height = texImage->Height;
const GLuint depth = texImage->Depth;
- const GLenum dataType = _mesa_get_format_datatype(texFormat);
- const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
- /* Normally, no pixel transfer ops are performed during glGetTexImage.
- * The only possible exception is component clamping to [0,1].
- */
- GLbitfield transferOps = 0x0;
-
- /* In general, clamping does not apply to glGetTexImage, except when
- * the returned type of the image can't hold negative values.
- */
- if (type_needs_clamping(type)) {
- /* the returned image type can't have negative values */
- if (dataType == GL_FLOAT ||
- dataType == GL_SIGNED_NORMALIZED ||
- format == GL_LUMINANCE ||
- format == GL_LUMINANCE_ALPHA) {
- transferOps |= IMAGE_CLAMP_BIT;
- }
+ GLfloat *tempImage, *srcRow;
+ GLuint row;
+
+ /* Decompress into temp float buffer, then pack into user buffer */
+ tempImage = (GLfloat *) malloc(width * height * depth
+ * 4 * sizeof(GLfloat));
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
+ return;
}
- if (_mesa_is_format_compressed(texFormat)) {
- /* Decompress into temp buffer, then pack into user buffer */
- GLfloat *tempImage, *srcRow;
- GLuint row;
+ /* Decompress the texture image - results in 'tempImage' */
+ {
+ GLubyte *srcMap;
+ GLint srcRowStride;
+ GLuint bytes, bw, bh;
- tempImage = (GLfloat *) malloc(texImage->Width * texImage->Height *
- texImage->Depth * 4 * sizeof(GLfloat));
- if (!tempImage) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
- return;
- }
+ bytes = _mesa_get_format_bytes(texFormat);
+ _mesa_get_format_block_size(texFormat, &bw, &bh);
- /* Decompress the texture image - results in 'tempImage' */
- {
- GLubyte *srcMap;
- GLint srcRowStride;
- GLuint bytes, bw, bh;
+ ctx->Driver.MapTextureImage(ctx, texImage, 0,
+ 0, 0, width, height,
+ GL_MAP_READ_BIT,
+ &srcMap, &srcRowStride);
+ if (srcMap) {
+ /* XXX This line is a bit of a hack to work around the
+ * mismatch of compressed row strides as returned by
+ * MapTextureImage() vs. what the texture decompression code
+ * uses. This will be fixed in the future.
+ */
+ srcRowStride = srcRowStride * bh / bytes;
- bytes = _mesa_get_format_bytes(texImage->TexFormat);
- _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
+ _mesa_decompress_image(texFormat, width, height,
+ srcMap, srcRowStride, tempImage);
- ctx->Driver.MapTextureImage(ctx, texImage, 0,
- 0, 0, width, height,
- GL_MAP_READ_BIT,
- &srcMap, &srcRowStride);
+ ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
+ }
+ else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ }
+ }
- if (srcMap) {
- /* XXX This line is a bit of a hack to work around the
- * mismatch of compressed row strides as returned by
- * MapTextureImage() vs. what the texture decompression code
- * uses. This will be fixed in the future.
- */
- srcRowStride = srcRowStride * bh / bytes;
+ if (baseFormat == GL_LUMINANCE ||
+ baseFormat == GL_LUMINANCE_ALPHA) {
+ /* Set green and blue to zero since the pack function here will
+ * compute L=R+G+B.
+ */
+ GLuint i;
+ for (i = 0; i < width * height; i++) {
+ tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f;
+ }
+ }
- _mesa_decompress_image(texFormat, width, height,
- srcMap, srcRowStride, tempImage);
+ srcRow = tempImage;
+ for (row = 0; row < height; row++) {
+ void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
+ width, height, format, type,
+ 0, row, 0);
- ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
- }
- else {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
- }
- }
+ _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
+ format, type, dest, &ctx->Pack, transferOps);
+ srcRow += width * 4;
+ }
- if (baseFormat == GL_LUMINANCE ||
- baseFormat == GL_LUMINANCE_ALPHA) {
- /* Set green and blue to zero since the pack function here will
- * compute L=R+G+B.
- */
- GLuint i;
- for (i = 0; i < width * height; i++) {
- tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f;
- }
- }
+ free(tempImage);
+}
- srcRow = tempImage;
- for (row = 0; row < height; row++) {
- void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
- width, height, format, type,
- 0, row, 0);
- _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
- format, type, dest, &ctx->Pack, transferOps);
- srcRow += width * 4;
- }
+/**
+ * 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 GLuint height = texImage->Height;
+ const GLuint depth = texImage->Depth;
+ GLuint img, row;
+ GLfloat (*rgba)[4];
- free(tempImage);
+ /* Allocate buffer for one row of texels */
+ rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
+ if (!rgba) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
+ return;
}
- else {
- /* No decompression needed */
- GLuint img, row;
- GLfloat (*rgba)[4];
- rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
- if (!rgba) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
- return;
- }
+ for (img = 0; img < depth; img++) {
+ GLubyte *srcMap;
+ GLint rowstride;
- 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);
-
- _mesa_unpack_rgba_row(texFormat, width, src, rgba);
-
- if (texImage->_BaseFormat == GL_ALPHA) {
- GLint col;
- for (col = 0; col < width; col++) {
- rgba[col][RCOMP] = 0.0F;
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- }
+ /* 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);
+
+ _mesa_unpack_rgba_row(texFormat, width, src, rgba);
+
+ if (texImage->_BaseFormat == GL_ALPHA) {
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][RCOMP] = 0.0F;
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
}
- else if (texImage->_BaseFormat == GL_LUMINANCE) {
- GLint col;
- for (col = 0; col < width; col++) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
- }
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE) {
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
}
- else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- GLint col;
- for (col = 0; col < width; col++) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- }
+ }
+ else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
}
- else if (texImage->_BaseFormat == GL_INTENSITY) {
- GLint col;
- for (col = 0; col < width; col++) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
- }
+ }
+ else if (texImage->_BaseFormat == GL_INTENSITY) {
+ GLint col;
+ for (col = 0; col < width; col++) {
+ rgba[col][GCOMP] = 0.0F;
+ rgba[col][BCOMP] = 0.0F;
+ rgba[col][ACOMP] = 1.0F;
}
-
- _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;
+ _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);
+}
+
- free(rgba);
+/**
+ * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
+ * Compressed textures are handled here as well.
+ */
+static void
+get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
+ GLenum format, GLenum type, GLvoid *pixels,
+ struct gl_texture_image *texImage)
+{
+ const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
+ GLbitfield transferOps = 0x0;
+
+ /* In general, clamping does not apply to glGetTexImage, except when
+ * the returned type of the image can't hold negative values.
+ */
+ if (type_needs_clamping(type)) {
+ /* the returned image type can't have negative values */
+ if (dataType == GL_FLOAT ||
+ dataType == GL_SIGNED_NORMALIZED ||
+ format == GL_LUMINANCE ||
+ format == GL_LUMINANCE_ALPHA) {
+ transferOps |= IMAGE_CLAMP_BIT;
+ }
+ }
+
+ if (_mesa_is_format_compressed(texImage->TexFormat)) {
+ get_tex_rgba_compressed(ctx, dimensions, format, type,
+ pixels, texImage, transferOps);
+ }
+ else {
+ get_tex_rgba_uncompressed(ctx, dimensions, format, type,
+ pixels, texImage, transferOps);
}
}
@@ -702,20 +732,20 @@ getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
return GL_TRUE;
}
- texImage = _mesa_select_tex_image(ctx, texObj, target, level);
- if (!texImage) {
- /* out of memory */
- return GL_TRUE;
- }
-
if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
- /*GL_INVALID_OPERATION is generated by a format/type
+ /* GL_INVALID_OPERATION is generated by a format/type
* mismatch (see the 1.2 spec page 94, sec 3.6.4.)
*/
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(target)");
return GL_TRUE;
}
+ texImage = _mesa_select_tex_image(ctx, texObj, target, level);
+ if (!texImage) {
+ /* non-existant texture image */
+ return GL_TRUE;
+ }
+
baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
/* Make sure the requested image format is compatible with the