877c8ac246de60b3a7b1c8be5334bceb0050847e
[mesa.git] / src / mesa / main / copyimage.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Jason Ekstrand <jason.ekstrand@intel.com>
26 */
27
28 #include "context.h"
29 #include "glheader.h"
30 #include "errors.h"
31 #include "enums.h"
32 #include "copyimage.h"
33 #include "teximage.h"
34 #include "texobj.h"
35 #include "fbobject.h"
36 #include "textureview.h"
37 #include "glformats.h"
38
39 enum mesa_block_class {
40 BLOCK_CLASS_128_BITS,
41 BLOCK_CLASS_64_BITS
42 };
43
44 /**
45 * Prepare the source or destination resource. This involves error
46 * checking and returning the relevant gl_texture_image or gl_renderbuffer.
47 * Note that one of the resulting tex_image or renderbuffer pointers will be
48 * NULL and the other will be non-null.
49 *
50 * \param name the texture or renderbuffer name
51 * \param target One of GL_TEXTURE_x target or GL_RENDERBUFFER
52 * \param level mipmap level
53 * \param z src or dest Z
54 * \param depth number of slices/faces/layers to copy
55 * \param tex_image returns a pointer to a texture image
56 * \param renderbuffer returns a pointer to a renderbuffer
57 * \return true if success, false if error
58 */
59 static bool
60 prepare_target(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 at times, which dEQP mandates, and other drivers
167 * appear to implement. We don't have any texture units here, so we
168 * can't look at any bound separate sampler objects...it appears that
169 * you're supposed to use the sampler object which is built-in to the
170 * texture object.
171 *
172 * See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16224.
173 */
174 _mesa_test_texobj_completeness(ctx, texObj);
175 if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
176 _mesa_error(ctx, GL_INVALID_OPERATION,
177 "glCopyImageSubData(%sName incomplete)", dbg_prefix);
178 return false;
179 }
180
181 /* Note that target will not be a cube face name */
182 if (texObj->Target != target) {
183 /*
184 * From GL_ARB_copy_image_specification:
185 * "INVALID_ENUM is generated if the target does not match the type
186 * of the object."
187 */
188 _mesa_error(ctx, GL_INVALID_ENUM,
189 "glCopyImageSubData(%sTarget = %s)", dbg_prefix,
190 _mesa_enum_to_string(target));
191 return false;
192 }
193
194 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
195 _mesa_error(ctx, GL_INVALID_VALUE,
196 "glCopyImageSubData(%sLevel = %d)", dbg_prefix, level);
197 return false;
198 }
199
200 if (target == GL_TEXTURE_CUBE_MAP) {
201 int i;
202
203 assert(z < MAX_FACES); /* should have been caught earlier */
204
205 /* make sure all the cube faces are present */
206 for (i = 0; i < depth; i++) {
207 if (!texObj->Image[z+i][level]) {
208 /* missing cube face */
209 _mesa_error(ctx, GL_INVALID_VALUE,
210 "glCopyImageSubData(missing cube face)");
211 return false;
212 }
213 }
214
215 *tex_image = texObj->Image[z][level];
216 }
217 else {
218 *tex_image = _mesa_select_tex_image(texObj, target, level);
219 }
220
221 if (!*tex_image) {
222 _mesa_error(ctx, GL_INVALID_VALUE,
223 "glCopyImageSubData(%sLevel = %u)", dbg_prefix, level);
224 return false;
225 }
226
227 *renderbuffer = NULL;
228 *format = (*tex_image)->TexFormat;
229 *internalFormat = (*tex_image)->InternalFormat;
230 *width = (*tex_image)->Width;
231 *height = (*tex_image)->Height;
232 *num_samples = (*tex_image)->NumSamples;
233 }
234
235 return true;
236 }
237
238
239 /**
240 * Check that the x,y,z,width,height,region is within the texture image
241 * dimensions.
242 * \return true if bounds OK, false if regions is out of bounds
243 */
244 static bool
245 check_region_bounds(struct gl_context *ctx,
246 GLenum target,
247 const struct gl_texture_image *tex_image,
248 const struct gl_renderbuffer *renderbuffer,
249 int x, int y, int z, int width, int height, int depth,
250 const char *dbg_prefix)
251 {
252 int surfWidth, surfHeight, surfDepth;
253
254 if (width < 0 || height < 0 || depth < 0) {
255 _mesa_error(ctx, GL_INVALID_VALUE,
256 "glCopyImageSubData(%sWidth, %sHeight, or %sDepth is negative)",
257 dbg_prefix, dbg_prefix, dbg_prefix);
258 return false;
259 }
260
261 if (x < 0 || y < 0 || z < 0) {
262 _mesa_error(ctx, GL_INVALID_VALUE,
263 "glCopyImageSubData(%sX, %sY, or %sZ is negative)",
264 dbg_prefix, dbg_prefix, dbg_prefix);
265 return false;
266 }
267
268 /* Check X direction */
269 if (target == GL_RENDERBUFFER) {
270 surfWidth = renderbuffer->Width;
271 }
272 else {
273 surfWidth = tex_image->Width;
274 }
275
276 if (x + width > surfWidth) {
277 _mesa_error(ctx, GL_INVALID_VALUE,
278 "glCopyImageSubData(%sX or %sWidth exceeds image bounds)",
279 dbg_prefix, dbg_prefix);
280 return false;
281 }
282
283 /* Check Y direction */
284 switch (target) {
285 case GL_RENDERBUFFER:
286 surfHeight = renderbuffer->Height;
287 break;
288 case GL_TEXTURE_1D:
289 case GL_TEXTURE_1D_ARRAY:
290 surfHeight = 1;
291 break;
292 default:
293 surfHeight = tex_image->Height;
294 }
295
296 if (y + height > surfHeight) {
297 _mesa_error(ctx, GL_INVALID_VALUE,
298 "glCopyImageSubData(%sY or %sHeight exceeds image bounds)",
299 dbg_prefix, dbg_prefix);
300 return false;
301 }
302
303 /* Check Z direction */
304 switch (target) {
305 case GL_RENDERBUFFER:
306 case GL_TEXTURE_1D:
307 case GL_TEXTURE_2D:
308 case GL_TEXTURE_2D_MULTISAMPLE:
309 case GL_TEXTURE_RECTANGLE:
310 surfDepth = 1;
311 break;
312 case GL_TEXTURE_CUBE_MAP:
313 surfDepth = 6;
314 break;
315 case GL_TEXTURE_1D_ARRAY:
316 surfDepth = tex_image->Height;
317 break;
318 default:
319 surfDepth = tex_image->Depth;
320 }
321
322 if (z < 0 || z + depth > surfDepth) {
323 _mesa_error(ctx, GL_INVALID_VALUE,
324 "glCopyImageSubData(%sZ or %sDepth exceeds image bounds)",
325 dbg_prefix, dbg_prefix);
326 return false;
327 }
328
329 return true;
330 }
331
332 static bool
333 compressed_format_compatible(const struct gl_context *ctx,
334 GLenum compressedFormat, GLenum otherFormat)
335 {
336 enum mesa_block_class compressedClass, otherClass;
337
338 /* Two view-incompatible compressed formats are never compatible. */
339 if (_mesa_is_compressed_format(ctx, otherFormat)) {
340 return false;
341 }
342
343 /*
344 * From ARB_copy_image spec:
345 * Table 4.X.1 (Compatible internal formats for copying between
346 * compressed and uncompressed internal formats)
347 * ---------------------------------------------------------------------
348 * | Texel / | Uncompressed | |
349 * | Block | internal format | Compressed internal format |
350 * | size | | |
351 * ---------------------------------------------------------------------
352 * | 128-bit | RGBA32UI, | COMPRESSED_RGBA_S3TC_DXT3_EXT, |
353 * | | RGBA32I, | COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,|
354 * | | RGBA32F | COMPRESSED_RGBA_S3TC_DXT5_EXT, |
355 * | | | COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,|
356 * | | | COMPRESSED_RG_RGTC2, |
357 * | | | COMPRESSED_SIGNED_RG_RGTC2, |
358 * | | | COMPRESSED_RGBA_BPTC_UNORM, |
359 * | | | COMPRESSED_SRGB_ALPHA_BPTC_UNORM, |
360 * | | | COMPRESSED_RGB_BPTC_SIGNED_FLOAT, |
361 * | | | COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT |
362 * ---------------------------------------------------------------------
363 * | 64-bit | RGBA16F, RG32F, | COMPRESSED_RGB_S3TC_DXT1_EXT, |
364 * | | RGBA16UI, RG32UI, | COMPRESSED_SRGB_S3TC_DXT1_EXT, |
365 * | | RGBA16I, RG32I, | COMPRESSED_RGBA_S3TC_DXT1_EXT, |
366 * | | RGBA16, | COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,|
367 * | | RGBA16_SNORM | COMPRESSED_RED_RGTC1, |
368 * | | | COMPRESSED_SIGNED_RED_RGTC1 |
369 * ---------------------------------------------------------------------
370 */
371
372 switch (compressedFormat) {
373 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
374 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
375 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
376 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
377 case GL_COMPRESSED_RG_RGTC2:
378 case GL_COMPRESSED_SIGNED_RG_RGTC2:
379 case GL_COMPRESSED_RGBA_BPTC_UNORM:
380 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
381 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
382 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
383 compressedClass = BLOCK_CLASS_128_BITS;
384 break;
385 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
386 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
387 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
388 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
389 case GL_COMPRESSED_RED_RGTC1:
390 case GL_COMPRESSED_SIGNED_RED_RGTC1:
391 compressedClass = BLOCK_CLASS_64_BITS;
392 break;
393 case GL_COMPRESSED_RGBA8_ETC2_EAC:
394 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
395 case GL_COMPRESSED_RG11_EAC:
396 case GL_COMPRESSED_SIGNED_RG11_EAC:
397 if (_mesa_is_gles(ctx))
398 compressedClass = BLOCK_CLASS_128_BITS;
399 else
400 return false;
401 break;
402 case GL_COMPRESSED_RGB8_ETC2:
403 case GL_COMPRESSED_SRGB8_ETC2:
404 case GL_COMPRESSED_R11_EAC:
405 case GL_COMPRESSED_SIGNED_R11_EAC:
406 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
407 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
408 if (_mesa_is_gles(ctx))
409 compressedClass = BLOCK_CLASS_64_BITS;
410 else
411 return false;
412 break;
413 default:
414 if (_mesa_is_gles(ctx) && _mesa_is_astc_format(compressedFormat))
415 compressedClass = BLOCK_CLASS_128_BITS;
416 else
417 return false;
418 break;
419 }
420
421 switch (otherFormat) {
422 case GL_RGBA32UI:
423 case GL_RGBA32I:
424 case GL_RGBA32F:
425 otherClass = BLOCK_CLASS_128_BITS;
426 break;
427 case GL_RGBA16F:
428 case GL_RG32F:
429 case GL_RGBA16UI:
430 case GL_RG32UI:
431 case GL_RGBA16I:
432 case GL_RG32I:
433 case GL_RGBA16:
434 case GL_RGBA16_SNORM:
435 otherClass = BLOCK_CLASS_64_BITS;
436 break;
437 default:
438 return false;
439 }
440
441 return compressedClass == otherClass;
442 }
443
444 static bool
445 copy_format_compatible(const struct gl_context *ctx,
446 GLenum srcFormat, GLenum dstFormat)
447 {
448 /*
449 * From ARB_copy_image spec:
450 * For the purposes of CopyImageSubData, two internal formats
451 * are considered compatible if any of the following conditions are
452 * met:
453 * * the formats are the same,
454 * * the formats are considered compatible according to the
455 * compatibility rules used for texture views as defined in
456 * section 3.9.X. In particular, if both internal formats are listed
457 * in the same entry of Table 3.X.2, they are considered compatible, or
458 * * one format is compressed and the other is uncompressed and
459 * Table 4.X.1 lists the two formats in the same row.
460 */
461
462 if (_mesa_texture_view_compatible_format(ctx, srcFormat, dstFormat)) {
463 /* Also checks if formats are equal. */
464 return true;
465 } else if (_mesa_is_compressed_format(ctx, srcFormat)) {
466 return compressed_format_compatible(ctx, srcFormat, dstFormat);
467 } else if (_mesa_is_compressed_format(ctx, dstFormat)) {
468 return compressed_format_compatible(ctx, dstFormat, srcFormat);
469 }
470
471 return false;
472 }
473
474 void GLAPIENTRY
475 _mesa_CopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel,
476 GLint srcX, GLint srcY, GLint srcZ,
477 GLuint dstName, GLenum dstTarget, GLint dstLevel,
478 GLint dstX, GLint dstY, GLint dstZ,
479 GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
480 {
481 GET_CURRENT_CONTEXT(ctx);
482 struct gl_texture_image *srcTexImage, *dstTexImage;
483 struct gl_renderbuffer *srcRenderbuffer, *dstRenderbuffer;
484 mesa_format srcFormat, dstFormat;
485 GLenum srcIntFormat, dstIntFormat;
486 GLuint src_w, src_h, dst_w, dst_h;
487 GLuint src_bw, src_bh, dst_bw, dst_bh;
488 GLuint src_num_samples, dst_num_samples;
489 int dstWidth, dstHeight, dstDepth;
490 int i;
491
492 if (MESA_VERBOSE & VERBOSE_API)
493 _mesa_debug(ctx, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
494 "%u, %s, %d, %d, %d, %d, "
495 "%d, %d, %d)\n",
496 srcName, _mesa_enum_to_string(srcTarget), srcLevel,
497 srcX, srcY, srcZ,
498 dstName, _mesa_enum_to_string(dstTarget), dstLevel,
499 dstX, dstY, dstZ,
500 srcWidth, srcHeight, srcDepth);
501
502 if (!ctx->Extensions.ARB_copy_image) {
503 _mesa_error(ctx, GL_INVALID_OPERATION,
504 "glCopyImageSubData(extension not available)");
505 return;
506 }
507
508 if (!prepare_target(ctx, srcName, srcTarget, srcLevel, srcZ, srcDepth,
509 &srcTexImage, &srcRenderbuffer, &srcFormat,
510 &srcIntFormat, &src_w, &src_h, &src_num_samples, "src"))
511 return;
512
513 if (!prepare_target(ctx, dstName, dstTarget, dstLevel, dstZ, srcDepth,
514 &dstTexImage, &dstRenderbuffer, &dstFormat,
515 &dstIntFormat, &dst_w, &dst_h, &dst_num_samples, "dst"))
516 return;
517
518 _mesa_get_format_block_size(srcFormat, &src_bw, &src_bh);
519
520 /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
521 * spec says:
522 *
523 * An INVALID_VALUE error is generated if the dimensions of either
524 * subregion exceeds the boundaries of the corresponding image object,
525 * or if the image format is compressed and the dimensions of the
526 * subregion fail to meet the alignment constraints of the format.
527 *
528 * and Section 8.7 (Compressed Texture Images) says:
529 *
530 * An INVALID_OPERATION error is generated if any of the following
531 * conditions occurs:
532 *
533 * * width is not a multiple of four, and width + xoffset is not
534 * equal to the value of TEXTURE_WIDTH.
535 * * height is not a multiple of four, and height + yoffset is not
536 * equal to the value of TEXTURE_HEIGHT.
537 *
538 * so we take that to mean that you can copy the "last" block of a
539 * compressed texture image even if it's smaller than the minimum block
540 * dimensions.
541 */
542 if ((srcX % src_bw != 0) || (srcY % src_bh != 0) ||
543 (srcWidth % src_bw != 0 && (srcX + srcWidth) != src_w) ||
544 (srcHeight % src_bh != 0 && (srcY + srcHeight) != src_h)) {
545 _mesa_error(ctx, GL_INVALID_VALUE,
546 "glCopyImageSubData(unaligned src rectangle)");
547 return;
548 }
549
550 _mesa_get_format_block_size(dstFormat, &dst_bw, &dst_bh);
551 if ((dstX % dst_bw != 0) || (dstY % dst_bh != 0)) {
552 _mesa_error(ctx, GL_INVALID_VALUE,
553 "glCopyImageSubData(unaligned dst rectangle)");
554 return;
555 }
556
557 /* From the GL_ARB_copy_image spec:
558 *
559 * "The dimensions are always specified in texels, even for compressed
560 * texture formats. But it should be noted that if only one of the
561 * source and destination textures is compressed then the number of
562 * texels touched in the compressed image will be a factor of the
563 * block size larger than in the uncompressed image."
564 *
565 * So, if copying from compressed to uncompressed, the dest region is
566 * shrunk by the src block size factor. If copying from uncompressed
567 * to compressed, the dest region is grown by the dest block size factor.
568 * Note that we're passed the _source_ width, height, depth and those
569 * dimensions are never changed.
570 */
571 dstWidth = srcWidth * dst_bw / src_bw;
572 dstHeight = srcHeight * dst_bh / src_bh;
573 dstDepth = srcDepth;
574
575 if (!check_region_bounds(ctx, srcTarget, srcTexImage, srcRenderbuffer,
576 srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
577 "src"))
578 return;
579
580 if (!check_region_bounds(ctx, dstTarget, dstTexImage, dstRenderbuffer,
581 dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
582 "dst"))
583 return;
584
585 /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
586 * spec says:
587 *
588 * An INVALID_OPERATION error is generated if either object is a texture
589 * and the texture is not complete, if the source and destination internal
590 * formats are not compatible, or if the number of samples do not match.
591 */
592 if (!copy_format_compatible(ctx, srcIntFormat, dstIntFormat)) {
593 _mesa_error(ctx, GL_INVALID_OPERATION,
594 "glCopyImageSubData(internalFormat mismatch)");
595 return;
596 }
597
598 if (src_num_samples != dst_num_samples) {
599 _mesa_error(ctx, GL_INVALID_OPERATION,
600 "glCopyImageSubData(number of samples mismatch)");
601 return;
602 }
603
604 /* loop over 2D slices/faces/layers */
605 for (i = 0; i < srcDepth; ++i) {
606 int newSrcZ = srcZ + i;
607 int newDstZ = dstZ + i;
608
609 if (srcTexImage &&
610 srcTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
611 /* need to update srcTexImage pointer for the cube face */
612 assert(srcZ + i < MAX_FACES);
613 srcTexImage = srcTexImage->TexObject->Image[srcZ + i][srcLevel];
614 assert(srcTexImage);
615 newSrcZ = 0;
616 }
617
618 if (dstTexImage &&
619 dstTexImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) {
620 /* need to update dstTexImage pointer for the cube face */
621 assert(dstZ + i < MAX_FACES);
622 dstTexImage = dstTexImage->TexObject->Image[dstZ + i][dstLevel];
623 assert(dstTexImage);
624 newDstZ = 0;
625 }
626
627 ctx->Driver.CopyImageSubData(ctx,
628 srcTexImage, srcRenderbuffer,
629 srcX, srcY, newSrcZ,
630 dstTexImage, dstRenderbuffer,
631 dstX, dstY, newDstZ,
632 srcWidth, srcHeight);
633 }
634 }