• 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 "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
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)60 prepare_target_err(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       /* The ARB_copy_image specification says:
153        *
154        *    "INVALID_OPERATION is generated if either object is a texture and
155        *     the texture is not complete (as defined in section 3.9.14)"
156        *
157        * The cited section says:
158        *
159        *    "Using the preceding definitions, a texture is complete unless any
160        *     of the following conditions hold true: [...]
161        *
162        *     * The minification filter requires a mipmap (is neither NEAREST
163        *       nor LINEAR), and the texture is not mipmap complete."
164        *
165        * This imposes the bizarre restriction that glCopyImageSubData requires
166        * mipmap completion based on the sampler minification filter, even
167        * though the call fundamentally ignores the sampler.  Additionally, it
168        * doesn't work with texture units, so it can't consider any bound
169        * separate sampler objects.  It appears that you're supposed to use
170        * the sampler object which is built-in to the texture object.
171        *
172        * dEQP and the Android CTS mandate this behavior, and the Khronos
173        * GL and ES working groups both affirmed that this is unfortunate but
174        * correct.  See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16224.
175        *
176        * Integer textures with filtering cause another completeness snag:
177        *
178        *    "Any of:
179        *     – The internal format of the texture is integer (see table 8.12).
180        *     – The internal format is STENCIL_INDEX.
181        *     – The internal format is DEPTH_STENCIL, and the value of
182        *       DEPTH_STENCIL_TEXTURE_MODE for the texture is STENCIL_INDEX.
183        *     and either the magnification filter is not NEAREST, or the
184        *     minification filter is neither NEAREST nor
185        *     NEAREST_MIPMAP_NEAREST."
186        *
187        * However, applications in the wild (such as "Total War: WARHAMMER")
188        * appear to call glCopyImageSubData with integer textures and the
189        * default mipmap filters of GL_LINEAR and GL_NEAREST_MIPMAP_LINEAR,
190        * which would be considered incomplete, but expect this to work.  In
191        * fact, until VK-GL-CTS commit fef80039ff875a51806b54d151c5f2d0c12da,
192        * the GL 4.5 CTS contained three tests which did the exact same thing
193        * by accident, and all conformant implementations allowed it.
194        *
195        * A proposal was made to amend the spec to say "is not complete (as
196        * defined in section <X>, but ignoring format-based completeness
197        * rules)" to allow this case.  It makes some sense, given that
198        * glCopyImageSubData copies raw data without considering format.
199        * While the official edits have not yet been made, the OpenGL
200        * working group agreed with the idea of allowing this behavior.
201        *
202        * To ignore formats, we check texObj->_MipmapComplete directly
203        * rather than calling _mesa_is_texture_complete().
204        */
205       _mesa_test_texobj_completeness(ctx, texObj);
206       const bool texture_complete_aside_from_formats =
207          _mesa_is_mipmap_filter(&texObj->Sampler) ? texObj->_MipmapComplete
208                                                   : texObj->_BaseComplete;
209       if (!texture_complete_aside_from_formats) {
210          _mesa_error(ctx, GL_INVALID_OPERATION,
211                      "glCopyImageSubData(%sName incomplete)", dbg_prefix);
212          return false;
213       }
214 
215       /* Note that target will not be a cube face name */
216       if (texObj->Target != target) {
217          /*
218           * From GL_ARB_copy_image_specification:
219           * "INVALID_ENUM is generated if the target does not match the type
220           * of the object."
221           */
222          _mesa_error(ctx, GL_INVALID_ENUM,
223                      "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
224                      _mesa_enum_to_string(target));
225          return false;
226       }
227 
228       if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
229          _mesa_error(ctx, GL_INVALID_VALUE,
230                      "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
231          return false;
232       }
233 
234       if (target == GL_TEXTURE_CUBE_MAP) {
235          int i;
236 
237          assert(z < MAX_FACES);  /* should have been caught earlier */
238 
239          /* make sure all the cube faces are present */
240          for (i = 0; i < depth; i++) {
241             if (!texObj->Image[z+i][level]) {
242                /* missing cube face */
243                _mesa_error(ctx, GL_INVALID_VALUE,
244                            "glCopyImageSubData(missing cube face)");
245                return false;
246             }
247          }
248 
249          *tex_image = texObj->Image[z][level];
250       }
251       else {
252          *tex_image = _mesa_select_tex_image(texObj, target, level);
253       }
254 
255       if (!*tex_image) {
256          _mesa_error(ctx, GL_INVALID_VALUE,
257                      "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
258          return false;
259       }
260 
261       *renderbuffer = NULL;
262       *format = (*tex_image)->TexFormat;
263       *internalFormat = (*tex_image)->InternalFormat;
264       *width = (*tex_image)->Width;
265       *height = (*tex_image)->Height;
266       *num_samples = (*tex_image)->NumSamples;
267    }
268 
269    return true;
270 }
271 
272 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)273 prepare_target(struct gl_context *ctx, GLuint name, GLenum target,
274                int level, int z,
275                struct gl_texture_image **texImage,
276                struct gl_renderbuffer **renderbuffer)
277 {
278    if (target == GL_RENDERBUFFER) {
279       struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
280 
281       *renderbuffer = rb;
282       *texImage = NULL;
283    } else {
284       struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
285 
286       if (target == GL_TEXTURE_CUBE_MAP) {
287          *texImage = texObj->Image[z][level];
288       }
289       else {
290          *texImage = _mesa_select_tex_image(texObj, target, level);
291       }
292 
293       *renderbuffer = NULL;
294    }
295 }
296 
297 /**
298  * Check that the x,y,z,width,height,region is within the texture image
299  * dimensions.
300  * \return true if bounds OK, false if regions is out of bounds
301  */
302 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)303 check_region_bounds(struct gl_context *ctx,
304                     GLenum target,
305                     const struct gl_texture_image *tex_image,
306                     const struct gl_renderbuffer *renderbuffer,
307                     int x, int y, int z, int width, int height, int depth,
308                     const char *dbg_prefix)
309 {
310    int surfWidth, surfHeight, surfDepth;
311 
312    if (width < 0 || height < 0 || depth < 0) {
313       _mesa_error(ctx, GL_INVALID_VALUE,
314                   "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)",
315                   dbg_prefix, dbg_prefix, dbg_prefix);
316       return false;
317    }
318 
319    if (x < 0 || y < 0 || z < 0) {
320       _mesa_error(ctx, GL_INVALID_VALUE,
321                   "glCopyImageSubData(%sX, %sY, or %sZ is negative)",
322                   dbg_prefix, dbg_prefix, dbg_prefix);
323       return false;
324    }
325 
326    /* Check X direction */
327    if (target == GL_RENDERBUFFER) {
328       surfWidth = renderbuffer->Width;
329    }
330    else {
331       surfWidth = tex_image->Width;
332    }
333 
334    if (x + width > surfWidth) {
335       _mesa_error(ctx, GL_INVALID_VALUE,
336                   "glCopyImageSubData(%sX or %sWidth exceeds image bounds)",
337                   dbg_prefix, dbg_prefix);
338       return false;
339    }
340 
341    /* Check Y direction */
342    switch (target) {
343    case GL_RENDERBUFFER:
344       surfHeight = renderbuffer->Height;
345       break;
346    case GL_TEXTURE_1D:
347    case GL_TEXTURE_1D_ARRAY:
348       surfHeight = 1;
349       break;
350    default:
351       surfHeight = tex_image->Height;
352    }
353 
354    if (y + height > surfHeight) {
355       _mesa_error(ctx, GL_INVALID_VALUE,
356                   "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
357                   dbg_prefix, dbg_prefix);
358       return false;
359    }
360 
361    /* Check Z direction */
362    switch (target) {
363    case GL_RENDERBUFFER:
364    case GL_TEXTURE_1D:
365    case GL_TEXTURE_2D:
366    case GL_TEXTURE_2D_MULTISAMPLE:
367    case GL_TEXTURE_RECTANGLE:
368       surfDepth = 1;
369       break;
370    case GL_TEXTURE_CUBE_MAP:
371       surfDepth = 6;
372       break;
373    case GL_TEXTURE_1D_ARRAY:
374       surfDepth = tex_image->Height;
375       break;
376    default:
377       surfDepth = tex_image->Depth;
378    }
379 
380    if (z < 0 || z + depth > surfDepth) {
381       _mesa_error(ctx, GL_INVALID_VALUE,
382                   "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
383                   dbg_prefix, dbg_prefix);
384       return false;
385    }
386 
387    return true;
388 }
389 
390 static bool
compressed_format_compatible(const struct gl_context * ctx,GLenum compressedFormat,GLenum otherFormat)391 compressed_format_compatible(const struct gl_context *ctx,
392                              GLenum compressedFormat, GLenum otherFormat)
393 {
394    enum mesa_block_class compressedClass, otherClass;
395 
396    /* Two view-incompatible compressed formats are never compatible. */
397    if (_mesa_is_compressed_format(ctx, otherFormat)) {
398       return false;
399    }
400 
401    /*
402     * From ARB_copy_image spec:
403     *    Table 4.X.1 (Compatible internal formats for copying between
404     *                 compressed and uncompressed internal formats)
405     *    ---------------------------------------------------------------------
406     *    | Texel / | Uncompressed      |                                     |
407     *    | Block   | internal format   | Compressed internal format          |
408     *    | size    |                   |                                     |
409     *    ---------------------------------------------------------------------
410     *    | 128-bit | RGBA32UI,         | COMPRESSED_RGBA_S3TC_DXT3_EXT,      |
411     *    |         | RGBA32I,          | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
412     *    |         | RGBA32F           | COMPRESSED_RGBA_S3TC_DXT5_EXT,      |
413     *    |         |                   | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
414     *    |         |                   | COMPRESSED_RG_RGTC2,                |
415     *    |         |                   | COMPRESSED_SIGNED_RG_RGTC2,         |
416     *    |         |                   | COMPRESSED_RGBA_BPTC_UNORM,         |
417     *    |         |                   | COMPRESSED_SRGB_ALPHA_BPTC_UNORM,   |
418     *    |         |                   | COMPRESSED_RGB_BPTC_SIGNED_FLOAT,   |
419     *    |         |                   | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT  |
420     *    ---------------------------------------------------------------------
421     *    | 64-bit  | RGBA16F, RG32F,   | COMPRESSED_RGB_S3TC_DXT1_EXT,       |
422     *    |         | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT,      |
423     *    |         | RGBA16I, RG32I,   | COMPRESSED_RGBA_S3TC_DXT1_EXT,      |
424     *    |         | RGBA16,           | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
425     *    |         | RGBA16_SNORM      | COMPRESSED_RED_RGTC1,               |
426     *    |         |                   | COMPRESSED_SIGNED_RED_RGTC1         |
427     *    ---------------------------------------------------------------------
428     */
429 
430    switch (compressedFormat) {
431       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
432       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
433       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
434       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
435       case GL_COMPRESSED_RG_RGTC2:
436       case GL_COMPRESSED_SIGNED_RG_RGTC2:
437       case GL_COMPRESSED_RGBA_BPTC_UNORM:
438       case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
439       case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
440       case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
441          compressedClass = BLOCK_CLASS_128_BITS;
442          break;
443       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
444       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
445       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
446       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
447       case GL_COMPRESSED_RED_RGTC1:
448       case GL_COMPRESSED_SIGNED_RED_RGTC1:
449          compressedClass = BLOCK_CLASS_64_BITS;
450          break;
451       case GL_COMPRESSED_RGBA8_ETC2_EAC:
452       case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
453       case GL_COMPRESSED_RG11_EAC:
454       case GL_COMPRESSED_SIGNED_RG11_EAC:
455          if (_mesa_is_gles(ctx))
456             compressedClass = BLOCK_CLASS_128_BITS;
457          else
458             return false;
459          break;
460       case GL_COMPRESSED_RGB8_ETC2:
461       case GL_COMPRESSED_SRGB8_ETC2:
462       case GL_COMPRESSED_R11_EAC:
463       case GL_COMPRESSED_SIGNED_R11_EAC:
464       case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
465       case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
466          if (_mesa_is_gles(ctx))
467             compressedClass = BLOCK_CLASS_64_BITS;
468          else
469             return false;
470          break;
471       default:
472          if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat))
473             compressedClass = BLOCK_CLASS_128_BITS;
474          else
475             return false;
476          break;
477    }
478 
479    switch (otherFormat) {
480       case GL_RGBA32UI:
481       case GL_RGBA32I:
482       case GL_RGBA32F:
483          otherClass = BLOCK_CLASS_128_BITS;
484          break;
485       case GL_RGBA16F:
486       case GL_RG32F:
487       case GL_RGBA16UI:
488       case GL_RG32UI:
489       case GL_RGBA16I:
490       case GL_RG32I:
491       case GL_RGBA16:
492       case GL_RGBA16_SNORM:
493          otherClass = BLOCK_CLASS_64_BITS;
494          break;
495       default:
496          return false;
497    }
498 
499    return compressedClass == otherClass;
500 }
501 
502 static bool
copy_format_compatible(const struct gl_context * ctx,GLenum srcFormat,GLenum dstFormat)503 copy_format_compatible(const struct gl_context *ctx,
504                        GLenum srcFormat, GLenum dstFormat)
505 {
506    /*
507     * From ARB_copy_image spec:
508     *    For the purposes of CopyImageSubData, two internal formats
509     *    are considered compatible if any of the following conditions are
510     *    met:
511     *    * the formats are the same,
512     *    * the formats are considered compatible according to the
513     *      compatibility rules used for texture views as defined in
514     *      section 3.9.X. In particular, if both internal formats are listed
515     *      in the same entry of Table 3.X.2, they are considered compatible, or
516     *    * one format is compressed and the other is uncompressed and
517     *      Table 4.X.1 lists the two formats in the same row.
518     */
519 
520    if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
521       /* Also checks if formats are equal. */
522       return true;
523    } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
524       return compressed_format_compatible(ctx, srcFormat, dstFormat);
525    } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
526       return compressed_format_compatible(ctx, dstFormat, srcFormat);
527    }
528 
529    return false;
530 }
531 
532 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)533 copy_image_subdata(struct gl_context *ctx,
534                    struct gl_texture_image *srcTexImage,
535                    struct gl_renderbuffer *srcRenderbuffer,
536                    int srcX, int srcY, int srcZ, int srcLevel,
537                    struct gl_texture_image *dstTexImage,
538                    struct gl_renderbuffer *dstRenderbuffer,
539                    int dstX, int dstY, int dstZ, int dstLevel,
540                    int srcWidth, int srcHeight, int srcDepth)
541 {
542    /* loop over 2D slices/faces/layers */
543    for (int i = 0; i < srcDepth; ++i) {
544       int newSrcZ = srcZ + i;
545       int newDstZ = dstZ + i;
546 
547       if (srcTexImage &&
548           srcTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
549          /* need to update srcTexImage pointer for the cube face */
550          assert(srcZ + i < MAX_FACES);
551          srcTexImage = srcTexImage->TexObject->Image[srcZ + i][srcLevel];
552          assert(srcTexImage);
553          newSrcZ = 0;
554       }
555 
556       if (dstTexImage &&
557           dstTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
558          /* need to update dstTexImage pointer for the cube face */
559          assert(dstZ + i < MAX_FACES);
560          dstTexImage = dstTexImage->TexObject->Image[dstZ + i][dstLevel];
561          assert(dstTexImage);
562          newDstZ = 0;
563       }
564 
565       ctx->Driver.CopyImageSubData(ctx,
566                                    srcTexImage, srcRenderbuffer,
567                                    srcX, srcY, newSrcZ,
568                                    dstTexImage, dstRenderbuffer,
569                                    dstX, dstY, newDstZ,
570                                    srcWidth, srcHeight);
571    }
572 }
573 
574 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)575 _mesa_CopyImageSubData_no_error(GLuint srcName, GLenum srcTarget, GLint srcLevel,
576                                 GLint srcX, GLint srcY, GLint srcZ,
577                                 GLuint dstName, GLenum dstTarget, GLint dstLevel,
578                                 GLint dstX, GLint dstY, GLint dstZ,
579                                 GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
580 {
581    struct gl_texture_image *srcTexImage, *dstTexImage;
582    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
583 
584    GET_CURRENT_CONTEXT(ctx);
585 
586    prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, &srcTexImage,
587                   &srcRenderbuffer);
588 
589    prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, &dstTexImage,
590                   &dstRenderbuffer);
591 
592    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
593                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
594                       dstLevel, srcWidth, srcHeight, srcDepth);
595 }
596 
597 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)598 _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
599                        GLint srcX, GLint srcY, GLint srcZ,
600                        GLuint dstName, GLenum dstTarget, GLint dstLevel,
601                        GLint dstX, GLint dstY, GLint dstZ,
602                        GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
603 {
604    GET_CURRENT_CONTEXT(ctx);
605    struct gl_texture_image *srcTexImage, *dstTexImage;
606    struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
607    mesa_format srcFormat, dstFormat;
608    GLenum srcIntFormat, dstIntFormat;
609    GLuint src_w, src_h, dst_w, dst_h;
610    GLuint src_bw, src_bh, dst_bw, dst_bh;
611    GLuint src_num_samples, dst_num_samples;
612    int dstWidth, dstHeight, dstDepth;
613 
614    if (MESA_VERBOSE & VERBOSE_API)
615       _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
616                                           "%u, %s, %d, %d, %d, %d, "
617                                           "%d, %d, %d)\n",
618                   srcName, _mesa_enum_to_string(srcTarget), srcLevel,
619                   srcX, srcY, srcZ,
620                   dstName, _mesa_enum_to_string(dstTarget), dstLevel,
621                   dstX, dstY, dstZ,
622                   srcWidth, srcHeight, srcDepth);
623 
624    if (!ctx->Extensions.ARB_copy_image) {
625       _mesa_error(ctx, GL_INVALID_OPERATION,
626                   "glCopyImageSubData(extension not available)");
627       return;
628    }
629 
630    if (!prepare_target_err(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
631                            &srcTexImage, &srcRenderbuffer, &srcFormat,
632                            &srcIntFormat, &src_w, &src_h, &src_num_samples,
633                            "src"))
634       return;
635 
636    if (!prepare_target_err(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
637                            &dstTexImage, &dstRenderbuffer, &dstFormat,
638                            &dstIntFormat, &dst_w, &dst_h, &dst_num_samples,
639                            "dst"))
640       return;
641 
642    _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
643 
644    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
645     * spec says:
646     *
647     *    An INVALID_VALUE error is generated if the dimensions of either
648     *    subregion exceeds the boundaries of the corresponding image object,
649     *    or if the image format is compressed and the dimensions of the
650     *    subregion fail to meet the alignment constraints of the format.
651     *
652     * and Section 8.7 (Compressed Texture Images) says:
653     *
654     *    An INVALID_OPERATION error is generated if any of the following
655     *    conditions occurs:
656     *
657     *      * width is not a multiple of four, and width + xoffset is not
658     *        equal to the value of TEXTURE_WIDTH.
659     *      * height is not a multiple of four, and height + yoffset is not
660     *        equal to the value of TEXTURE_HEIGHT.
661     *
662     * so we take that to mean that you can copy the "last" block of a
663     * compressed texture image even if it's smaller than the minimum block
664     * dimensions.
665     */
666    if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
667        (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
668        (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
669       _mesa_error(ctx, GL_INVALID_VALUE,
670                   "glCopyImageSubData(unaligned src rectangle)");
671       return;
672    }
673 
674    _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
675    if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
676       _mesa_error(ctx, GL_INVALID_VALUE,
677                   "glCopyImageSubData(unaligned dst rectangle)");
678       return;
679    }
680 
681    /* From the GL_ARB_copy_image spec:
682     *
683     * "The dimensions are always specified in texels, even for compressed
684     * texture formats. But it should be noted that if only one of the
685     * source and destination textures is compressed then the number of
686     * texels touched in the compressed image will be a factor of the
687     * block size larger than in the uncompressed image."
688     *
689     * So, if copying from compressed to uncompressed, the dest region is
690     * shrunk by the src block size factor.  If copying from uncompressed
691     * to compressed, the dest region is grown by the dest block size factor.
692     * Note that we're passed the _source_ width, height, depth and those
693     * dimensions are never changed.
694     */
695    dstWidth = srcWidth * dst_bw / src_bw;
696    dstHeight = srcHeight * dst_bh / src_bh;
697    dstDepth = srcDepth;
698 
699    if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
700                             srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
701                             "src"))
702       return;
703 
704    if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
705                             dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
706                             "dst"))
707       return;
708 
709    /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
710     * spec says:
711     *
712     *    An INVALID_OPERATION error is generated if either object is a texture
713     *    and the texture is not complete, if the source and destination internal
714     *    formats are not compatible, or if the number of samples do not match.
715     */
716    if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
717       _mesa_error(ctx, GL_INVALID_OPERATION,
718                   "glCopyImageSubData(internalFormat mismatch)");
719       return;
720    }
721 
722    if (src_num_samples != dst_num_samples) {
723       _mesa_error(ctx, GL_INVALID_OPERATION,
724                   "glCopyImageSubData(number of samples mismatch)");
725       return;
726    }
727 
728    copy_image_subdata(ctx, srcTexImage, srcRenderbuffer, srcX, srcY, srcZ,
729                       srcLevel, dstTexImage, dstRenderbuffer, dstX, dstY, dstZ,
730                       dstLevel, srcWidth, srcHeight, srcDepth);
731 }
732