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