* Jason Ekstrand <jason.ekstrand@intel.com>
*/
+#include "context.h"
#include "glheader.h"
#include "errors.h"
#include "enums.h"
struct gl_renderbuffer **renderbuffer,
mesa_format *format,
GLenum *internalFormat,
+ GLuint *width,
+ GLuint *height,
+ GLuint *num_samples,
const char *dbg_prefix)
{
if (name == 0) {
*renderbuffer = rb;
*format = rb->Format;
*internalFormat = rb->InternalFormat;
+ *width = rb->Width;
+ *height = rb->Height;
+ *num_samples = rb->NumSamples;
*tex_image = NULL;
} else {
struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
if (!texObj) {
+ /*
+ * From GL_ARB_copy_image specification:
+ * "INVALID_VALUE is generated if either <srcName> or <dstName> does
+ * not correspond to a valid renderbuffer or texture object according
+ * to the corresponding target parameter."
+ */
_mesa_error(ctx, GL_INVALID_VALUE,
"glCopyImageSubData(%sName = %u)", dbg_prefix, name);
return false;
/* Note that target will not be a cube face name */
if (texObj->Target != target) {
/*
- * From GL_ARB_copy_image specification:
- * "INVALID_VALUE is generated if either <srcName> or <dstName> does
- * not correspond to a valid renderbuffer or texture object according
- * to the corresponding target parameter."
+ * From GL_ARB_copy_image_specification:
+ * "INVALID_ENUM is generated if the target does not match the type
+ * of the object."
*/
- _mesa_error(ctx, GL_INVALID_VALUE,
+ _mesa_error(ctx, GL_INVALID_ENUM,
"glCopyImageSubData(%sTarget = %s)", dbg_prefix,
_mesa_enum_to_string(target));
return false;
for (i = 0; i < depth; i++) {
if (!texObj->Image[z+i][level]) {
/* missing cube face */
- _mesa_error(ctx, GL_INVALID_OPERATION,
+ _mesa_error(ctx, GL_INVALID_VALUE,
"glCopyImageSubData(missing cube face)");
return false;
}
*renderbuffer = NULL;
*format = (*tex_image)->TexFormat;
*internalFormat = (*tex_image)->InternalFormat;
+ *width = (*tex_image)->Width;
+ *height = (*tex_image)->Height;
+ *num_samples = (*tex_image)->NumSamples;
}
return true;
case GL_COMPRESSED_SIGNED_RED_RGTC1:
compressedClass = BLOCK_CLASS_64_BITS;
break;
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ case GL_COMPRESSED_RG11_EAC:
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ if (_mesa_is_gles(ctx))
+ compressedClass = BLOCK_CLASS_128_BITS;
+ else
+ return false;
+ break;
+ case GL_COMPRESSED_RGB8_ETC2:
+ case GL_COMPRESSED_SRGB8_ETC2:
+ case GL_COMPRESSED_R11_EAC:
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ if (_mesa_is_gles(ctx))
+ compressedClass = BLOCK_CLASS_64_BITS;
+ else
+ return false;
+ break;
default:
- return false;
+ if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat))
+ compressedClass = BLOCK_CLASS_128_BITS;
+ else
+ return false;
+ break;
}
switch (otherFormat) {
struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
mesa_format srcFormat, dstFormat;
GLenum srcIntFormat, dstIntFormat;
+ GLuint src_w, src_h, dst_w, dst_h;
GLuint src_bw, src_bh, dst_bw, dst_bh;
+ GLuint src_num_samples, dst_num_samples;
int dstWidth, dstHeight, dstDepth;
int i;
if (!prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
&srcTexImage, &srcRenderbuffer, &srcFormat,
- &srcIntFormat, "src"))
+ &srcIntFormat, &src_w, &src_h, &src_num_samples, "src"))
return;
if (!prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
&dstTexImage, &dstRenderbuffer, &dstFormat,
- &dstIntFormat, "dst"))
+ &dstIntFormat, &dst_w, &dst_h, &dst_num_samples, "dst"))
return;
_mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
+
+ /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
+ * spec says:
+ *
+ * An INVALID_VALUE error is generated if the dimensions of either
+ * subregion exceeds the boundaries of the corresponding image object,
+ * or if the image format is compressed and the dimensions of the
+ * subregion fail to meet the alignment constraints of the format.
+ *
+ * and Section 8.7 (Compressed Texture Images) says:
+ *
+ * An INVALID_OPERATION error is generated if any of the following
+ * conditions occurs:
+ *
+ * * width is not a multiple of four, and width + xoffset is not
+ * equal to the value of TEXTURE_WIDTH.
+ * * height is not a multiple of four, and height + yoffset is not
+ * equal to the value of TEXTURE_HEIGHT.
+ *
+ * so we take that to mean that you can copy the "last" block of a
+ * compressed texture image even if it's smaller than the minimum block
+ * dimensions.
+ */
if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
- (srcWidth % src_bw != 0) || (srcHeight % src_bh != 0)) {
+ (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
+ (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glCopyImageSubData(unaligned src rectangle)");
return;
"dst"))
return;
+ /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
+ * spec says:
+ *
+ * An INVALID_OPERATION error is generated if either object is a texture
+ * and the texture is not complete, if the source and destination internal
+ * formats are not compatible, or if the number of samples do not match.
+ */
if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glCopyImageSubData(internalFormat mismatch)");
return;
}
+ if (src_num_samples != dst_num_samples) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubData(number of samples mismatch)");
+ return;
+ }
+
/* loop over 2D slices/faces/layers */
for (i = 0; i < srcDepth; ++i) {
int newSrcZ = srcZ + i;