aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/main/copyimage.c
diff options
context:
space:
mode:
authorIndrajit Kumar Das <[email protected]>2020-01-20 14:19:47 +0530
committerMarge Bot <[email protected]>2020-02-24 16:31:06 +0000
commit18124d727865f1c53b0dac644560bce177b7d233 (patch)
tree09bc2e6e10214fb6bd457cc3bc45725afd43bb3d /src/mesa/main/copyimage.c
parentae7bda27a0691d6d89c35c9f732b6e49d726c17f (diff)
glapi/copyimage: Implement CopyImageSubDataNV
Implement CopyImageSubDataNV from NV_copy_image spec. This is derived out of the existing implementation of CopyImageSubData. It differs from CopyImageSubData in accordance with the differences laid down in the ARB_copy_image spec. Reviewed-by: Marek Olšák <[email protected]> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3649> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3649>
Diffstat (limited to 'src/mesa/main/copyimage.c')
-rw-r--r--src/mesa/main/copyimage.c200
1 files changed, 174 insertions, 26 deletions
diff --git a/src/mesa/main/copyimage.c b/src/mesa/main/copyimage.c
index 10777cfdf05..3373c6e8cbb 100644
--- a/src/mesa/main/copyimage.c
+++ b/src/mesa/main/copyimage.c
@@ -66,11 +66,14 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
GLuint *width,
GLuint *height,
GLuint *num_samples,
- const char *dbg_prefix)
+ const char *dbg_prefix,
+ bool is_arb_version)
{
+ const char *suffix = is_arb_version ? "" : "NV";
+
if (name == 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sName = %d)", dbg_prefix, name);
+ "glCopyImageSubData%s(%sName = %d)", suffix, dbg_prefix, name);
return false;
}
@@ -101,7 +104,7 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
case GL_TEXTURE_BUFFER:
default:
_mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
+ "glCopyImageSubData%s(%sTarget = %s)", suffix, dbg_prefix,
_mesa_enum_to_string(target));
return false;
}
@@ -111,19 +114,19 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
if (!rb) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
+ "glCopyImageSubData%s(%sName = %u)", suffix, dbg_prefix, name);
return false;
}
if (!rb->Name) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyImageSubData(%sName incomplete)", dbg_prefix);
+ "glCopyImageSubData%s(%sName incomplete)", suffix, dbg_prefix);
return false;
}
if (level != 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
+ "glCopyImageSubData%s(%sLevel = %u)", suffix, dbg_prefix, level);
return false;
}
@@ -145,7 +148,7 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
* to the corresponding target parameter."
*/
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
+ "glCopyImageSubData%s(%sName = %u)", suffix, dbg_prefix, name);
return false;
}
@@ -208,7 +211,7 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
: texObj->_BaseComplete;
if (!texture_complete_aside_from_formats) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "glCopyImageSubData(%sName incomplete)", dbg_prefix);
+ "glCopyImageSubData%s(%sName incomplete)", suffix, dbg_prefix);
return false;
}
@@ -220,14 +223,14 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
* of the object."
*/
_mesa_error(ctx, GL_INVALID_ENUM,
- "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
+ "glCopyImageSubData%s(%sTarget = %s)", suffix, dbg_prefix,
_mesa_enum_to_string(target));
return false;
}
if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
+ "glCopyImageSubData%s(%sLevel = %d)", suffix, dbg_prefix, level);
return false;
}
@@ -254,7 +257,7 @@ prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
if (!*tex_image) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
+ "glCopyImageSubData%s(%sLevel = %u)", suffix, dbg_prefix, level);
return false;
}
@@ -305,21 +308,23 @@ check_region_bounds(struct gl_context *ctx,
const struct gl_texture_image *tex_image,
const struct gl_renderbuffer *renderbuffer,
int x, int y, int z, int width, int height, int depth,
- const char *dbg_prefix)
+ const char *dbg_prefix,
+ bool is_arb_version)
{
int surfWidth, surfHeight, surfDepth;
+ const char *suffix = is_arb_version ? "" : "NV";
if (width < 0 || height < 0 || depth < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)",
- dbg_prefix, dbg_prefix, dbg_prefix);
+ "glCopyImageSubData%s(%sWidth, %sHeight, or %sDepth is negative)",
+ suffix, dbg_prefix, dbg_prefix, dbg_prefix);
return false;
}
if (x < 0 || y < 0 || z < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sX, %sY, or %sZ is negative)",
- dbg_prefix, dbg_prefix, dbg_prefix);
+ "glCopyImageSubData%s(%sX, %sY, or %sZ is negative)",
+ suffix, dbg_prefix, dbg_prefix, dbg_prefix);
return false;
}
@@ -333,8 +338,8 @@ check_region_bounds(struct gl_context *ctx,
if (x + width > surfWidth) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sX or %sWidth exceeds image bounds)",
- dbg_prefix, dbg_prefix);
+ "glCopyImageSubData%s(%sX or %sWidth exceeds image bounds)",
+ suffix, dbg_prefix, dbg_prefix);
return false;
}
@@ -353,8 +358,8 @@ check_region_bounds(struct gl_context *ctx,
if (y + height > surfHeight) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
- dbg_prefix, dbg_prefix);
+ "glCopyImageSubData%s(%sY or %sHeight exceeds image bounds)",
+ suffix, dbg_prefix, dbg_prefix);
return false;
}
@@ -379,8 +384,8 @@ check_region_bounds(struct gl_context *ctx,
if (z < 0 || z + depth > surfDepth) {
_mesa_error(ctx, GL_INVALID_VALUE,
- "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
- dbg_prefix, dbg_prefix);
+ "glCopyImageSubData%s(%sZ or %sDepth exceeds image bounds)",
+ suffix, dbg_prefix, dbg_prefix);
return false;
}
@@ -630,13 +635,13 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
if (!prepare_target_err(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
&srcTexImage, &srcRenderbuffer, &srcFormat,
&srcIntFormat, &src_w, &src_h, &src_num_samples,
- "src"))
+ "src",true))
return;
if (!prepare_target_err(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
&dstTexImage, &dstRenderbuffer, &dstFormat,
&dstIntFormat, &dst_w, &dst_h, &dst_num_samples,
- "dst"))
+ "dst",true))
return;
_mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
@@ -698,12 +703,12 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
- "src"))
+ "src", true))
return;
if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
- "dst"))
+ "dst", true))
return;
/* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
@@ -729,3 +734,146 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
dstLevel, srcWidth, srcHeight, srcDepth);
}
+
+void GLAPIENTRY
+_mesa_CopyImageSubDataNV_no_error(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+ GLint srcX, GLint srcY, GLint srcZ,
+ GLuint dstName, GLenum dstTarget, GLint dstLevel,
+ GLint dstX, GLint dstY, GLint dstZ,
+ GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+{
+ struct gl_texture_image *srcTexImage, *dstTexImage;
+ struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, &srcTexImage,
+ &srcRenderbuffer);
+
+ prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, &dstTexImage,
+ &dstRenderbuffer);
+
+ copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
+ srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
+ dstLevel, srcWidth, srcHeight, srcDepth);
+}
+
+void GLAPIENTRY
+_mesa_CopyImageSubDataNV(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+ GLint srcX, GLint srcY, GLint srcZ,
+ GLuint dstName, GLenum dstTarget, GLint dstLevel,
+ GLint dstX, GLint dstY, GLint dstZ,
+ GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_texture_image *srcTexImage, *dstTexImage;
+ 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;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glCopyImageSubDataNV(%u, %s, %d, %d, %d, %d, "
+ "%u, %s, %d, %d, %d, %d, "
+ "%d, %d, %d)\n",
+ srcName, _mesa_enum_to_string(srcTarget), srcLevel,
+ srcX, srcY, srcZ,
+ dstName, _mesa_enum_to_string(dstTarget), dstLevel,
+ dstX, dstY, dstZ,
+ srcWidth, srcHeight, srcDepth);
+
+ if (!ctx->Extensions.NV_copy_image) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubDataNV(extension not available)");
+ return;
+ }
+
+ if (!prepare_target_err(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
+ &srcTexImage, &srcRenderbuffer, &srcFormat,
+ &srcIntFormat, &src_w, &src_h, &src_num_samples,
+ "src", false))
+ return;
+
+ if (!prepare_target_err(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
+ &dstTexImage, &dstRenderbuffer, &dstFormat,
+ &dstIntFormat, &dst_w, &dst_h, &dst_num_samples,
+ "dst", false))
+ return;
+
+ /*
+ * The NV_copy_image spec says:
+ *
+ * INVALID_OPERATION is generated if either object is a texture
+ * and the texture is not consistent, or if the source and destination
+ * internal formats or number of samples do not match.
+ *
+ * In the absence of any definition of texture consistency the texture
+ * completeness check, which is affected in the prepare_target_err function,
+ * is used instead in keeping with the ARB version.
+ * The check related to the internal format here is different from the ARB
+ * version which adds the ability to copy between images which have
+ * different formats where the formats are compatible for texture views.
+ */
+ if (srcIntFormat != dstIntFormat) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubDataNV(internalFormat mismatch)");
+ return;
+ }
+
+ if (src_num_samples != dst_num_samples) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glCopyImageSubDataNV(number of samples mismatch)");
+ return;
+ }
+
+ /*
+ * The NV_copy_image spec says:
+ *
+ * INVALID_VALUE is generated if the image format is compressed
+ * and the dimensions of the subregion fail to meet the alignment
+ * constraints of the format.
+ *
+ * The check here is identical to the ARB version.
+ */
+ _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
+ if ((srcX % src_bw != 0) || (srcY % 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,
+ "glCopyImageSubDataNV(unaligned src rectangle)");
+ return;
+ }
+
+ _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
+ if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glCopyImageSubDataNV(unaligned dst rectangle)");
+ return;
+ }
+
+ /*
+ * The NV_copy_image spec says:
+ *
+ * INVALID_VALUE is generated if the dimensions of the either subregion
+ * exceeds the boundaries of the corresponding image object.
+ *
+ * The check here is similar to the ARB version except for the fact that
+ * block sizes are not considered owing to the fact that copying across
+ * compressed and uncompressed formats is not supported.
+ */
+ if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
+ srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
+ "src", false))
+ return;
+
+ if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
+ dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth,
+ "dst", false))
+ return;
+
+ copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
+ srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
+ dstLevel, srcWidth, srcHeight, srcDepth);
+}