glapi/copyimage: Implement CopyImageSubDataNV
authorIndrajit Kumar Das <indrajit-kumar.das@amd.com>
Mon, 20 Jan 2020 08:49:47 +0000 (14:19 +0530)
committerMarge Bot <eric+marge@anholt.net>
Mon, 24 Feb 2020 16:31:06 +0000 (16:31 +0000)
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 <marek.olsak@amd.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3649>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3649>

docs/relnotes/new_features.txt
src/mapi/glapi/gen/NV_copy_image.xml [new file with mode: 0644]
src/mapi/glapi/gen/gl_API.xml
src/mapi/glapi/gen/meson.build
src/mapi/glapi/gen/static_data.py
src/mesa/main/copyimage.c
src/mesa/main/copyimage.h
src/mesa/main/extensions_table.h
src/mesa/main/mtypes.h
src/mesa/main/tests/dispatch_sanity.cpp
src/mesa/state_tracker/st_extensions.c

index 2fe8ecaf8df772680c07a8186b2dba122cffa8e1..7d8597d2ee49f8ac1e2755fc8c3fcde9428bfc83 100644 (file)
@@ -1 +1,2 @@
+GL_NV_copy_image
 VK_KHR_shader_non_semantic_info on Intel, RADV.
diff --git a/src/mapi/glapi/gen/NV_copy_image.xml b/src/mapi/glapi/gen/NV_copy_image.xml
new file mode 100644 (file)
index 0000000..9fe144c
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_NV_copy_image" number="376" no_error="true">
+    <function name="CopyImageSubDataNV">
+        <param name="srcName" type="GLuint"/>
+        <param name="srcTarget" type="GLenum"/>
+        <param name="srcLevel" type="GLint"/>
+        <param name="srcX" type="GLint"/>
+        <param name="srcY" type="GLint"/>
+        <param name="srcZ" type="GLint"/>
+        <param name="dstName" type="GLuint"/>
+        <param name="dstTarget" type="GLenum"/>
+        <param name="dstLevel" type="GLint"/>
+        <param name="dstX" type="GLint"/>
+        <param name="dstY" type="GLint"/>
+        <param name="dstZ" type="GLint"/>
+        <param name="width" type="GLsizei"/>
+        <param name="height" type="GLsizei"/>
+        <param name="depth" type="GLsizei"/>
+    </function>
+
+</category>
+
+</OpenGLAPI>
index 1cee28f3105b91111ce9fe1d612398df0cfc49f0..154f85cd4d572fcdd05ab873d27d7fec79e87769 100644 (file)
 <xi:include href="EXT_separate_shader_objects.xml"
            xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
+<xi:include href="NV_copy_image.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
 <xi:include href="EXT_vertex_attrib_64bit.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
 <xi:include href="AMD_depth_clamp_separate.xml"
index 1e69242e042e721fbafdc361e62dca3565544105..007f0dc2346c1f631ce645feb95ea345a46c6011 100644 (file)
@@ -133,6 +133,7 @@ api_xml_files = files(
   'KHR_robustness.xml',
   'KHR_robustness_es.xml',
   'KHR_texture_compression_astc.xml',
+  'NV_copy_image.xml',
   'NV_conditional_render.xml',
   'NV_primitive_restart.xml',
   'NV_texture_barrier.xml',
index d2a9c66b4cd6bcf4a3be49b480cb15f001fe5450..367b51338b94d3985006fd5f11f6421319e0eaa4 100644 (file)
@@ -1640,6 +1640,7 @@ offsets = {
     "GetNamedStringivARB": 1604,
     "EGLImageTargetTexStorageEXT" : 1605,
     "EGLImageTargetTextureStorageEXT" : 1606,
+    "CopyImageSubDataNV": 1607,
 }
 
 functions = [
index 10777cfdf0570e877ef89e6c22cbd40103f16b6f..3373c6e8cbbcedec952ef23d5aa221365f1f3c7e 100644 (file)
@@ -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);
+}
index 7cebb30d997c171486b5e3bbfb711dd95bb2d5bf..09f6dca3bdf0a449c371b6564d33e9dea53f8964 100644 (file)
@@ -49,6 +49,20 @@ _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
                        GLint destX, GLint destY, GLint destZ,
                        GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
 
+void GLAPIENTRY
+_mesa_CopyImageSubDataNV_no_error(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+                                GLint srcX, GLint srcY, GLint srcZ,
+                                GLuint destName, GLenum destTarget, GLint destLevel,
+                                GLint destX, GLint destY, GLint destZ,
+                                GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+
+extern void GLAPIENTRY
+_mesa_CopyImageSubDataNV(GLuint srcName, GLenum srcTarget, GLint srcLevel,
+                       GLint srcX, GLint srcY, GLint srcZ,
+                       GLuint destName, GLenum destTarget, GLint destLevel,
+                       GLint destX, GLint destY, GLint destZ,
+                       GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+
 #ifdef __cplusplus
 }
 #endif
index 1f5d88e412b69bc96e35375db081e73d6662a853..0301590223dcf8927046a8f2d9969c5c6954f23c 100644 (file)
@@ -378,6 +378,7 @@ EXT(NV_conservative_raster                  , NV_conservative_raster
 EXT(NV_conservative_raster_dilate           , NV_conservative_raster_dilate          , GLL, GLC, ES1, ES2, 2015)
 EXT(NV_conservative_raster_pre_snap         , NV_conservative_raster_pre_snap        , GLL, GLC, ES1, ES2, 2017)
 EXT(NV_conservative_raster_pre_snap_triangles, NV_conservative_raster_pre_snap_triangles, GLL, GLC, ES1, ES2, 2015)
+EXT(NV_copy_image                           , NV_copy_image                          , GLL, GLC,  x ,  x,  2009)
 EXT(NV_depth_clamp                          , ARB_depth_clamp                        , GLL, GLC,  x ,  x , 2001)
 EXT(NV_draw_buffers                         , dummy_true                             ,  x ,  x ,  x , ES2, 2011)
 EXT(NV_fbo_color_attachments                , dummy_true                             ,  x ,  x ,  x , ES2, 2010)
index db4921d0106e35f4ea0f723c97289360499ba64f..2ad1ffd82cd043417f4369694f2fb6a05a8bf22a 100644 (file)
@@ -4394,6 +4394,7 @@ struct gl_extensions
    GLboolean MESA_ycbcr_texture;
    GLboolean NV_compute_shader_derivatives;
    GLboolean NV_conditional_render;
+   GLboolean NV_copy_image;
    GLboolean NV_fill_rectangle;
    GLboolean NV_fog_distance;
    GLboolean NV_point_sprite;
index 0a86c127d0543dfd0b8cc75099ee3b7c124fcf6f..e0324bd54d28750eaa8c42a584064bc71cc5f58a 100644 (file)
@@ -563,6 +563,9 @@ const struct function common_desktop_functions_possible[] = {
    { "glEGLImageTargetTexStorageEXT", 31, -1 },
    { "glEGLImageTargetTextureStorageEXT", 31, -1 },
 
+   /* GL_NV_copy_image */
+   { "glCopyImageSubDataNV", 31, -1 },
+
    /* GL 3.2 */
    { "glGetInteger64i_v", 32, -1 },
    { "glGetBufferParameteri64v", 32, -1 },
index f3d13d7ad8c8dd265323b89d0c9581c42cc1f8b2..446c9b5a618b069cbca5a3c6284f395a332c341c 100644 (file)
@@ -1036,6 +1036,7 @@ void st_init_extensions(struct pipe_screen *screen,
    extensions->MESA_framebuffer_flip_y = GL_TRUE;
    extensions->MESA_pack_invert = GL_TRUE;
 
+   extensions->NV_copy_image = GL_TRUE;
    extensions->NV_fog_distance = GL_TRUE;
    extensions->NV_texture_env_combine4 = GL_TRUE;
    extensions->NV_texture_rectangle = GL_TRUE;