summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mesa/main/copyimage.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c
index f02e842f34d..d571d221bce 100644
--- a/src/mesa/main/copyimage.c
+++ b/src/mesa/main/copyimage.c
@@ -62,6 +62,8 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
struct gl_renderbuffer **renderbuffer,
mesa_format *format,
GLenum *internalFormat,
+ GLuint *width,
+ GLuint *height,
const char *dbg_prefix)
{
if (name == 0) {
@@ -126,6 +128,8 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
*renderbuffer = rb;
*format = rb->Format;
*internalFormat = rb->InternalFormat;
+ *width = rb->Width;
+ *height = rb->Height;
*tex_image = NULL;
} else {
struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
@@ -194,6 +198,8 @@ prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
*renderbuffer = NULL;
*format = (*tex_image)->TexFormat;
*internalFormat = (*tex_image)->InternalFormat;
+ *width = (*tex_image)->Width;
+ *height = (*tex_image)->Height;
}
return true;
@@ -423,6 +429,7 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
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;
int dstWidth, dstHeight, dstDepth;
int i;
@@ -445,17 +452,41 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
if (!prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
&srcTexImage, &srcRenderbuffer, &srcFormat,
- &srcIntFormat, "src"))
+ &srcIntFormat, &src_w, &src_h, "src"))
return;
if (!prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
&dstTexImage, &dstRenderbuffer, &dstFormat,
- &dstIntFormat, "dst"))
+ &dstIntFormat, &dst_w, &dst_h, "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;