copyimage.c revision 7ec681f3
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
39enum 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 */
59static bool
60prepare_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
275static void
276prepare_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 */
305static bool
306check_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
395static bool
396compressed_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
507static bool
508copy_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
537static void
538copy_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
579void GLAPIENTRY
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
602void GLAPIENTRY
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
738void GLAPIENTRY
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
761void GLAPIENTRY
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