xref: /third_party/mesa3d/src/mesa/main/copyimage.c (revision bf215546)
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
41enum 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 */
61static bool
62prepare_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
277static void
278prepare_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 */
307static bool
308check_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
397static bool
398compressed_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
509static bool
510copy_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
539static void
540copy_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
581void GLAPIENTRY
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
604void GLAPIENTRY
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
740void GLAPIENTRY
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
763void GLAPIENTRY
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