2 * Mesa 3-D graphics library
4 * Copyright (C) 2014 Intel Corporation. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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.
25 * Jason Ekstrand <jason.ekstrand@intel.com>
32 #include "copyimage.h"
36 #include "textureview.h"
37 #include "glformats.h"
39 enum mesa_block_class
{
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.
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
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
,
65 GLenum
*internalFormat
,
69 const char *dbg_prefix
,
72 const char *suffix
= is_arb_version
? "" : "NV";
75 _mesa_error(ctx
, GL_INVALID_VALUE
,
76 "glCopyImageSubData%s(%sName = %d)", suffix
, dbg_prefix
, name
);
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,
89 /* Not a texture target, but valid */
91 case GL_TEXTURE_1D_ARRAY
:
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 */
102 case GL_TEXTURE_EXTERNAL_OES
:
103 /* Only exists in ES */
104 case GL_TEXTURE_BUFFER
:
106 _mesa_error(ctx
, GL_INVALID_ENUM
,
107 "glCopyImageSubData%s(%sTarget = %s)", suffix
, dbg_prefix
,
108 _mesa_enum_to_string(target
));
112 if (target
== GL_RENDERBUFFER
) {
113 struct gl_renderbuffer
*rb
= _mesa_lookup_renderbuffer(ctx
, name
);
116 _mesa_error(ctx
, GL_INVALID_VALUE
,
117 "glCopyImageSubData%s(%sName = %u)", suffix
, dbg_prefix
, name
);
122 _mesa_error(ctx
, GL_INVALID_OPERATION
,
123 "glCopyImageSubData%s(%sName incomplete)", suffix
, dbg_prefix
);
128 _mesa_error(ctx
, GL_INVALID_VALUE
,
129 "glCopyImageSubData%s(%sLevel = %u)", suffix
, dbg_prefix
, level
);
134 *format
= rb
->Format
;
135 *internalFormat
= rb
->InternalFormat
;
137 *height
= rb
->Height
;
138 *num_samples
= rb
->NumSamples
;
141 struct gl_texture_object
*texObj
= _mesa_lookup_texture(ctx
, name
);
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."
150 _mesa_error(ctx
, GL_INVALID_VALUE
,
151 "glCopyImageSubData%s(%sName = %u)", suffix
, dbg_prefix
, name
);
155 /* The ARB_copy_image specification says:
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)"
160 * The cited section says:
162 * "Using the preceding definitions, a texture is complete unless any
163 * of the following conditions hold true: [...]
165 * * The minification filter requires a mipmap (is neither NEAREST
166 * nor LINEAR), and the texture is not mipmap complete."
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.
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.
179 * Integer textures with filtering cause another completeness snag:
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."
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.
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.
205 * To ignore formats, we check texObj->_MipmapComplete directly
206 * rather than calling _mesa_is_texture_complete().
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
);
218 /* Note that target will not be a cube face name */
219 if (texObj
->Target
!= target
) {
221 * From GL_ARB_copy_image_specification:
222 * "INVALID_ENUM is generated if the target does not match the type
225 _mesa_error(ctx
, GL_INVALID_ENUM
,
226 "glCopyImageSubData%s(%sTarget = %s)", suffix
, dbg_prefix
,
227 _mesa_enum_to_string(target
));
231 if (level
< 0 || level
>= MAX_TEXTURE_LEVELS
) {
232 _mesa_error(ctx
, GL_INVALID_VALUE
,
233 "glCopyImageSubData%s(%sLevel = %d)", suffix
, dbg_prefix
, level
);
237 if (target
== GL_TEXTURE_CUBE_MAP
) {
240 assert(z
< MAX_FACES
); /* should have been caught earlier */
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)");
252 *tex_image
= texObj
->Image
[z
][level
];
255 *tex_image
= _mesa_select_tex_image(texObj
, target
, level
);
259 _mesa_error(ctx
, GL_INVALID_VALUE
,
260 "glCopyImageSubData%s(%sLevel = %u)", suffix
, dbg_prefix
, level
);
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
;
276 prepare_target(struct gl_context
*ctx
, GLuint name
, GLenum target
,
278 struct gl_texture_image
**texImage
,
279 struct gl_renderbuffer
**renderbuffer
)
281 if (target
== GL_RENDERBUFFER
) {
282 struct gl_renderbuffer
*rb
= _mesa_lookup_renderbuffer(ctx
, name
);
287 struct gl_texture_object
*texObj
= _mesa_lookup_texture(ctx
, name
);
289 if (target
== GL_TEXTURE_CUBE_MAP
) {
290 *texImage
= texObj
->Image
[z
][level
];
293 *texImage
= _mesa_select_tex_image(texObj
, target
, level
);
296 *renderbuffer
= NULL
;
301 * Check that the x,y,z,width,height,region is within the texture image
303 * \return true if bounds OK, false if regions is out of bounds
306 check_region_bounds(struct gl_context
*ctx
,
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
,
314 int surfWidth
, surfHeight
, surfDepth
;
315 const char *suffix
= is_arb_version
? "" : "NV";
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
);
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
);
331 /* Check X direction */
332 if (target
== GL_RENDERBUFFER
) {
333 surfWidth
= renderbuffer
->Width
;
336 surfWidth
= tex_image
->Width
;
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
);
346 /* Check Y direction */
348 case GL_RENDERBUFFER
:
349 surfHeight
= renderbuffer
->Height
;
352 case GL_TEXTURE_1D_ARRAY
:
356 surfHeight
= tex_image
->Height
;
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
);
366 /* Check Z direction */
368 case GL_RENDERBUFFER
:
371 case GL_TEXTURE_2D_MULTISAMPLE
:
372 case GL_TEXTURE_RECTANGLE
:
375 case GL_TEXTURE_CUBE_MAP
:
378 case GL_TEXTURE_1D_ARRAY
:
379 surfDepth
= tex_image
->Height
;
382 surfDepth
= tex_image
->Depth
;
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
);
396 compressed_format_compatible(const struct gl_context
*ctx
,
397 GLenum compressedFormat
, GLenum otherFormat
)
399 enum mesa_block_class compressedClass
, otherClass
;
401 /* Two view-incompatible compressed formats are never compatible. */
402 if (_mesa_is_compressed_format(ctx
, otherFormat
)) {
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 |
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 * ---------------------------------------------------------------------
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
;
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
;
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
;
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
;
477 if (_mesa_is_gles(ctx
) && _mesa_is_astc_format(compressedFormat
))
478 compressedClass
= BLOCK_CLASS_128_BITS
;
484 switch (otherFormat
) {
488 otherClass
= BLOCK_CLASS_128_BITS
;
497 case GL_RGBA16_SNORM
:
498 otherClass
= BLOCK_CLASS_64_BITS
;
504 return compressedClass
== otherClass
;
508 copy_format_compatible(const struct gl_context
*ctx
,
509 GLenum srcFormat
, GLenum dstFormat
)
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
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.
525 if (_mesa_texture_view_compatible_format(ctx
, srcFormat
, dstFormat
)) {
526 /* Also checks if formats are equal. */
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
);
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
)
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
;
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
];
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
];
570 ctx
->Driver
.CopyImageSubData(ctx
,
571 srcTexImage
, srcRenderbuffer
,
573 dstTexImage
, dstRenderbuffer
,
575 srcWidth
, srcHeight
);
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
)
586 struct gl_texture_image
*srcTexImage
, *dstTexImage
;
587 struct gl_renderbuffer
*srcRenderbuffer
, *dstRenderbuffer
;
589 GET_CURRENT_CONTEXT(ctx
);
591 prepare_target(ctx
, srcName
, srcTarget
, srcLevel
, srcZ
, &srcTexImage
,
594 prepare_target(ctx
, dstName
, dstTarget
, dstLevel
, dstZ
, &dstTexImage
,
597 copy_image_subdata(ctx
, srcTexImage
, srcRenderbuffer
, srcX
, srcY
, srcZ
,
598 srcLevel
, dstTexImage
, dstRenderbuffer
, dstX
, dstY
, dstZ
,
599 dstLevel
, srcWidth
, srcHeight
, srcDepth
);
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
)
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
;
619 if (MESA_VERBOSE
& VERBOSE_API
)
620 _mesa_debug(ctx
, "glCopyImageSubData(%u, %s, %d, %d, %d, %d, "
621 "%u, %s, %d, %d, %d, %d, "
623 srcName
, _mesa_enum_to_string(srcTarget
), srcLevel
,
625 dstName
, _mesa_enum_to_string(dstTarget
), dstLevel
,
627 srcWidth
, srcHeight
, srcDepth
);
629 if (!ctx
->Extensions
.ARB_copy_image
) {
630 _mesa_error(ctx
, GL_INVALID_OPERATION
,
631 "glCopyImageSubData(extension not available)");
635 if (!prepare_target_err(ctx
, srcName
, srcTarget
, srcLevel
, srcZ
, srcDepth
,
636 &srcTexImage
, &srcRenderbuffer
, &srcFormat
,
637 &srcIntFormat
, &src_w
, &src_h
, &src_num_samples
,
641 if (!prepare_target_err(ctx
, dstName
, dstTarget
, dstLevel
, dstZ
, srcDepth
,
642 &dstTexImage
, &dstRenderbuffer
, &dstFormat
,
643 &dstIntFormat
, &dst_w
, &dst_h
, &dst_num_samples
,
647 _mesa_get_format_block_size(srcFormat
, &src_bw
, &src_bh
);
649 /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
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.
657 * and Section 8.7 (Compressed Texture Images) says:
659 * An INVALID_OPERATION error is generated if any of the following
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.
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
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)");
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)");
686 /* From the GL_ARB_copy_image spec:
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."
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.
700 dstWidth
= srcWidth
* dst_bw
/ src_bw
;
701 dstHeight
= srcHeight
* dst_bh
/ src_bh
;
704 if (!check_region_bounds(ctx
, srcTarget
, srcTexImage
, srcRenderbuffer
,
705 srcX
, srcY
, srcZ
, srcWidth
, srcHeight
, srcDepth
,
709 if (!check_region_bounds(ctx
, dstTarget
, dstTexImage
, dstRenderbuffer
,
710 dstX
, dstY
, dstZ
, dstWidth
, dstHeight
, dstDepth
,
714 /* Section 18.3.2 (Copying Between Images) of the OpenGL 4.5 Core Profile
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.
721 if (!copy_format_compatible(ctx
, srcIntFormat
, dstIntFormat
)) {
722 _mesa_error(ctx
, GL_INVALID_OPERATION
,
723 "glCopyImageSubData(internalFormat mismatch)");
727 if (src_num_samples
!= dst_num_samples
) {
728 _mesa_error(ctx
, GL_INVALID_OPERATION
,
729 "glCopyImageSubData(number of samples mismatch)");
733 copy_image_subdata(ctx
, srcTexImage
, srcRenderbuffer
, srcX
, srcY
, srcZ
,
734 srcLevel
, dstTexImage
, dstRenderbuffer
, dstX
, dstY
, dstZ
,
735 dstLevel
, srcWidth
, srcHeight
, srcDepth
);
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
)
745 struct gl_texture_image
*srcTexImage
, *dstTexImage
;
746 struct gl_renderbuffer
*srcRenderbuffer
, *dstRenderbuffer
;
748 GET_CURRENT_CONTEXT(ctx
);
750 prepare_target(ctx
, srcName
, srcTarget
, srcLevel
, srcZ
, &srcTexImage
,
753 prepare_target(ctx
, dstName
, dstTarget
, dstLevel
, dstZ
, &dstTexImage
,
756 copy_image_subdata(ctx
, srcTexImage
, srcRenderbuffer
, srcX
, srcY
, srcZ
,
757 srcLevel
, dstTexImage
, dstRenderbuffer
, dstX
, dstY
, dstZ
,
758 dstLevel
, srcWidth
, srcHeight
, srcDepth
);
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
)
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
;
777 if (MESA_VERBOSE
& VERBOSE_API
)
778 _mesa_debug(ctx
, "glCopyImageSubDataNV(%u, %s, %d, %d, %d, %d, "
779 "%u, %s, %d, %d, %d, %d, "
781 srcName
, _mesa_enum_to_string(srcTarget
), srcLevel
,
783 dstName
, _mesa_enum_to_string(dstTarget
), dstLevel
,
785 srcWidth
, srcHeight
, srcDepth
);
787 if (!ctx
->Extensions
.NV_copy_image
) {
788 _mesa_error(ctx
, GL_INVALID_OPERATION
,
789 "glCopyImageSubDataNV(extension not available)");
793 if (!prepare_target_err(ctx
, srcName
, srcTarget
, srcLevel
, srcZ
, srcDepth
,
794 &srcTexImage
, &srcRenderbuffer
, &srcFormat
,
795 &srcIntFormat
, &src_w
, &src_h
, &src_num_samples
,
799 if (!prepare_target_err(ctx
, dstName
, dstTarget
, dstLevel
, dstZ
, srcDepth
,
800 &dstTexImage
, &dstRenderbuffer
, &dstFormat
,
801 &dstIntFormat
, &dst_w
, &dst_h
, &dst_num_samples
,
806 * The NV_copy_image spec says:
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.
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.
819 if (srcIntFormat
!= dstIntFormat
) {
820 _mesa_error(ctx
, GL_INVALID_OPERATION
,
821 "glCopyImageSubDataNV(internalFormat mismatch)");
825 if (src_num_samples
!= dst_num_samples
) {
826 _mesa_error(ctx
, GL_INVALID_OPERATION
,
827 "glCopyImageSubDataNV(number of samples mismatch)");
832 * The NV_copy_image spec says:
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.
838 * The check here is identical to the ARB version.
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)");
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)");
857 * The NV_copy_image spec says:
859 * INVALID_VALUE is generated if the dimensions of the either subregion
860 * exceeds the boundaries of the corresponding image object.
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.
866 if (!check_region_bounds(ctx
, srcTarget
, srcTexImage
, srcRenderbuffer
,
867 srcX
, srcY
, srcZ
, srcWidth
, srcHeight
, srcDepth
,
871 if (!check_region_bounds(ctx
, dstTarget
, dstTexImage
, dstRenderbuffer
,
872 dstX
, dstY
, dstZ
, srcWidth
, srcHeight
, srcDepth
,
876 copy_image_subdata(ctx
, srcTexImage
, srcRenderbuffer
, srcX
, srcY
, srcZ
,
877 srcLevel
, dstTexImage
, dstRenderbuffer
, dstX
, dstY
, dstZ
,
878 dstLevel
, srcWidth
, srcHeight
, srcDepth
);