• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@intel.com>
26  */
27 
28 #include "context.h"
29 #include "glheader.h"
30 #include "errors.h"
31 #include "enums.h"
32 #include "teximage.h"
33 #include "texobj.h"
34 #include "fbobject.h"
35 #include "textureview.h"
36 #include "glformats.h"
37 #include "api_exec_decl.h"
38 
39 #include "state_tracker/st_cb_copyimage.h"
40 
41 enum mesa_block_class {
42    BLOCK_CLASS_128_BITS,
43    BLOCK_CLASS_64_BITS
44 };
45 
46 /**
47  * Prepare the source or destination resource.  This involves error
48  * checking and returning the relevant gl_texture_image or gl_renderbuffer.
49  * Note that one of the resulting tex_image or renderbuffer pointers will be
50  * NULL and the other will be non-null.
51  *
52  * \param name  the texture or renderbuffer name
53  * \param target  One of GL_TEXTURE_x target or GL_RENDERBUFFER
54  * \param level  mipmap level
55  * \param z  src or dest Z
56  * \param depth  number of slices/faces/layers to copy
57  * \param tex_image  returns a pointer to a texture image
58  * \param renderbuffer  returns a pointer to a renderbuffer
59  * \return true if success, false if error
60  */
61 static bool
prepare_target_err(struct gl_context * ctx,GLuint name,GLenum target,int level,int z,int depth,struct gl_texture_image ** tex_image,struct gl_renderbuffer ** renderbuffer,mesa_format * format,GLenum * internalFormat,GLuint * width,GLuint * height,GLuint * num_samples,const char * dbg_prefix,bool is_arb_version)62 prepare_target_err(struct gl_context *ctx, GLuint name, GLenum target,
63                    int level, int z, int depth,
64                    struct gl_texture_image **tex_image,
65                    struct gl_renderbuffer **renderbuffer,
66                    mesa_format *format,
67                    GLenum *internalFormat,
68                    GLuint *width,
69                    GLuint *height,
70                    GLuint *num_samples,
71                    const char *dbg_prefix,
72                    bool is_arb_version)
73 {
74    const char *suffix = is_arb_version ? "" : "NV";
75 
76    if (name == 0) {
77       _mesa_error(ctx, GL_INVALID_VALUE,
78                   "glCopyImageSubData%s(%sName = %d)", suffix, dbg_prefix, name);
79       return false;
80    }
81 
82    /*
83     * INVALID_ENUM is generated
84     *  * if either <srcTarget> or <dstTarget>
85     *   - is not RENDERBUFFER or a valid non-proxy texture target
86     *   - is TEXTURE_BUFFER, or
87     *   - is one of the cubemap face selectors described in table 3.17,
88     */
89    switch (target) {
90    case GL_RENDERBUFFER:
91       /* Not a texture target, but valid */
92    case GL_TEXTURE_1D:
93    case GL_TEXTURE_1D_ARRAY:
94    case GL_TEXTURE_2D:
95    case GL_TEXTURE_3D:
96    case GL_TEXTURE_CUBE_MAP:
97    case GL_TEXTURE_RECTANGLE:
98    case GL_TEXTURE_2D_ARRAY:
99    case GL_TEXTURE_CUBE_MAP_ARRAY:
100    case GL_TEXTURE_2D_MULTISAMPLE:
101    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
102       /* These are all valid */
103       break;
104    case GL_TEXTURE_EXTERNAL_OES:
105       /* Only exists in ES */
106    case GL_TEXTURE_BUFFER:
107    default:
108       _mesa_error(ctx, GL_INVALID_ENUM,
109                   "glCopyImageSubData%s(%sTarget = %s)", suffix, dbg_prefix,
110                   _mesa_enum_to_string(target));
111       return false;
112    }
113 
114    if (target == GL_RENDERBUFFER) {
115       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
116 
117       if (!rb) {
118          _mesa_error(ctx, GL_INVALID_VALUE,
119                      "glCopyImageSubData%s(%sName = %u)", suffix, dbg_prefix, name);
120          return false;
121       }
122 
123       if (!rb->Name) {
124          _mesa_error(ctx, GL_INVALID_OPERATION,
125                      "glCopyImageSubData%s(%sName incomplete)", suffix, dbg_prefix);
126          return false;
127       }
128 
129       if (level != 0) {
130          _mesa_error(ctx, GL_INVALID_VALUE,
131                      "glCopyImageSubData%s(%sLevel = %u)", suffix, dbg_prefix, level);
132          return false;
133       }
134 
135       *renderbuffer = rb;
136       *format = rb->Format;
137       *internalFormat = rb->InternalFormat;
138       *width = rb->Width;
139       *height = rb->Height;
140       *num_samples = rb->NumSamples;
141       *tex_image = NULL;
142    } else {
143       struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
144 
145       if (!texObj) {
146          /*
147           * From GL_ARB_copy_image specification:
148           * "INVALID_VALUE is generated if either <srcName> or <dstName> does
149           * not correspond to a valid renderbuffer or texture object according
150           * to the corresponding target parameter."
151           */
152          _mesa_error(ctx, GL_INVALID_VALUE,
153                      "glCopyImageSubData%s(%sName = %u)", suffix, dbg_prefix, name);
154          return false;
155       }
156 
157       /* The ARB_copy_image specification says:
158        *
159        *    "INVALID_OPERATION is generated if either object is a texture and
160        *     the texture is not complete (as defined in section 3.9.14)"
161        *
162        * The cited section says:
163        *
164        *    "Using the preceding definitions, a texture is complete unless any
165        *     of the following conditions hold true: [...]
166        *
167        *     * The minification filter requires a mipmap (is neither NEAREST
168        *       nor LINEAR), and the texture is not mipmap complete."
169        *
170        * This imposes the bizarre restriction that glCopyImageSubData requires
171        * mipmap completion based on the sampler minification filter, even
172        * though the call fundamentally ignores the sampler.  Additionally, it
173        * doesn't work with texture units, so it can't consider any bound
174        * separate sampler objects.  It appears that you're supposed to use
175        * the sampler object which is built-in to the texture object.
176        *
177        * dEQP and the Android CTS mandate this behavior, and the Khronos
178        * GL and ES working groups both affirmed that this is unfortunate but
179        * correct.  See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16224.
180        *
181        * Integer textures with filtering cause another completeness snag:
182        *
183        *    "Any of:
184        *     – The internal format of the texture is integer (see table 8.12).
185        *     – The internal format is STENCIL_INDEX.
186        *     – The internal format is DEPTH_STENCIL, and the value of
187        *       DEPTH_STENCIL_TEXTURE_MODE for the texture is STENCIL_INDEX.
188        *     and either the magnification filter is not NEAREST, or the
189        *     minification filter is neither NEAREST nor
190        *     NEAREST_MIPMAP_NEAREST."
191        *
192        * However, applications in the wild (such as "Total War: WARHAMMER")
193        * appear to call glCopyImageSubData with integer textures and the
194        * default mipmap filters of GL_LINEAR and GL_NEAREST_MIPMAP_LINEAR,
195        * which would be considered incomplete, but expect this to work.  In
196        * fact, until VK-GL-CTS commit fef80039ff875a51806b54d151c5f2d0c12da,
197        * the GL 4.5 CTS contained three tests which did the exact same thing
198        * by accident, and all conformant implementations allowed it.
199        *
200        * A proposal was made to amend the spec to say "is not complete (as
201        * defined in section <X>, but ignoring format-based completeness
202        * rules)" to allow this case.  It makes some sense, given that
203        * glCopyImageSubData copies raw data without considering format.
204        * While the official edits have not yet been made, the OpenGL
205        * working group agreed with the idea of allowing this behavior.
206        *
207        * To ignore formats, we check texObj->_MipmapComplete directly
208        * rather than calling _mesa_is_texture_complete().
209        */
210       _mesa_test_texobj_completeness(ctx, texObj);
211       const bool texture_complete_aside_from_formats =
212          _mesa_is_mipmap_filter(&texObj->Sampler) ? texObj->_MipmapComplete
213                                                   : texObj->_BaseComplete;
214       if (!texture_complete_aside_from_formats) {
215          _mesa_error(ctx, GL_INVALID_OPERATION,
216                      "glCopyImageSubData%s(%sName incomplete)", suffix, dbg_prefix);
217          return false;
218       }
219 
220       /* Note that target will not be a cube face name */
221       if (texObj->Target != target) {
222          /*
223           * From GL_ARB_copy_image_specification:
224           * "INVALID_ENUM is generated if the target does not match the type
225           * of the object."
226           */
227          _mesa_error(ctx, GL_INVALID_ENUM,
228                      "glCopyImageSubData%s(%sTarget = %s)", suffix, dbg_prefix,
229                      _mesa_enum_to_string(target));
230          return false;
231       }
232 
233       if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
234          _mesa_error(ctx, GL_INVALID_VALUE,
235                      "glCopyImageSubData%s(%sLevel = %d)", suffix, dbg_prefix, level);
236          return false;
237       }
238 
239       if (target == GL_TEXTURE_CUBE_MAP) {
240          int i;
241 
242          assert(z < MAX_FACES);  /* should have been caught earlier */
243 
244          /* make sure all the cube faces are present */
245          for (i = 0; i < depth; i++) {
246             if (!texObj->Image[z+i][level]) {
247                /* missing cube face */
248                _mesa_error(ctx, GL_INVALID_VALUE,
249                            "glCopyImageSubData(missing cube face)");
250                return false;
251             }
252          }
253 
254          *tex_image = texObj->Image[z][level];
255       }
256       else {
257          *tex_image = _mesa_select_tex_image(texObj, target, level);
258       }
259 
260       if (!*tex_image) {
261          _mesa_error(ctx, GL_INVALID_VALUE,
262                      "glCopyImageSubData%s(%sLevel = %u)", suffix, dbg_prefix, level);
263          return false;
264       }
265 
266       *renderbuffer = NULL;
267       *format = (*tex_image)->TexFormat;
268       *internalFormat = (*tex_image)->InternalFormat;
269       *width = (*tex_image)->Width;
270       *height = (*tex_image)->Height;
271       *num_samples = (*tex_image)->NumSamples;
272    }
273 
274    return true;
275 }
276 
277 static void
prepare_target(struct gl_context * ctx,GLuint name,GLenum target,int level,int z,struct gl_texture_image ** texImage,struct gl_renderbuffer ** renderbuffer)278 prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
279                int level, int z,
280                struct gl_texture_image **texImage,
281                struct gl_renderbuffer **renderbuffer)
282 {
283    if (target == GL_RENDERBUFFER) {
284       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
285 
286       *renderbuffer = rb;
287       *texImage = NULL;
288    } else {
289       struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
290 
291       if (target == GL_TEXTURE_CUBE_MAP) {
292          *texImage = texObj->Image[z][level];
293       }
294       else {
295          *texImage = _mesa_select_tex_image(texObj, target, level);
296       }
297 
298       *renderbuffer = NULL;
299    }
300 }
301 
302 /**
303  * Check that the x,y,z,width,height,region is within the texture image
304  * dimensions.
305  * \return true if bounds OK, false if regions is out of bounds
306  */
307 static bool
check_region_bounds(struct gl_context * ctx,GLenum target,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,bool is_arb_version)308 check_region_bounds(struct gl_context *ctx,
309                     GLenum target,
310                     const struct gl_texture_image *tex_image,
311                     const struct gl_renderbuffer *renderbuffer,
312                     int x, int y, int z, int width, int height, int depth,
313                     const char *dbg_prefix,
314                     bool is_arb_version)
315 {
316    int surfWidth, surfHeight, surfDepth;
317    const char *suffix = is_arb_version ? "" : "NV";
318 
319    if (width < 0 || height < 0 || depth < 0) {
320       _mesa_error(ctx, GL_INVALID_VALUE,
321                   "glCopyImageSubData%s(%sWidth, %sHeight, or %sDepth is negative)",
322                   suffix, dbg_prefix, dbg_prefix, dbg_prefix);
323       return false;
324    }
325 
326    if (x < 0 || y < 0 || z < 0) {
327       _mesa_error(ctx, GL_INVALID_VALUE,
328                   "glCopyImageSubData%s(%sX, %sY, or %sZ is negative)",
329                   suffix, dbg_prefix, dbg_prefix, dbg_prefix);
330       return false;
331    }
332 
333    /* Check X direction */
334    if (target == GL_RENDERBUFFER) {
335       surfWidth = renderbuffer->Width;
336    }
337    else {
338       surfWidth = tex_image->Width;
339    }
340 
341    if (x + width > surfWidth) {
342       _mesa_error(ctx, GL_INVALID_VALUE,
343                   "glCopyImageSubData%s(%sX or %sWidth exceeds image bounds)",
344                   suffix, dbg_prefix, dbg_prefix);
345       return false;
346    }
347 
348    /* Check Y direction */
349    switch (target) {
350    case GL_RENDERBUFFER:
351       surfHeight = renderbuffer->Height;
352       break;
353    case GL_TEXTURE_1D:
354    case GL_TEXTURE_1D_ARRAY:
355       surfHeight = 1;
356       break;
357    default:
358       surfHeight = tex_image->Height;
359    }
360 
361    if (y + height > surfHeight) {
362       _mesa_error(ctx, GL_INVALID_VALUE,
363                   "glCopyImageSubData%s(%sY or %sHeight exceeds image bounds)",
364                   suffix, dbg_prefix, dbg_prefix);
365       return false;
366    }
367 
368    /* Check Z direction */
369    switch (target) {
370    case GL_RENDERBUFFER:
371    case GL_TEXTURE_1D:
372    case GL_TEXTURE_2D:
373    case GL_TEXTURE_2D_MULTISAMPLE:
374    case GL_TEXTURE_RECTANGLE:
375       surfDepth = 1;
376       break;
377    case GL_TEXTURE_CUBE_MAP:
378       surfDepth = 6;
379       break;
380    case GL_TEXTURE_1D_ARRAY:
381       surfDepth = tex_image->Height;
382       break;
383    default:
384       surfDepth = tex_image->Depth;
385    }
386 
387    if (z < 0 || z + depth > surfDepth) {
388       _mesa_error(ctx, GL_INVALID_VALUE,
389                   "glCopyImageSubData%s(%sZ or %sDepth exceeds image bounds)",
390                   suffix, dbg_prefix, dbg_prefix);
391       return false;
392    }
393 
394    return true;
395 }
396 
397 static bool
compressed_format_compatible(const struct gl_context * ctx,GLenum compressedFormat,GLenum otherFormat)398 compressed_format_compatible(const struct gl_context *ctx,
399                              GLenum compressedFormat, GLenum otherFormat)
400 {
401    enum mesa_block_class compressedClass, otherClass;
402 
403    /* Two view-incompatible compressed formats are never compatible. */
404    if (_mesa_is_compressed_format(ctx, otherFormat)) {
405       return false;
406    }
407 
408    /*
409     * From ARB_copy_image spec:
410     *    Table 4.X.1 (Compatible internal formats for copying between
411     *                 compressed and uncompressed internal formats)
412     *    ---------------------------------------------------------------------
413     *    | Texel / | Uncompressed      |                                     |
414     *    | Block   | internal format   | Compressed internal format          |
415     *    | size    |                   |                                     |
416     *    ---------------------------------------------------------------------
417     *    | 128-bit | RGBA32UI,         | COMPRESSED_RGBA_S3TC_DXT3_EXT,      |
418     *    |         | RGBA32I,          | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
419     *    |         | RGBA32F           | COMPRESSED_RGBA_S3TC_DXT5_EXT,      |
420     *    |         |                   | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
421     *    |         |                   | COMPRESSED_RG_RGTC2,                |
422     *    |         |                   | COMPRESSED_SIGNED_RG_RGTC2,         |
423     *    |         |                   | COMPRESSED_RGBA_BPTC_UNORM,         |
424     *    |         |                   | COMPRESSED_SRGB_ALPHA_BPTC_UNORM,   |
425     *    |         |                   | COMPRESSED_RGB_BPTC_SIGNED_FLOAT,   |
426     *    |         |                   | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT  |
427     *    ---------------------------------------------------------------------
428     *    | 64-bit  | RGBA16F, RG32F,   | COMPRESSED_RGB_S3TC_DXT1_EXT,       |
429     *    |         | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT,      |
430     *    |         | RGBA16I, RG32I,   | COMPRESSED_RGBA_S3TC_DXT1_EXT,      |
431     *    |         | RGBA16,           | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
432     *    |         | RGBA16_SNORM      | COMPRESSED_RED_RGTC1,               |
433     *    |         |                   | COMPRESSED_SIGNED_RED_RGTC1         |
434     *    ---------------------------------------------------------------------
435     */
436 
437    switch (compressedFormat) {
438       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
439       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
440       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
441       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
442       case GL_COMPRESSED_RG_RGTC2:
443       case GL_COMPRESSED_SIGNED_RG_RGTC2:
444       case GL_COMPRESSED_RGBA_BPTC_UNORM:
445       case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
446       case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
447       case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
448          compressedClass = BLOCK_CLASS_128_BITS;
449          break;
450       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
451       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
452       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
453       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
454       case GL_COMPRESSED_RED_RGTC1:
455       case GL_COMPRESSED_SIGNED_RED_RGTC1:
456          compressedClass = BLOCK_CLASS_64_BITS;
457          break;
458       case GL_COMPRESSED_RGBA8_ETC2_EAC:
459       case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
460       case GL_COMPRESSED_RG11_EAC:
461       case GL_COMPRESSED_SIGNED_RG11_EAC:
462          if (_mesa_is_gles(ctx))
463             compressedClass = BLOCK_CLASS_128_BITS;
464          else
465             return false;
466          break;
467       case GL_COMPRESSED_RGB8_ETC2:
468       case GL_COMPRESSED_SRGB8_ETC2:
469       case GL_COMPRESSED_R11_EAC:
470       case GL_COMPRESSED_SIGNED_R11_EAC:
471       case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
472       case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
473          if (_mesa_is_gles(ctx))
474             compressedClass = BLOCK_CLASS_64_BITS;
475          else
476             return false;
477          break;
478       default:
479          if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat))
480             compressedClass = BLOCK_CLASS_128_BITS;
481          else
482             return false;
483          break;
484    }
485 
486    switch (otherFormat) {
487       case GL_RGBA32UI:
488       case GL_RGBA32I:
489       case GL_RGBA32F:
490          otherClass = BLOCK_CLASS_128_BITS;
491          break;
492       case GL_RGBA16F:
493       case GL_RG32F:
494       case GL_RGBA16UI:
495       case GL_RG32UI:
496       case GL_RGBA16I:
497       case GL_RG32I:
498       case GL_RGBA16:
499       case GL_RGBA16_SNORM:
500          otherClass = BLOCK_CLASS_64_BITS;
501          break;
502       default:
503          return false;
504    }
505 
506    return compressedClass == otherClass;
507 }
508 
509 static bool
copy_format_compatible(const struct gl_context * ctx,GLenum srcFormat,GLenum dstFormat)510 copy_format_compatible(const struct gl_context *ctx,
511                        GLenum srcFormat, GLenum dstFormat)
512 {
513    /*
514     * From ARB_copy_image spec:
515     *    For the purposes of CopyImageSubData, two internal formats
516     *    are considered compatible if any of the following conditions are
517     *    met:
518     *    * the formats are the same,
519     *    * the formats are considered compatible according to the
520     *      compatibility rules used for texture views as defined in
521     *      section 3.9.X. In particular, if both internal formats are listed
522     *      in the same entry of Table 3.X.2, they are considered compatible, or
523     *    * one format is compressed and the other is uncompressed and
524     *      Table 4.X.1 lists the two formats in the same row.
525     */
526 
527    if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
528       /* Also checks if formats are equal. */
529       return true;
530    } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
531       return compressed_format_compatible(ctx, srcFormat, dstFormat);
532    } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
533       return compressed_format_compatible(ctx, dstFormat, srcFormat);
534    }
535 
536    return false;
537 }
538 
539 static void
copy_image_subdata(struct gl_context * ctx,struct gl_texture_image * srcTexImage,struct gl_renderbuffer * srcRenderbuffer,int srcX,int srcY,int srcZ,int srcLevel,struct gl_texture_image * dstTexImage,struct gl_renderbuffer * dstRenderbuffer,int dstX,int dstY,int dstZ,int dstLevel,int srcWidth,int srcHeight,int srcDepth)540 copy_image_subdata(struct gl_context *ctx,
541                    struct gl_texture_image *srcTexImage,
542                    struct gl_renderbuffer *srcRenderbuffer,
543                    int srcX, int srcY, int srcZ, int srcLevel,
544                    struct gl_texture_image *dstTexImage,
545                    struct gl_renderbuffer *dstRenderbuffer,
546                    int dstX, int dstY, int dstZ, int dstLevel,
547                    int srcWidth, int srcHeight, int srcDepth)
548 {
549    /* loop over 2D slices/faces/layers */
550    for (int i = 0; i < srcDepth; ++i) {
551       int newSrcZ = srcZ + i;
552       int newDstZ = dstZ + i;
553 
554       if (srcTexImage &&
555           srcTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
556          /* need to update srcTexImage pointer for the cube face */
557          assert(srcZ + i < MAX_FACES);
558          srcTexImage = srcTexImage->TexObject->Image[srcZ + i][srcLevel];
559          assert(srcTexImage);
560          newSrcZ = 0;
561       }
562 
563       if (dstTexImage &&
564           dstTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
565          /* need to update dstTexImage pointer for the cube face */
566          assert(dstZ + i < MAX_FACES);
567          dstTexImage = dstTexImage->TexObject->Image[dstZ + i][dstLevel];
568          assert(dstTexImage);
569          newDstZ = 0;
570       }
571 
572       st_CopyImageSubData(ctx,
573                           srcTexImage, srcRenderbuffer,
574                           srcX, srcY, newSrcZ,
575                           dstTexImage, dstRenderbuffer,
576                           dstX, dstY, newDstZ,
577                           srcWidth, srcHeight);
578    }
579 }
580 
581 void GLAPIENTRY
_mesa_CopyImageSubData_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)582 _mesa_CopyImageSubData_no_error(GLuint srcName, GLenum srcTarget, GLint srcLevel,
583                                 GLint srcX, GLint srcY, GLint srcZ,
584                                 GLuint dstName, GLenum dstTarget, GLint dstLevel,
585                                 GLint dstX, GLint dstY, GLint dstZ,
586                                 GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
587 {
588    struct gl_texture_image *srcTexImage, *dstTexImage;
589    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
590 
591    GET_CURRENT_CONTEXT(ctx);
592 
593    prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, &srcTexImage,
594                   &srcRenderbuffer);
595 
596    prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, &dstTexImage,
597                   &dstRenderbuffer);
598 
599    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
600                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
601                       dstLevel, srcWidth, srcHeight, srcDepth);
602 }
603 
604 void GLAPIENTRY
_mesa_CopyImageSubData(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)605 _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
606                        GLint srcX, GLint srcY, GLint srcZ,
607                        GLuint dstName, GLenum dstTarget, GLint dstLevel,
608                        GLint dstX, GLint dstY, GLint dstZ,
609                        GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
610 {
611    GET_CURRENT_CONTEXT(ctx);
612    struct gl_texture_image *srcTexImage, *dstTexImage;
613    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
614    mesa_format srcFormat, dstFormat;
615    GLenum srcIntFormat, dstIntFormat;
616    GLuint src_w, src_h, dst_w, dst_h;
617    GLuint src_bw, src_bh, dst_bw, dst_bh;
618    GLuint src_num_samples, dst_num_samples;
619    int dstWidth, dstHeight, dstDepth;
620 
621    if (MESA_VERBOSE & VERBOSE_API)
622       _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
623                                           "%u, %s, %d, %d, %d, %d, "
624                                           "%d, %d, %d)\n",
625                   srcName, _mesa_enum_to_string(srcTarget), srcLevel,
626                   srcX, srcY, srcZ,
627                   dstName, _mesa_enum_to_string(dstTarget), dstLevel,
628                   dstX, dstY, dstZ,
629                   srcWidth, srcHeight, srcDepth);
630 
631    if (!ctx->Extensions.ARB_copy_image) {
632       _mesa_error(ctx, GL_INVALID_OPERATION,
633                   "glCopyImageSubData(extension not available)");
634       return;
635    }
636 
637    if (!prepare_target_err(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
638                            &srcTexImage, &srcRenderbuffer, &srcFormat,
639                            &srcIntFormat, &src_w, &src_h, &src_num_samples,
640                            "src",true))
641       return;
642 
643    if (!prepare_target_err(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
644                            &dstTexImage, &dstRenderbuffer, &dstFormat,
645                            &dstIntFormat, &dst_w, &dst_h, &dst_num_samples,
646                            "dst",true))
647       return;
648 
649    _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
650 
651    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
652     * spec says:
653     *
654     *    An INVALID_VALUE error is generated if the dimensions of either
655     *    subregion exceeds the boundaries of the corresponding image object,
656     *    or if the image format is compressed and the dimensions of the
657     *    subregion fail to meet the alignment constraints of the format.
658     *
659     * and Section 8.7 (Compressed Texture Images) says:
660     *
661     *    An INVALID_OPERATION error is generated if any of the following
662     *    conditions occurs:
663     *
664     *      * width is not a multiple of four, and width + xoffset is not
665     *        equal to the value of TEXTURE_WIDTH.
666     *      * height is not a multiple of four, and height + yoffset is not
667     *        equal to the value of TEXTURE_HEIGHT.
668     *
669     * so we take that to mean that you can copy the "last" block of a
670     * compressed texture image even if it's smaller than the minimum block
671     * dimensions.
672     */
673    if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
674        (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
675        (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
676       _mesa_error(ctx, GL_INVALID_VALUE,
677                   "glCopyImageSubData(unaligned src rectangle)");
678       return;
679    }
680 
681    _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
682    if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
683       _mesa_error(ctx, GL_INVALID_VALUE,
684                   "glCopyImageSubData(unaligned dst rectangle)");
685       return;
686    }
687 
688    /* From the GL_ARB_copy_image spec:
689     *
690     * "The dimensions are always specified in texels, even for compressed
691     * texture formats. But it should be noted that if only one of the
692     * source and destination textures is compressed then the number of
693     * texels touched in the compressed image will be a factor of the
694     * block size larger than in the uncompressed image."
695     *
696     * So, if copying from compressed to uncompressed, the dest region is
697     * shrunk by the src block size factor.  If copying from uncompressed
698     * to compressed, the dest region is grown by the dest block size factor.
699     * Note that we're passed the _source_ width, height, depth and those
700     * dimensions are never changed.
701     */
702    dstWidth = srcWidth * dst_bw / src_bw;
703    dstHeight = srcHeight * dst_bh / src_bh;
704    dstDepth = srcDepth;
705 
706    if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
707                             srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
708                             "src", true))
709       return;
710 
711    if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
712                             dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
713                             "dst", true))
714       return;
715 
716    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
717     * spec says:
718     *
719     *    An INVALID_OPERATION error is generated if either object is a texture
720     *    and the texture is not complete, if the source and destination internal
721     *    formats are not compatible, or if the number of samples do not match.
722     */
723    if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
724       _mesa_error(ctx, GL_INVALID_OPERATION,
725                   "glCopyImageSubData(internalFormat mismatch)");
726       return;
727    }
728 
729    if (src_num_samples != dst_num_samples) {
730       _mesa_error(ctx, GL_INVALID_OPERATION,
731                   "glCopyImageSubData(number of samples mismatch)");
732       return;
733    }
734 
735    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
736                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
737                       dstLevel, srcWidth, srcHeight, srcDepth);
738 }
739 
740 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)741 _mesa_CopyImageSubDataNV_no_error(GLuint srcName, GLenum srcTarget, GLint srcLevel,
742                                   GLint srcX, GLint srcY, GLint srcZ,
743                                   GLuint dstName, GLenum dstTarget, GLint dstLevel,
744                                   GLint dstX, GLint dstY, GLint dstZ,
745                                   GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
746 {
747    struct gl_texture_image *srcTexImage, *dstTexImage;
748    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
749 
750    GET_CURRENT_CONTEXT(ctx);
751 
752    prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, &srcTexImage,
753                   &srcRenderbuffer);
754 
755    prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, &dstTexImage,
756                   &dstRenderbuffer);
757 
758    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
759                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
760                       dstLevel, srcWidth, srcHeight, srcDepth);
761 }
762 
763 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)764 _mesa_CopyImageSubDataNV(GLuint srcName, GLenum srcTarget, GLint srcLevel,
765                          GLint srcX, GLint srcY, GLint srcZ,
766                          GLuint dstName, GLenum dstTarget, GLint dstLevel,
767                          GLint dstX, GLint dstY, GLint dstZ,
768                          GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
769 {
770    GET_CURRENT_CONTEXT(ctx);
771    struct gl_texture_image *srcTexImage, *dstTexImage;
772    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
773    mesa_format srcFormat, dstFormat;
774    GLenum srcIntFormat, dstIntFormat;
775    GLuint src_w, src_h, dst_w, dst_h;
776    GLuint src_bw, src_bh, dst_bw, dst_bh;
777    GLuint src_num_samples, dst_num_samples;
778 
779    if (MESA_VERBOSE & VERBOSE_API)
780       _mesa_debug(ctx, "glCopyImageSubDataNV(%u, %s, %d, %d, %d, %d, "
781                                             "%u, %s, %d, %d, %d, %d, "
782                                             "%d, %d, %d)\n",
783                   srcName, _mesa_enum_to_string(srcTarget), srcLevel,
784                   srcX, srcY, srcZ,
785                   dstName, _mesa_enum_to_string(dstTarget), dstLevel,
786                   dstX, dstY, dstZ,
787                   srcWidth, srcHeight, srcDepth);
788 
789    if (!ctx->Extensions.NV_copy_image) {
790       _mesa_error(ctx, GL_INVALID_OPERATION,
791                   "glCopyImageSubDataNV(extension not available)");
792       return;
793    }
794 
795    if (!prepare_target_err(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
796                            &srcTexImage, &srcRenderbuffer, &srcFormat,
797                            &srcIntFormat, &src_w, &src_h, &src_num_samples,
798                            "src", false))
799       return;
800 
801    if (!prepare_target_err(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
802                            &dstTexImage, &dstRenderbuffer, &dstFormat,
803                            &dstIntFormat, &dst_w, &dst_h, &dst_num_samples,
804                            "dst", false))
805       return;
806 
807    /*
808     * The NV_copy_image spec says:
809     *
810     *    INVALID_OPERATION is generated if either object is a texture
811     *    and the texture is not consistent, or if the source and destination
812     *    internal formats or number of samples do not match.
813     *
814     * In the absence of any definition of texture consistency the texture
815     * completeness check, which is affected in the prepare_target_err function,
816     * is used instead in keeping with the ARB version.
817     * The check related to the internal format here is different from the ARB
818     * version which adds the ability to copy between images which have
819     * different formats where the formats are compatible for texture views.
820     */
821    if (srcIntFormat != dstIntFormat) {
822       _mesa_error(ctx, GL_INVALID_OPERATION,
823                   "glCopyImageSubDataNV(internalFormat mismatch)");
824       return;
825    }
826 
827    if (src_num_samples != dst_num_samples) {
828       _mesa_error(ctx, GL_INVALID_OPERATION,
829                   "glCopyImageSubDataNV(number of samples mismatch)");
830       return;
831    }
832 
833    /*
834     * The NV_copy_image spec says:
835     *
836     *    INVALID_VALUE is generated if the image format is compressed
837     *    and the dimensions of the subregion fail to meet the alignment
838     *    constraints of the format.
839     *
840     * The check here is identical to the ARB version.
841     */
842    _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
843    if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
844        (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
845        (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
846       _mesa_error(ctx, GL_INVALID_VALUE,
847                   "glCopyImageSubDataNV(unaligned src rectangle)");
848       return;
849    }
850 
851    _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
852    if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
853       _mesa_error(ctx, GL_INVALID_VALUE,
854                   "glCopyImageSubDataNV(unaligned dst rectangle)");
855       return;
856    }
857 
858    /*
859     * The NV_copy_image spec says:
860     *
861     *    INVALID_VALUE is generated if the dimensions of the either subregion
862     *    exceeds the boundaries of the corresponding image object.
863     *
864     * The check here is similar to the ARB version except for the fact that
865     * block sizes are not considered owing to the fact that copying across
866     * compressed and uncompressed formats is not supported.
867     */
868    if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
869                             srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
870                             "src", false))
871       return;
872 
873    if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
874                             dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth,
875                             "dst", false))
876       return;
877 
878    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
879                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
880                       dstLevel, srcWidth, srcHeight, srcDepth);
881 }
882