#include "context.h"
#include "formats.h"
#include "format_unpack.h"
+#include "glformats.h"
#include "image.h"
#include "mfeatures.h"
#include "mtypes.h"
const GLint height = texImage->Height;
const GLint depth = texImage->Depth;
GLint img, row;
- GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
+ GLfloat *depthRow = malloc(width * sizeof(GLfloat));
if (!depthRow) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
GLuint row;
/* Decompress into temp float buffer, then pack into user buffer */
- tempImage = (GLfloat *) malloc(width * height * depth
+ tempImage = malloc(width * height * depth
* 4 * sizeof(GLfloat));
if (!tempImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
}
else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
+ free(tempImage);
+ return;
}
}
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_rebase_rgba_float(width * height, (GLfloat (*)[4]) tempImage,
+ baseFormat);
}
srcRow = tempImage;
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 is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
+ 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 = malloc(4 * width * sizeof(GLfloat));
rgba_uint = (GLuint (*)[4]) rgba;
if (!rgba) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
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) &&
+ (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;
width, height, format, type,
img, row, 0);
- if (is_integer) {
+ if (tex_is_integer) {
_mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
-
- if (texImage->_BaseFormat == GL_ALPHA) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba_uint[col][RCOMP] = 0;
- rgba_uint[col][GCOMP] = 0;
- rgba_uint[col][BCOMP] = 0;
- }
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba_uint[col][GCOMP] = 0;
- rgba_uint[col][BCOMP] = 0;
- rgba_uint[col][ACOMP] = 1;
- }
- }
- else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba_uint[col][GCOMP] = 0;
- rgba_uint[col][BCOMP] = 0;
- }
- }
- else if (texImage->_BaseFormat == GL_INTENSITY) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba_uint[col][GCOMP] = 0;
- rgba_uint[col][BCOMP] = 0;
- rgba_uint[col][ACOMP] = 1;
- }
- }
-
- _mesa_pack_rgba_span_int(ctx, width, rgba_uint,
- format, type, dest);
+ 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 (texImage->_BaseFormat == GL_ALPHA) {
- GLuint 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) {
- GLuint 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) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- }
- }
- else if (texImage->_BaseFormat == GL_INTENSITY) {
- GLuint col;
- for (col = 0; col < width; col++) {
- rgba[col][GCOMP] = 0.0F;
- rgba[col][BCOMP] = 0.0F;
- rgba[col][ACOMP] = 1.0F;
- }
- }
-
+ 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);
}
+/**
+ * Validate the texture target enum supplied to glTexImage or
+ * glCompressedTexImage.
+ */
+static GLboolean
+legal_getteximage_target(struct gl_context *ctx, GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ return GL_TRUE;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
+ return ctx->Extensions.ARB_texture_cube_map;
+ case GL_TEXTURE_RECTANGLE_NV:
+ return ctx->Extensions.NV_texture_rectangle;
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ return (ctx->Extensions.MESA_texture_array ||
+ ctx->Extensions.EXT_texture_array);
+ default:
+ return GL_FALSE;
+ }
+}
+
/**
* Do error checking for a glGetTexImage() call.
const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
GLenum baseFormat, err;
- if (maxLevels == 0) {
+ if (!legal_getteximage_target(ctx, target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
return GL_TRUE;
}
+ assert(maxLevels != 0);
if (level < 0 || level >= maxLevels) {
_mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
return GL_TRUE;
texObj = _mesa_get_current_tex_object(ctx, target);
- if (!texObj || _mesa_is_proxy_texture(target)) {
+ if (!texObj) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
return GL_TRUE;
}
const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
GLuint compressedSize;
- if (maxLevels == 0) {
+ if (!legal_getteximage_target(ctx, target)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
target);
return GL_TRUE;
}
+ assert(maxLevels != 0);
if (level < 0 || level >= maxLevels) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetCompressedTexImageARB(bad level = %d)", level);
return GL_TRUE;
}
- if (_mesa_is_proxy_texture(target)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetCompressedTexImageARB(bad target = %s)",
- _mesa_lookup_enum_by_nr(target));
- return GL_TRUE;
- }
-
texObj = _mesa_get_current_tex_object(ctx, target);
if (!texObj) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");