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