case GL_RGBA8I_EXT:
case GL_RGBA16I_EXT:
case GL_RGBA32I_EXT:
+ case GL_RGB10_A2UI:
return GL_RGBA;
case GL_RGB8UI_EXT:
case GL_RGB16UI_EXT:
}
}
+ if (ctx->Extensions.OES_compressed_ETC1_RGB8_texture) {
+ switch (internalFormat) {
+ case GL_ETC1_RGB8_OES:
+ return GL_RGB;
+ default:
+ ; /* fallthrough */
+ }
+ }
+
if (ctx->API == API_OPENGLES) {
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
/**
- * Store a gl_texture_image pointer in a gl_texture_object structure
- * according to the target and level parameters.
+ * Install gl_texture_image in a gl_texture_object according to the target
+ * and level parameters.
*
* \param tObj texture object.
* \param target texture target.
* \param level image level.
* \param texImage texture image.
*/
-void
-_mesa_set_tex_image(struct gl_texture_object *tObj,
- GLenum target, GLint level,
- struct gl_texture_image *texImage)
+static void
+set_tex_image(struct gl_texture_object *tObj,
+ GLenum target, GLint level,
+ struct gl_texture_image *texImage)
{
const GLuint face = _mesa_tex_target_to_face(target);
*/
ASSERT(ctx->Driver.FreeTextureImageBuffer);
ctx->Driver.FreeTextureImageBuffer( ctx, texImage );
+ free(texImage);
}
return NULL;
}
- _mesa_set_tex_image(texObj, target, level, texImage);
+ set_tex_image(texObj, target, level, texImage);
}
return texImage;
/**
- * Reset the fields of a gl_texture_image struct to zero.
- *
- * \param img texture image structure.
- *
- * This is called when a proxy texture test fails, we set all the
- * image members (except DriverData) to zero.
- * It's also used in glTexImage[123]D as a safeguard to be sure all
- * required fields get initialized properly by the Driver.TexImage[123]D
- * functions.
+ * Set the size and format-related fields of a gl_texture_image struct
+ * to zero. This is used when a proxy texture test fails.
*/
static void
clear_teximage_fields(struct gl_texture_image *img)
* Initialize basic fields of the gl_texture_image struct.
*
* \param ctx GL context.
- * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
* \param img texture image structure to be initialized.
* \param width image width.
* \param height image height.
* Note: width, height and depth include the border.
*/
void
-_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target,
+_mesa_init_teximage_fields(struct gl_context *ctx,
struct gl_texture_image *img,
GLsizei width, GLsizei height, GLsizei depth,
GLint border, GLenum internalFormat,
}
+/**
+ * Return true if the format is only valid for glCompressedTexImage.
+ */
+static GLboolean
+compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
+{
+ switch (format) {
+ case GL_ETC1_RGB8_OES:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
/**
* Helper function to determine whether a target and specific compression
/* additional checks for depth textures */
if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
- /* Only 1D, 2D, rect and array textures supported, not 3D or cubes */
+ /* Only 1D, 2D, rect, array and cube textures supported, not 3D
+ * Cubemaps are only supported for GL version > 3.0 or with EXT_gpu_shader4 */
if (target != GL_TEXTURE_1D &&
target != GL_PROXY_TEXTURE_1D &&
target != GL_TEXTURE_2D &&
target != GL_TEXTURE_2D_ARRAY &&
target != GL_PROXY_TEXTURE_2D_ARRAY &&
target != GL_TEXTURE_RECTANGLE_ARB &&
- target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
+ target != GL_PROXY_TEXTURE_RECTANGLE_ARB &&
+ !((_mesa_is_cube_face(target) || target == GL_PROXY_TEXTURE_CUBE_MAP) &&
+ (ctx->VersionMajor >= 3 || ctx->Extensions.EXT_gpu_shader4))) {
if (!isProxy)
_mesa_error(ctx, GL_INVALID_ENUM,
"glTexImage(target/internalFormat)");
"glTexImage%dD(target)", dimensions);
return GL_TRUE;
}
+ if (compressedteximage_only_format(ctx, internalFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexImage%dD(no compression for format)", dimensions);
+ return GL_TRUE;
+ }
if (border != 0) {
if (!isProxy) {
_mesa_error(ctx, GL_INVALID_OPERATION,
if (_mesa_is_format_compressed(destTex->TexFormat)) {
GLuint bw, bh;
+ if (compressedteximage_only_format(ctx, destTex->InternalFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexSubImage%dD(no compression for format)", dimensions);
+ return GL_TRUE;
+ }
+
/* do tests which depend on compression block size */
_mesa_get_format_block_size(destTex->TexFormat, &bw, &bh);
"glCopyTexImage%dD(target)", dimensions);
return GL_TRUE;
}
+ if (compressedteximage_only_format(ctx, internalFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexImage%dD(no compression for format)", dimensions);
+ return GL_TRUE;
+ }
if (border != 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyTexImage%dD(border!=0)", dimensions);
}
if (_mesa_is_format_compressed(teximage->TexFormat)) {
+ if (compressedteximage_only_format(ctx, teximage->InternalFormat)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyTexSubImage%dD(no compression for format)", dimensions);
+ return GL_TRUE;
+ }
/* offset must be multiple of 4 */
if ((xoffset & 3) || (yoffset & 3)) {
_mesa_error(ctx, GL_INVALID_VALUE,
* in size or format since that effects FBO completeness.
* Any FBOs rendering into the texture must be re-validated.
*/
-static void
-update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj,
- GLuint face, GLuint level)
+void
+_mesa_update_fbo_texture(struct gl_context *ctx,
+ struct gl_texture_object *texObj,
+ GLuint face, GLuint level)
{
/* Only check this texture if it's been marked as RenderToTexture */
if (texObj->_RenderToTexture) {
format, type);
if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ _mesa_init_teximage_fields(ctx, texImage, width, height,
depth, border, internalFormat,
texFormat);
}
type);
if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage,
+ _mesa_init_teximage_fields(ctx, texImage,
width, height, depth,
border, internalFormat, texFormat);
ASSERT(ctx->Driver.TexImage3D);
switch (dims) {
case 1:
- ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ ctx->Driver.TexImage1D(ctx, texImage, internalFormat,
width, border, format,
- type, pixels, unpack, texObj,
- texImage);
+ type, pixels, unpack);
break;
case 2:
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ ctx->Driver.TexImage2D(ctx, texImage, internalFormat,
width, height, border, format,
- type, pixels, unpack, texObj,
- texImage);
+ type, pixels, unpack);
break;
case 3:
- ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
+ ctx->Driver.TexImage3D(ctx, texImage, internalFormat,
width, height, depth, border, format,
- type, pixels, unpack, texObj,
- texImage);
+ type, pixels, unpack);
break;
default:
_mesa_problem(ctx, "invalid dims=%u in teximage()", dims);
check_gen_mipmap(ctx, target, texObj, level);
- update_fbo_texture(ctx, texObj, face, level);
+ _mesa_update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->_Complete = GL_FALSE;
switch (dims) {
case 1:
- ctx->Driver.TexSubImage1D(ctx, target, level,
+ ctx->Driver.TexSubImage1D(ctx, texImage,
xoffset, width,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
+ format, type, pixels, &ctx->Unpack);
break;
case 2:
- ctx->Driver.TexSubImage2D(ctx, target, level,
+ ctx->Driver.TexSubImage2D(ctx, texImage,
xoffset, yoffset, width, height,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
+ format, type, pixels, &ctx->Unpack);
break;
case 3:
- ctx->Driver.TexSubImage3D(ctx, target, level,
+ ctx->Driver.TexSubImage3D(ctx, texImage,
xoffset, yoffset, zoffset,
width, height, depth,
- format, type, pixels,
- &ctx->Unpack, texObj, texImage );
+ format, type, pixels, &ctx->Unpack);
break;
default:
_mesa_problem(ctx, "unexpected dims in subteximage()");
+/**
+ * For glCopyTexSubImage, return the source renderbuffer to copy texel data
+ * from. This depends on whether the texture contains color or depth values.
+ */
+static struct gl_renderbuffer *
+get_copy_tex_image_source(struct gl_context *ctx, gl_format texFormat)
+{
+ if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) {
+ /* reading from depth/stencil buffer */
+ return ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ }
+ else {
+ /* copying from color buffer */
+ return ctx->ReadBuffer->_ColorReadBuffer;
+ }
+}
+
+
+
/**
* Implement the glCopyTexImage1/2D() functions.
*/
/* Free old texture image */
ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
- _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
+ _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
border, internalFormat, texFormat);
/* Allocate texture memory (no pixel data yet) */
if (dims == 1) {
- ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
+ ctx->Driver.TexImage1D(ctx, texImage, internalFormat,
width, border, GL_NONE, GL_NONE, NULL,
- &ctx->Unpack, texObj, texImage);
+ &ctx->Unpack);
}
else {
- ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
+ ctx->Driver.TexImage2D(ctx, texImage, internalFormat,
width, height, border, GL_NONE, GL_NONE,
- NULL, &ctx->Unpack, texObj, texImage);
+ NULL, &ctx->Unpack);
}
if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY,
&width, &height)) {
+ struct gl_renderbuffer *srcRb =
+ get_copy_tex_image_source(ctx, texImage->TexFormat);
+
if (dims == 1)
- ctx->Driver.CopyTexSubImage1D(ctx, target, level, dstX,
- srcX, srcY, width);
+ ctx->Driver.CopyTexSubImage1D(ctx, texImage, dstX,
+ srcRb, srcX, srcY, width);
else
- ctx->Driver.CopyTexSubImage2D(ctx, target, level, dstX, dstY,
- srcX, srcY, width, height);
+ ctx->Driver.CopyTexSubImage2D(ctx, texImage, dstX, dstY,
+ srcRb, srcX, srcY, width, height);
}
check_gen_mipmap(ctx, target, texObj, level);
- update_fbo_texture(ctx, texObj, face, level);
+ _mesa_update_fbo_texture(ctx, texObj, face, level);
/* state update */
texObj->_Complete = GL_FALSE;
if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
&width, &height)) {
+ struct gl_renderbuffer *srcRb =
+ get_copy_tex_image_source(ctx, texImage->TexFormat);
+
switch (dims) {
case 1:
- ctx->Driver.CopyTexSubImage1D(ctx, target, level,
- xoffset, x, y, width);
+ ctx->Driver.CopyTexSubImage1D(ctx, texImage, xoffset,
+ srcRb, x, y, width);
break;
case 2:
- ctx->Driver.CopyTexSubImage2D(ctx, target, level,
- xoffset, yoffset,
- x, y, width, height);
+ ctx->Driver.CopyTexSubImage2D(ctx, texImage, xoffset, yoffset,
+ srcRb, x, y, width, height);
break;
case 3:
- ctx->Driver.CopyTexSubImage3D(ctx, target, level,
+ ctx->Driver.CopyTexSubImage3D(ctx, texImage,
xoffset, yoffset, zoffset,
- x, y, width, height);
+ srcRb, x, y, width, height);
break;
default:
_mesa_problem(ctx, "bad dims in copytexsubimage()");
return GL_TRUE;
}
+ if (compressedteximage_only_format(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCompressedTexSubImage%uD(format=0x%x cannot be updated)"
+ , dims, format);
+ return GL_TRUE;
+ }
+
if (((width == 1 || width == 2) &&
width != (GLsizei) texImage->Width) ||
(width > (GLsizei) texImage->Width)) {
internalFormat, width, height, depth,
border, imageSize, &reason);
- if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason);
- return;
- }
-
#if FEATURE_ES
/* XXX this is kind of a hack */
- if (dims == 2) {
+ if (!error && dims == 2) {
switch (internalFormat) {
case GL_PALETTE4_RGB8_OES:
case GL_PALETTE4_RGBA8_OES:
}
else {
/* no error: store the teximage parameters */
- _mesa_init_teximage_fields(ctx, target, texImage, width, height,
+ _mesa_init_teximage_fields(ctx, texImage, width, height,
depth, border, internalFormat,
MESA_FORMAT_NONE);
}
struct gl_texture_image *texImage;
if (error) {
- _mesa_error(ctx, error, "glCompressedTexImage%uD", dims);
+ _mesa_error(ctx, error, "glCompressedTexImage%uD(%s)", dims, reason);
return;
}
GL_NONE);
if (legal_texture_size(ctx, texFormat, width, height, depth)) {
- _mesa_init_teximage_fields(ctx, target, texImage,
+ _mesa_init_teximage_fields(ctx, texImage,
width, height, depth,
border, internalFormat, texFormat);
switch (dims) {
case 1:
ASSERT(ctx->Driver.CompressedTexImage1D);
- ctx->Driver.CompressedTexImage1D(ctx, target, level,
+ ctx->Driver.CompressedTexImage1D(ctx, texImage,
internalFormat,
width,
- border, imageSize, data,
- texObj, texImage);
+ border, imageSize, data);
break;
case 2:
ASSERT(ctx->Driver.CompressedTexImage2D);
- ctx->Driver.CompressedTexImage2D(ctx, target, level,
+ ctx->Driver.CompressedTexImage2D(ctx, texImage,
internalFormat,
width, height,
- border, imageSize, data,
- texObj, texImage);
+ border, imageSize, data);
break;
case 3:
ASSERT(ctx->Driver.CompressedTexImage3D);
- ctx->Driver.CompressedTexImage3D(ctx, target, level,
+ ctx->Driver.CompressedTexImage3D(ctx, texImage,
internalFormat,
width, height, depth,
- border, imageSize, data,
- texObj, texImage);
+ border, imageSize, data);
break;
default:
_mesa_problem(ctx, "bad dims in compressedteximage");
switch (dims) {
case 1:
if (ctx->Driver.CompressedTexSubImage1D) {
- ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
+ ctx->Driver.CompressedTexSubImage1D(ctx, texImage,
xoffset, width,
- format, imageSize, data,
- texObj, texImage);
+ format, imageSize, data);
}
break;
case 2:
if (ctx->Driver.CompressedTexSubImage2D) {
- ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
+ ctx->Driver.CompressedTexSubImage2D(ctx, texImage,
xoffset, yoffset,
width, height,
- format, imageSize, data,
- texObj, texImage);
+ format, imageSize, data);
}
break;
case 3:
if (ctx->Driver.CompressedTexSubImage3D) {
- ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
+ ctx->Driver.CompressedTexSubImage3D(ctx, texImage,
xoffset, yoffset, zoffset,
width, height, depth,
- format, imageSize, data,
- texObj, texImage);
+ format, imageSize, data);
}
break;
default: