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