Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2014 Intel Corporation.  All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Jason Ekstrand <jason.ekstrand (at) intel.com>
     26  */
     27 
     28 #include "context.h"
     29 #include "glheader.h"
     30 #include "errors.h"
     31 #include "enums.h"
     32 #include "copyimage.h"
     33 #include "teximage.h"
     34 #include "texobj.h"
     35 #include "fbobject.h"
     36 #include "textureview.h"
     37 #include "glformats.h"
     38 
     39 enum mesa_block_class {
     40    BLOCK_CLASS_128_BITS,
     41    BLOCK_CLASS_64_BITS
     42 };
     43 
     44 /**
     45  * Prepare the source or destination resource.  This involves error
     46  * checking and returning the relevant gl_texture_image or gl_renderbuffer.
     47  * Note that one of the resulting tex_image or renderbuffer pointers will be
     48  * NULL and the other will be non-null.
     49  *
     50  * \param name  the texture or renderbuffer name
     51  * \param target  One of GL_TEXTURE_x target or GL_RENDERBUFFER
     52  * \param level  mipmap level
     53  * \param z  src or dest Z
     54  * \param depth  number of slices/faces/layers to copy
     55  * \param tex_image  returns a pointer to a texture image
     56  * \param renderbuffer  returns a pointer to a renderbuffer
     57  * \return true if success, false if error
     58  */
     59 static bool
     60 prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
     61                int level, int z, int depth,
     62                struct gl_texture_image **tex_image,
     63                struct gl_renderbuffer **renderbuffer,
     64                mesa_format *format,
     65                GLenum *internalFormat,
     66                GLuint *width,
     67                GLuint *height,
     68                GLuint *num_samples,
     69                const char *dbg_prefix)
     70 {
     71    if (name == 0) {
     72       _mesa_error(ctx, GL_INVALID_VALUE,
     73                   "glCopyImageSubData(%sName = %d)", dbg_prefix, name);
     74       return false;
     75    }
     76 
     77    /*
     78     * INVALID_ENUM is generated
     79     *  * if either <srcTarget> or <dstTarget>
     80     *   - is not RENDERBUFFER or a valid non-proxy texture target
     81     *   - is TEXTURE_BUFFER, or
     82     *   - is one of the cubemap face selectors described in table 3.17,
     83     */
     84    switch (target) {
     85    case GL_RENDERBUFFER:
     86       /* Not a texture target, but valid */
     87    case GL_TEXTURE_1D:
     88    case GL_TEXTURE_1D_ARRAY:
     89    case GL_TEXTURE_2D:
     90    case GL_TEXTURE_3D:
     91    case GL_TEXTURE_CUBE_MAP:
     92    case GL_TEXTURE_RECTANGLE:
     93    case GL_TEXTURE_2D_ARRAY:
     94    case GL_TEXTURE_CUBE_MAP_ARRAY:
     95    case GL_TEXTURE_2D_MULTISAMPLE:
     96    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
     97       /* These are all valid */
     98       break;
     99    case GL_TEXTURE_EXTERNAL_OES:
    100       /* Only exists in ES */
    101    case GL_TEXTURE_BUFFER:
    102    default:
    103       _mesa_error(ctx, GL_INVALID_ENUM,
    104                   "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
    105                   _mesa_enum_to_string(target));
    106       return false;
    107    }
    108 
    109    if (target == GL_RENDERBUFFER) {
    110       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
    111 
    112       if (!rb) {
    113          _mesa_error(ctx, GL_INVALID_VALUE,
    114                      "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
    115          return false;
    116       }
    117 
    118       if (!rb->Name) {
    119          _mesa_error(ctx, GL_INVALID_OPERATION,
    120                      "glCopyImageSubData(%sName incomplete)", dbg_prefix);
    121          return false;
    122       }
    123 
    124       if (level != 0) {
    125          _mesa_error(ctx, GL_INVALID_VALUE,
    126                      "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
    127          return false;
    128       }
    129 
    130       *renderbuffer = rb;
    131       *format = rb->Format;
    132       *internalFormat = rb->InternalFormat;
    133       *width = rb->Width;
    134       *height = rb->Height;
    135       *num_samples = rb->NumSamples;
    136       *tex_image = NULL;
    137    } else {
    138       struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
    139 
    140       if (!texObj) {
    141          /*
    142           * From GL_ARB_copy_image specification:
    143           * "INVALID_VALUE is generated if either <srcName> or <dstName> does
    144           * not correspond to a valid renderbuffer or texture object according
    145           * to the corresponding target parameter."
    146           */
    147          _mesa_error(ctx, GL_INVALID_VALUE,
    148                      "glCopyImageSubData(%sName = %u)", dbg_prefix, name);
    149          return false;
    150       }
    151 
    152       _mesa_test_texobj_completeness(ctx, texObj);
    153       if (!texObj->_BaseComplete ||
    154           (level != 0 && !texObj->_MipmapComplete)) {
    155          _mesa_error(ctx, GL_INVALID_OPERATION,
    156                      "glCopyImageSubData(%sName incomplete)", dbg_prefix);
    157          return false;
    158       }
    159 
    160       /* Note that target will not be a cube face name */
    161       if (texObj->Target != target) {
    162          /*
    163           * From GL_ARB_copy_image_specification:
    164           * "INVALID_ENUM is generated if the target does not match the type
    165           * of the object."
    166           */
    167          _mesa_error(ctx, GL_INVALID_ENUM,
    168                      "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
    169                      _mesa_enum_to_string(target));
    170          return false;
    171       }
    172 
    173       if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
    174          _mesa_error(ctx, GL_INVALID_VALUE,
    175                      "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
    176          return false;
    177       }
    178 
    179       if (target == GL_TEXTURE_CUBE_MAP) {
    180          int i;
    181 
    182          assert(z < MAX_FACES);  /* should have been caught earlier */
    183 
    184          /* make sure all the cube faces are present */
    185          for (i = 0; i < depth; i++) {
    186             if (!texObj->Image[z+i][level]) {
    187                /* missing cube face */
    188                _mesa_error(ctx, GL_INVALID_VALUE,
    189                            "glCopyImageSubData(missing cube face)");
    190                return false;
    191             }
    192          }
    193 
    194          *tex_image = texObj->Image[z][level];
    195       }
    196       else {
    197          *tex_image = _mesa_select_tex_image(texObj, target, level);
    198       }
    199 
    200       if (!*tex_image) {
    201          _mesa_error(ctx, GL_INVALID_VALUE,
    202                      "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
    203          return false;
    204       }
    205 
    206       *renderbuffer = NULL;
    207       *format = (*tex_image)->TexFormat;
    208       *internalFormat = (*tex_image)->InternalFormat;
    209       *width = (*tex_image)->Width;
    210       *height = (*tex_image)->Height;
    211       *num_samples = (*tex_image)->NumSamples;
    212    }
    213 
    214    return true;
    215 }
    216 
    217 
    218 /**
    219  * Check that the x,y,z,width,height,region is within the texture image
    220  * dimensions.
    221  * \return true if bounds OK, false if regions is out of bounds
    222  */
    223 static bool
    224 check_region_bounds(struct gl_context *ctx,
    225                     GLenum target,
    226                     const struct gl_texture_image *tex_image,
    227                     const struct gl_renderbuffer *renderbuffer,
    228                     int x, int y, int z, int width, int height, int depth,
    229                     const char *dbg_prefix)
    230 {
    231    int surfWidth, surfHeight, surfDepth;
    232 
    233    if (width < 0 || height < 0 || depth < 0) {
    234       _mesa_error(ctx, GL_INVALID_VALUE,
    235                   "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)",
    236                   dbg_prefix, dbg_prefix, dbg_prefix);
    237       return false;
    238    }
    239 
    240    if (x < 0 || y < 0 || z < 0) {
    241       _mesa_error(ctx, GL_INVALID_VALUE,
    242                   "glCopyImageSubData(%sX, %sY, or %sZ is negative)",
    243                   dbg_prefix, dbg_prefix, dbg_prefix);
    244       return false;
    245    }
    246 
    247    /* Check X direction */
    248    if (target == GL_RENDERBUFFER) {
    249       surfWidth = renderbuffer->Width;
    250    }
    251    else {
    252       surfWidth = tex_image->Width;
    253    }
    254 
    255    if (x + width > surfWidth) {
    256       _mesa_error(ctx, GL_INVALID_VALUE,
    257                   "glCopyImageSubData(%sX or %sWidth exceeds image bounds)",
    258                   dbg_prefix, dbg_prefix);
    259       return false;
    260    }
    261 
    262    /* Check Y direction */
    263    switch (target) {
    264    case GL_RENDERBUFFER:
    265       surfHeight = renderbuffer->Height;
    266       break;
    267    case GL_TEXTURE_1D:
    268    case GL_TEXTURE_1D_ARRAY:
    269       surfHeight = 1;
    270       break;
    271    default:
    272       surfHeight = tex_image->Height;
    273    }
    274 
    275    if (y + height > surfHeight) {
    276       _mesa_error(ctx, GL_INVALID_VALUE,
    277                   "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
    278                   dbg_prefix, dbg_prefix);
    279       return false;
    280    }
    281 
    282    /* Check Z direction */
    283    switch (target) {
    284    case GL_RENDERBUFFER:
    285    case GL_TEXTURE_1D:
    286    case GL_TEXTURE_2D:
    287    case GL_TEXTURE_2D_MULTISAMPLE:
    288    case GL_TEXTURE_RECTANGLE:
    289       surfDepth = 1;
    290       break;
    291    case GL_TEXTURE_CUBE_MAP:
    292       surfDepth = 6;
    293       break;
    294    case GL_TEXTURE_1D_ARRAY:
    295       surfDepth = tex_image->Height;
    296       break;
    297    default:
    298       surfDepth = tex_image->Depth;
    299    }
    300 
    301    if (z < 0 || z + depth > surfDepth) {
    302       _mesa_error(ctx, GL_INVALID_VALUE,
    303                   "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
    304                   dbg_prefix, dbg_prefix);
    305       return false;
    306    }
    307 
    308    return true;
    309 }
    310 
    311 static bool
    312 compressed_format_compatible(const struct gl_context *ctx,
    313                              GLenum compressedFormat, GLenum otherFormat)
    314 {
    315    enum mesa_block_class compressedClass, otherClass;
    316 
    317    /* Two view-incompatible compressed formats are never compatible. */
    318    if (_mesa_is_compressed_format(ctx, otherFormat)) {
    319       return false;
    320    }
    321 
    322    /*
    323     * From ARB_copy_image spec:
    324     *    Table 4.X.1 (Compatible internal formats for copying between
    325     *                 compressed and uncompressed internal formats)
    326     *    ---------------------------------------------------------------------
    327     *    | Texel / | Uncompressed      |                                     |
    328     *    | Block   | internal format   | Compressed internal format          |
    329     *    | size    |                   |                                     |
    330     *    ---------------------------------------------------------------------
    331     *    | 128-bit | RGBA32UI,         | COMPRESSED_RGBA_S3TC_DXT3_EXT,      |
    332     *    |         | RGBA32I,          | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
    333     *    |         | RGBA32F           | COMPRESSED_RGBA_S3TC_DXT5_EXT,      |
    334     *    |         |                   | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
    335     *    |         |                   | COMPRESSED_RG_RGTC2,                |
    336     *    |         |                   | COMPRESSED_SIGNED_RG_RGTC2,         |
    337     *    |         |                   | COMPRESSED_RGBA_BPTC_UNORM,         |
    338     *    |         |                   | COMPRESSED_SRGB_ALPHA_BPTC_UNORM,   |
    339     *    |         |                   | COMPRESSED_RGB_BPTC_SIGNED_FLOAT,   |
    340     *    |         |                   | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT  |
    341     *    ---------------------------------------------------------------------
    342     *    | 64-bit  | RGBA16F, RG32F,   | COMPRESSED_RGB_S3TC_DXT1_EXT,       |
    343     *    |         | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT,      |
    344     *    |         | RGBA16I, RG32I,   | COMPRESSED_RGBA_S3TC_DXT1_EXT,      |
    345     *    |         | RGBA16,           | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
    346     *    |         | RGBA16_SNORM      | COMPRESSED_RED_RGTC1,               |
    347     *    |         |                   | COMPRESSED_SIGNED_RED_RGTC1         |
    348     *    ---------------------------------------------------------------------
    349     */
    350 
    351    switch (compressedFormat) {
    352       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
    353       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
    354       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
    355       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
    356       case GL_COMPRESSED_RG_RGTC2:
    357       case GL_COMPRESSED_SIGNED_RG_RGTC2:
    358       case GL_COMPRESSED_RGBA_BPTC_UNORM:
    359       case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
    360       case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
    361       case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
    362          compressedClass = BLOCK_CLASS_128_BITS;
    363          break;
    364       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
    365       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
    366       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
    367       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
    368       case GL_COMPRESSED_RED_RGTC1:
    369       case GL_COMPRESSED_SIGNED_RED_RGTC1:
    370          compressedClass = BLOCK_CLASS_64_BITS;
    371          break;
    372       case GL_COMPRESSED_RGBA8_ETC2_EAC:
    373       case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
    374       case GL_COMPRESSED_RG11_EAC:
    375       case GL_COMPRESSED_SIGNED_RG11_EAC:
    376          if (_mesa_is_gles(ctx))
    377             compressedClass = BLOCK_CLASS_128_BITS;
    378          else
    379             return false;
    380          break;
    381       case GL_COMPRESSED_RGB8_ETC2:
    382       case GL_COMPRESSED_SRGB8_ETC2:
    383       case GL_COMPRESSED_R11_EAC:
    384       case GL_COMPRESSED_SIGNED_R11_EAC:
    385       case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    386       case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    387          if (_mesa_is_gles(ctx))
    388             compressedClass = BLOCK_CLASS_64_BITS;
    389          else
    390             return false;
    391          break;
    392       default:
    393          if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat))
    394             compressedClass = BLOCK_CLASS_128_BITS;
    395          else
    396             return false;
    397          break;
    398    }
    399 
    400    switch (otherFormat) {
    401       case GL_RGBA32UI:
    402       case GL_RGBA32I:
    403       case GL_RGBA32F:
    404          otherClass = BLOCK_CLASS_128_BITS;
    405          break;
    406       case GL_RGBA16F:
    407       case GL_RG32F:
    408       case GL_RGBA16UI:
    409       case GL_RG32UI:
    410       case GL_RGBA16I:
    411       case GL_RG32I:
    412       case GL_RGBA16:
    413       case GL_RGBA16_SNORM:
    414          otherClass = BLOCK_CLASS_64_BITS;
    415          break;
    416       default:
    417          return false;
    418    }
    419 
    420    return compressedClass == otherClass;
    421 }
    422 
    423 static bool
    424 copy_format_compatible(const struct gl_context *ctx,
    425                        GLenum srcFormat, GLenum dstFormat)
    426 {
    427    /*
    428     * From ARB_copy_image spec:
    429     *    For the purposes of CopyImageSubData, two internal formats
    430     *    are considered compatible if any of the following conditions are
    431     *    met:
    432     *    * the formats are the same,
    433     *    * the formats are considered compatible according to the
    434     *      compatibility rules used for texture views as defined in
    435     *      section 3.9.X. In particular, if both internal formats are listed
    436     *      in the same entry of Table 3.X.2, they are considered compatible, or
    437     *    * one format is compressed and the other is uncompressed and
    438     *      Table 4.X.1 lists the two formats in the same row.
    439     */
    440 
    441    if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
    442       /* Also checks if formats are equal. */
    443       return true;
    444    } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
    445       return compressed_format_compatible(ctx, srcFormat, dstFormat);
    446    } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
    447       return compressed_format_compatible(ctx, dstFormat, srcFormat);
    448    }
    449 
    450    return false;
    451 }
    452 
    453 void GLAPIENTRY
    454 _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
    455                        GLint srcX, GLint srcY, GLint srcZ,
    456                        GLuint dstName, GLenum dstTarget, GLint dstLevel,
    457                        GLint dstX, GLint dstY, GLint dstZ,
    458                        GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
    459 {
    460    GET_CURRENT_CONTEXT(ctx);
    461    struct gl_texture_image *srcTexImage, *dstTexImage;
    462    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
    463    mesa_format srcFormat, dstFormat;
    464    GLenum srcIntFormat, dstIntFormat;
    465    GLuint src_w, src_h, dst_w, dst_h;
    466    GLuint src_bw, src_bh, dst_bw, dst_bh;
    467    GLuint src_num_samples, dst_num_samples;
    468    int dstWidth, dstHeight, dstDepth;
    469    int i;
    470 
    471    if (MESA_VERBOSE & VERBOSE_API)
    472       _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
    473                                           "%u, %s, %d, %d, %d, %d, "
    474                                           "%d, %d, %d)\n",
    475                   srcName, _mesa_enum_to_string(srcTarget), srcLevel,
    476                   srcX, srcY, srcZ,
    477                   dstName, _mesa_enum_to_string(dstTarget), dstLevel,
    478                   dstX, dstY, dstZ,
    479                   srcWidth, srcHeight, srcDepth);
    480 
    481    if (!ctx->Extensions.ARB_copy_image) {
    482       _mesa_error(ctx, GL_INVALID_OPERATION,
    483                   "glCopyImageSubData(extension not available)");
    484       return;
    485    }
    486 
    487    if (!prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
    488                        &srcTexImage, &srcRenderbuffer, &srcFormat,
    489                        &srcIntFormat, &src_w, &src_h, &src_num_samples, "src"))
    490       return;
    491 
    492    if (!prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
    493                        &dstTexImage, &dstRenderbuffer, &dstFormat,
    494                        &dstIntFormat, &dst_w, &dst_h, &dst_num_samples, "dst"))
    495       return;
    496 
    497    _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
    498 
    499    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
    500     * spec says:
    501     *
    502     *    An INVALID_VALUE error is generated if the dimensions of either
    503     *    subregion exceeds the boundaries of the corresponding image object,
    504     *    or if the image format is compressed and the dimensions of the
    505     *    subregion fail to meet the alignment constraints of the format.
    506     *
    507     * and Section 8.7 (Compressed Texture Images) says:
    508     *
    509     *    An INVALID_OPERATION error is generated if any of the following
    510     *    conditions occurs:
    511     *
    512     *      * width is not a multiple of four, and width + xoffset is not
    513     *        equal to the value of TEXTURE_WIDTH.
    514     *      * height is not a multiple of four, and height + yoffset is not
    515     *        equal to the value of TEXTURE_HEIGHT.
    516     *
    517     * so we take that to mean that you can copy the "last" block of a
    518     * compressed texture image even if it's smaller than the minimum block
    519     * dimensions.
    520     */
    521    if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
    522        (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
    523        (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
    524       _mesa_error(ctx, GL_INVALID_VALUE,
    525                   "glCopyImageSubData(unaligned src rectangle)");
    526       return;
    527    }
    528 
    529    _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
    530    if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
    531       _mesa_error(ctx, GL_INVALID_VALUE,
    532                   "glCopyImageSubData(unaligned dst rectangle)");
    533       return;
    534    }
    535 
    536    /* From the GL_ARB_copy_image spec:
    537     *
    538     * "The dimensions are always specified in texels, even for compressed
    539     * texture formats. But it should be noted that if only one of the
    540     * source and destination textures is compressed then the number of
    541     * texels touched in the compressed image will be a factor of the
    542     * block size larger than in the uncompressed image."
    543     *
    544     * So, if copying from compressed to uncompressed, the dest region is
    545     * shrunk by the src block size factor.  If copying from uncompressed
    546     * to compressed, the dest region is grown by the dest block size factor.
    547     * Note that we're passed the _source_ width, height, depth and those
    548     * dimensions are never changed.
    549     */
    550    dstWidth = srcWidth * dst_bw / src_bw;
    551    dstHeight = srcHeight * dst_bh / src_bh;
    552    dstDepth = srcDepth;
    553 
    554    if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
    555                             srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
    556                             "src"))
    557       return;
    558 
    559    if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
    560                             dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
    561                             "dst"))
    562       return;
    563 
    564    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
    565     * spec says:
    566     *
    567     *    An INVALID_OPERATION error is generated if either object is a texture
    568     *    and the texture is not complete, if the source and destination internal
    569     *    formats are not compatible, or if the number of samples do not match.
    570     */
    571    if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
    572       _mesa_error(ctx, GL_INVALID_OPERATION,
    573                   "glCopyImageSubData(internalFormat mismatch)");
    574       return;
    575    }
    576 
    577    if (src_num_samples != dst_num_samples) {
    578       _mesa_error(ctx, GL_INVALID_OPERATION,
    579                   "glCopyImageSubData(number of samples mismatch)");
    580       return;
    581    }
    582 
    583    /* loop over 2D slices/faces/layers */
    584    for (i = 0; i < srcDepth; ++i) {
    585       int newSrcZ = srcZ + i;
    586       int newDstZ = dstZ + i;
    587 
    588       if (srcTexImage &&
    589           srcTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
    590          /* need to update srcTexImage pointer for the cube face */
    591          assert(srcZ + i < MAX_FACES);
    592          srcTexImage = srcTexImage->TexObject->Image[srcZ + i][srcLevel];
    593          assert(srcTexImage);
    594          newSrcZ = 0;
    595       }
    596 
    597       if (dstTexImage &&
    598           dstTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
    599          /* need to update dstTexImage pointer for the cube face */
    600          assert(dstZ + i < MAX_FACES);
    601          dstTexImage = dstTexImage->TexObject->Image[dstZ + i][dstLevel];
    602          assert(dstTexImage);
    603          newDstZ = 0;
    604       }
    605 
    606       ctx->Driver.CopyImageSubData(ctx,
    607                                    srcTexImage, srcRenderbuffer,
    608                                    srcX, srcY, newSrcZ,
    609                                    dstTexImage, dstRenderbuffer,
    610                                    dstX, dstY, newDstZ,
    611                                    srcWidth, srcHeight);
    612    }
    613 }
    614