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