2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "state_tracker/st_context.h"
26 #include "state_tracker/st_cb_bitmap.h"
27 #include "state_tracker/st_cb_copyimage.h"
28 #include "state_tracker/st_cb_fbo.h"
29 #include "state_tracker/st_texture.h"
31 #include "util/u_box.h"
32 #include "util/u_format.h"
33 #include "util/u_inlines.h"
37 * Return an equivalent canonical format without "X" channels.
39 * Copying between incompatible formats is easier when the format is
40 * canonicalized, meaning that it is in a standard form.
42 * The returned format has the same component sizes and swizzles as
43 * the source format, the type is changed to UINT or UNORM, depending on
44 * which one has the most swizzle combinations in their group.
46 * If it's not an array format, return a memcpy-equivalent array format.
48 * The key feature is that swizzled versions of formats of the same
49 * component size always return the same component type.
52 * Luminance, intensity, alpha, depth, stencil, and 8-bit and 16-bit packed
53 * formats are not supported. (same as ARB_copy_image)
55 static enum pipe_format
56 get_canonical_format(enum pipe_format format
)
58 const struct util_format_description
*desc
=
59 util_format_description(format
);
61 /* Packed formats. Return the equivalent array format. */
62 if (format
== PIPE_FORMAT_R11G11B10_FLOAT
||
63 format
== PIPE_FORMAT_R9G9B9E5_FLOAT
)
64 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
66 if (desc
->nr_channels
== 4 &&
67 desc
->channel
[0].size
== 10 &&
68 desc
->channel
[1].size
== 10 &&
69 desc
->channel
[2].size
== 10 &&
70 desc
->channel
[3].size
== 2) {
71 if (desc
->swizzle
[0] == PIPE_SWIZZLE_X
&&
72 desc
->swizzle
[1] == PIPE_SWIZZLE_Y
&&
73 desc
->swizzle
[2] == PIPE_SWIZZLE_Z
)
74 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
76 return PIPE_FORMAT_NONE
;
79 #define RETURN_FOR_SWIZZLE1(x, format) \
80 if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \
83 #define RETURN_FOR_SWIZZLE2(x, y, format) \
84 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
85 desc->swizzle[1] == PIPE_SWIZZLE_##y) \
88 #define RETURN_FOR_SWIZZLE3(x, y, z, format) \
89 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
90 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
91 desc->swizzle[2] == PIPE_SWIZZLE_##z) \
94 #define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \
95 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
96 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
97 desc->swizzle[2] == PIPE_SWIZZLE_##z && \
98 desc->swizzle[3] == PIPE_SWIZZLE_##w) \
102 if (desc
->is_array
) {
103 switch (desc
->nr_channels
) {
105 switch (desc
->channel
[0].size
) {
107 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R8_UINT
);
111 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R16_UINT
);
115 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R32_UINT
);
121 switch (desc
->channel
[0].size
) {
123 /* All formats in each group must be of the same type.
124 * We can't use UINT for R8G8 while using UNORM for G8R8.
126 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R8G8_UNORM
);
127 RETURN_FOR_SWIZZLE2(Y
, X
, PIPE_FORMAT_G8R8_UNORM
);
131 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R16G16_UNORM
);
132 RETURN_FOR_SWIZZLE2(Y
, X
, PIPE_FORMAT_G16R16_UNORM
);
136 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R32G32_UINT
);
142 switch (desc
->channel
[0].size
) {
144 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R8G8B8_UINT
);
148 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R16G16B16_UINT
);
152 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R32G32B32_UINT
);
158 switch (desc
->channel
[0].size
) {
160 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R8G8B8A8_UNORM
);
161 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R8G8B8A8_UNORM
);
162 RETURN_FOR_SWIZZLE4(Z
, Y
, X
, W
, PIPE_FORMAT_B8G8R8A8_UNORM
);
163 RETURN_FOR_SWIZZLE4(Z
, Y
, X
, 1, PIPE_FORMAT_B8G8R8A8_UNORM
);
164 RETURN_FOR_SWIZZLE4(W
, Z
, Y
, X
, PIPE_FORMAT_A8B8G8R8_UNORM
);
165 RETURN_FOR_SWIZZLE4(W
, Z
, Y
, 1, PIPE_FORMAT_A8B8G8R8_UNORM
);
166 RETURN_FOR_SWIZZLE4(Y
, Z
, W
, X
, PIPE_FORMAT_A8R8G8B8_UNORM
);
167 RETURN_FOR_SWIZZLE4(Y
, Z
, W
, 1, PIPE_FORMAT_A8R8G8B8_UNORM
);
171 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R16G16B16A16_UINT
);
172 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R16G16B16A16_UINT
);
176 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R32G32B32A32_UINT
);
177 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R32G32B32A32_UINT
);
182 assert(!"unknown array format");
183 return PIPE_FORMAT_NONE
;
186 assert(!"unknown packed format");
187 return PIPE_FORMAT_NONE
;
191 * Return true if the swizzle is XYZW in case of a 4-channel format,
192 * XY in case of a 2-channel format, or X in case of a 1-channel format.
195 has_identity_swizzle(const struct util_format_description
*desc
)
199 for (i
= 0; i
< desc
->nr_channels
; i
++)
200 if (desc
->swizzle
[i
] != PIPE_SWIZZLE_X
+ i
)
207 * Return a canonical format for the given bits and channel size.
209 static enum pipe_format
210 canonical_format_from_bits(unsigned bits
, unsigned channel_size
)
214 if (channel_size
== 8)
215 return get_canonical_format(PIPE_FORMAT_R8_UINT
);
219 if (channel_size
== 8)
220 return get_canonical_format(PIPE_FORMAT_R8G8_UINT
);
221 if (channel_size
== 16)
222 return get_canonical_format(PIPE_FORMAT_R16_UINT
);
226 if (channel_size
== 8)
227 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
228 if (channel_size
== 16)
229 return get_canonical_format(PIPE_FORMAT_R16G16_UINT
);
230 if (channel_size
== 32)
231 return get_canonical_format(PIPE_FORMAT_R32_UINT
);
235 if (channel_size
== 16)
236 return get_canonical_format(PIPE_FORMAT_R16G16B16A16_UINT
);
237 if (channel_size
== 32)
238 return get_canonical_format(PIPE_FORMAT_R32G32_UINT
);
242 if (channel_size
== 32)
243 return get_canonical_format(PIPE_FORMAT_R32G32B32A32_UINT
);
247 assert(!"impossible format");
248 return PIPE_FORMAT_NONE
;
252 blit(struct pipe_context
*pipe
,
253 struct pipe_resource
*dst
,
254 enum pipe_format dst_format
,
256 unsigned dstx
, unsigned dsty
, unsigned dstz
,
257 struct pipe_resource
*src
,
258 enum pipe_format src_format
,
260 const struct pipe_box
*src_box
)
262 struct pipe_blit_info blit
= {{0}};
264 blit
.src
.resource
= src
;
265 blit
.dst
.resource
= dst
;
266 blit
.src
.format
= src_format
;
267 blit
.dst
.format
= dst_format
;
268 blit
.src
.level
= src_level
;
269 blit
.dst
.level
= dst_level
;
270 blit
.src
.box
= *src_box
;
271 u_box_3d(dstx
, dsty
, dstz
, src_box
->width
, src_box
->height
,
272 src_box
->depth
, &blit
.dst
.box
);
273 blit
.mask
= PIPE_MASK_RGBA
;
274 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
276 pipe
->blit(pipe
, &blit
);
280 swizzled_copy(struct pipe_context
*pipe
,
281 struct pipe_resource
*dst
,
283 unsigned dstx
, unsigned dsty
, unsigned dstz
,
284 struct pipe_resource
*src
,
286 const struct pipe_box
*src_box
)
288 const struct util_format_description
*src_desc
, *dst_desc
;
290 enum pipe_format blit_src_format
, blit_dst_format
;
292 /* Get equivalent canonical formats. Those are always array formats and
293 * copying between compatible canonical formats behaves either like
294 * memcpy or like swizzled memcpy. The idea is that we won't have to care
295 * about the channel type from this point on.
296 * Only the swizzle and channel size.
298 blit_src_format
= get_canonical_format(src
->format
);
299 blit_dst_format
= get_canonical_format(dst
->format
);
301 assert(blit_src_format
!= PIPE_FORMAT_NONE
);
302 assert(blit_dst_format
!= PIPE_FORMAT_NONE
);
304 src_desc
= util_format_description(blit_src_format
);
305 dst_desc
= util_format_description(blit_dst_format
);
307 assert(src_desc
->block
.bits
== dst_desc
->block
.bits
);
308 bits
= src_desc
->block
.bits
;
310 if (dst_desc
->channel
[0].size
== src_desc
->channel
[0].size
) {
311 /* Only the swizzle is different, which means we can just blit,
314 } else if (has_identity_swizzle(src_desc
)) {
315 /* Src is unswizzled and dst can be swizzled, so src is typecast
316 * to an equivalent dst-compatible format.
317 * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8
320 canonical_format_from_bits(bits
, dst_desc
->channel
[0].size
);
321 } else if (has_identity_swizzle(dst_desc
)) {
322 /* Dst is unswizzled and src can be swizzled, so dst is typecast
323 * to an equivalent src-compatible format.
324 * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8
327 canonical_format_from_bits(bits
, src_desc
->channel
[0].size
);
329 assert(!"This should have been handled by handle_complex_copy.");
333 blit(pipe
, dst
, blit_dst_format
, dst_level
, dstx
, dsty
, dstz
,
334 src
, blit_src_format
, src_level
, src_box
);
338 same_size_and_swizzle(const struct util_format_description
*d1
,
339 const struct util_format_description
*d2
)
343 if (d1
->layout
!= d2
->layout
||
344 d1
->nr_channels
!= d2
->nr_channels
||
345 d1
->is_array
!= d2
->is_array
)
348 for (i
= 0; i
< d1
->nr_channels
; i
++) {
349 if (d1
->channel
[i
].size
!= d2
->channel
[i
].size
)
352 if (d1
->swizzle
[i
] <= PIPE_SWIZZLE_W
&&
353 d2
->swizzle
[i
] <= PIPE_SWIZZLE_W
&&
354 d1
->swizzle
[i
] != d2
->swizzle
[i
])
361 static struct pipe_resource
*
362 create_texture(struct pipe_screen
*screen
, enum pipe_format format
,
363 unsigned nr_samples
, unsigned nr_storage_samples
,
364 unsigned width
, unsigned height
, unsigned depth
)
366 struct pipe_resource templ
;
368 memset(&templ
, 0, sizeof(templ
));
369 templ
.format
= format
;
370 templ
.width0
= width
;
371 templ
.height0
= height
;
373 templ
.array_size
= depth
;
374 templ
.nr_samples
= nr_samples
;
375 templ
.nr_storage_samples
= nr_storage_samples
;
376 templ
.usage
= PIPE_USAGE_DEFAULT
;
377 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
380 templ
.target
= PIPE_TEXTURE_2D_ARRAY
;
382 templ
.target
= PIPE_TEXTURE_2D
;
384 return screen
->resource_create(screen
, &templ
);
388 * Handle complex format conversions using 2 blits with a temporary texture
389 * in between, e.g. blitting from B10G10R10A2 to G16R16.
391 * This example is implemented this way:
392 * 1) First, blit from B10G10R10A2 to R10G10B10A2, which is canonical, so it
393 * can be reinterpreted as a different canonical format of the same bpp,
394 * such as R16G16. This blit only swaps R and B 10-bit components.
395 * 2) Finally, blit the result, which is R10G10B10A2, as R16G16 to G16R16.
396 * This blit only swaps R and G 16-bit components.
399 handle_complex_copy(struct pipe_context
*pipe
,
400 struct pipe_resource
*dst
,
402 unsigned dstx
, unsigned dsty
, unsigned dstz
,
403 struct pipe_resource
*src
,
405 const struct pipe_box
*src_box
,
406 enum pipe_format noncanon_format
,
407 enum pipe_format canon_format
)
409 struct pipe_box temp_box
;
410 struct pipe_resource
*temp
= NULL
;
411 const struct util_format_description
*src_desc
, *dst_desc
;
412 const struct util_format_description
*canon_desc
, *noncanon_desc
;
414 bool src_is_noncanon
;
416 bool dst_is_noncanon
;
418 src_desc
= util_format_description(src
->format
);
419 dst_desc
= util_format_description(dst
->format
);
420 canon_desc
= util_format_description(canon_format
);
421 noncanon_desc
= util_format_description(noncanon_format
);
423 src_is_canon
= same_size_and_swizzle(src_desc
, canon_desc
);
424 dst_is_canon
= same_size_and_swizzle(dst_desc
, canon_desc
);
425 src_is_noncanon
= same_size_and_swizzle(src_desc
, noncanon_desc
);
426 dst_is_noncanon
= same_size_and_swizzle(dst_desc
, noncanon_desc
);
428 if (src_is_noncanon
) {
429 /* Simple case - only types differ (e.g. UNORM and UINT). */
430 if (dst_is_noncanon
) {
431 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
432 noncanon_format
, src_level
, src_box
);
436 /* Simple case - only types and swizzles differ. */
438 blit(pipe
, dst
, canon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
439 noncanon_format
, src_level
, src_box
);
443 /* Use the temporary texture. Src is converted to a canonical format,
444 * then proceed the generic swizzled_copy.
446 temp
= create_texture(pipe
->screen
, canon_format
, src
->nr_samples
,
447 src
->nr_storage_samples
, src_box
->width
,
448 src_box
->height
, src_box
->depth
);
450 u_box_3d(0, 0, 0, src_box
->width
, src_box
->height
, src_box
->depth
,
453 blit(pipe
, temp
, canon_format
, 0, 0, 0, 0, src
, noncanon_format
,
455 swizzled_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, temp
, 0,
457 pipe_resource_reference(&temp
, NULL
);
461 if (dst_is_noncanon
) {
462 /* Simple case - only types and swizzles differ. */
464 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
465 canon_format
, src_level
, src_box
);
469 /* Use the temporary texture. First, use the generic copy, but use
470 * a canonical format in the destination. Then convert */
471 temp
= create_texture(pipe
->screen
, canon_format
, dst
->nr_samples
,
472 dst
->nr_storage_samples
, src_box
->width
,
473 src_box
->height
, src_box
->depth
);
475 u_box_3d(0, 0, 0, src_box
->width
, src_box
->height
, src_box
->depth
,
478 swizzled_copy(pipe
, temp
, 0, 0, 0, 0, src
, src_level
, src_box
);
479 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, temp
,
480 canon_format
, 0, &temp_box
);
481 pipe_resource_reference(&temp
, NULL
);
489 copy_image(struct pipe_context
*pipe
,
490 struct pipe_resource
*dst
,
492 unsigned dstx
, unsigned dsty
, unsigned dstz
,
493 struct pipe_resource
*src
,
495 const struct pipe_box
*src_box
)
497 if (src
->format
== dst
->format
||
498 util_format_is_compressed(src
->format
) ||
499 util_format_is_compressed(dst
->format
)) {
500 pipe
->resource_copy_region(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
,
501 src
, src_level
, src_box
);
505 /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2
506 * as a temporary texture in between.
508 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
509 src_level
, src_box
, PIPE_FORMAT_B10G10R10A2_UINT
,
510 PIPE_FORMAT_R10G10B10A2_UINT
))
513 /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture
516 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
517 src_level
, src_box
, PIPE_FORMAT_G8R8_UNORM
,
518 PIPE_FORMAT_R8G8_UNORM
))
521 /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture
524 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
525 src_level
, src_box
, PIPE_FORMAT_G16R16_UNORM
,
526 PIPE_FORMAT_R16G16_UNORM
))
529 /* Only allow non-identity swizzling on RGBA8 formats. */
531 /* Simple copy, memcpy with swizzling, no format conversion. */
532 swizzled_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
, src_level
,
537 fallback_copy_image(struct st_context
*st
,
538 struct gl_texture_image
*dst_image
,
539 struct pipe_resource
*dst_res
,
540 int dst_x
, int dst_y
, int dst_z
,
541 struct gl_texture_image
*src_image
,
542 struct pipe_resource
*src_res
,
543 int src_x
, int src_y
, int src_z
,
544 int src_w
, int src_h
)
547 int dst_stride
, src_stride
;
548 struct pipe_transfer
*dst_transfer
, *src_transfer
;
551 bool dst_is_compressed
= dst_image
&& _mesa_is_format_compressed(dst_image
->TexFormat
);
552 bool src_is_compressed
= src_image
&& _mesa_is_format_compressed(src_image
->TexFormat
);
554 unsigned dst_blk_w
= 1, dst_blk_h
= 1, src_blk_w
= 1, src_blk_h
= 1;
556 _mesa_get_format_block_size(dst_image
->TexFormat
, &dst_blk_w
, &dst_blk_h
);
558 _mesa_get_format_block_size(src_image
->TexFormat
, &src_blk_w
, &src_blk_h
);
560 unsigned dst_w
= src_w
;
561 unsigned dst_h
= src_h
;
562 unsigned lines
= src_h
;
564 if (src_is_compressed
&& !dst_is_compressed
) {
565 dst_w
= DIV_ROUND_UP(dst_w
, src_blk_w
);
566 dst_h
= DIV_ROUND_UP(dst_h
, src_blk_h
);
567 } else if (!src_is_compressed
&& dst_is_compressed
) {
571 if (src_is_compressed
) {
572 lines
= DIV_ROUND_UP(lines
, src_blk_h
);
576 line_bytes
= _mesa_format_row_stride(src_image
->TexFormat
, src_w
);
578 line_bytes
= _mesa_format_row_stride(dst_image
->TexFormat
, dst_w
);
581 st
->ctx
->Driver
.MapTextureImage(
582 st
->ctx
, dst_image
, dst_z
,
583 dst_x
, dst_y
, dst_w
, dst_h
,
584 GL_MAP_WRITE_BIT
, &dst
, &dst_stride
);
586 dst
= pipe_transfer_map(st
->pipe
, dst_res
, 0, dst_z
,
588 dst_x
, dst_y
, dst_w
, dst_h
,
590 dst_stride
= dst_transfer
->stride
;
594 st
->ctx
->Driver
.MapTextureImage(
595 st
->ctx
, src_image
, src_z
,
596 src_x
, src_y
, src_w
, src_h
,
597 GL_MAP_READ_BIT
, &src
, &src_stride
);
599 src
= pipe_transfer_map(st
->pipe
, src_res
, 0, src_z
,
601 src_x
, src_y
, src_w
, src_h
,
603 src_stride
= src_transfer
->stride
;
606 for (int y
= 0; y
< lines
; y
++) {
607 memcpy(dst
, src
, line_bytes
);
613 st
->ctx
->Driver
.UnmapTextureImage(st
->ctx
, dst_image
, dst_z
);
615 pipe_transfer_unmap(st
->pipe
, dst_transfer
);
619 st
->ctx
->Driver
.UnmapTextureImage(st
->ctx
, src_image
, src_z
);
621 pipe_transfer_unmap(st
->pipe
, src_transfer
);
626 st_CopyImageSubData(struct gl_context
*ctx
,
627 struct gl_texture_image
*src_image
,
628 struct gl_renderbuffer
*src_renderbuffer
,
629 int src_x
, int src_y
, int src_z
,
630 struct gl_texture_image
*dst_image
,
631 struct gl_renderbuffer
*dst_renderbuffer
,
632 int dst_x
, int dst_y
, int dst_z
,
633 int src_width
, int src_height
)
635 struct st_context
*st
= st_context(ctx
);
636 struct pipe_context
*pipe
= st
->pipe
;
637 struct pipe_resource
*src_res
, *dst_res
;
639 int src_level
, dst_level
;
640 int orig_src_z
= src_z
, orig_dst_z
= dst_z
;
642 st_flush_bitmap_cache(st
);
643 st_invalidate_readpix_cache(st
);
646 struct st_texture_image
*src
= st_texture_image(src_image
);
648 src_level
= src_image
->Level
;
649 src_z
+= src_image
->Face
;
650 if (src_image
->TexObject
->Immutable
) {
651 src_level
+= src_image
->TexObject
->MinLevel
;
652 src_z
+= src_image
->TexObject
->MinLayer
;
655 struct st_renderbuffer
*src
= st_renderbuffer(src_renderbuffer
);
656 src_res
= src
->texture
;
661 struct st_texture_image
*dst
= st_texture_image(dst_image
);
663 dst_level
= dst_image
->Level
;
664 dst_z
+= dst_image
->Face
;
665 if (dst_image
->TexObject
->Immutable
) {
666 dst_level
+= dst_image
->TexObject
->MinLevel
;
667 dst_z
+= dst_image
->TexObject
->MinLayer
;
670 struct st_renderbuffer
*dst
= st_renderbuffer(dst_renderbuffer
);
671 dst_res
= dst
->texture
;
675 u_box_2d_zslice(src_x
, src_y
, src_z
, src_width
, src_height
, &box
);
677 if ((src_image
&& st_compressed_format_fallback(st
, src_image
->TexFormat
)) ||
678 (dst_image
&& st_compressed_format_fallback(st
, dst_image
->TexFormat
))) {
679 fallback_copy_image(st
, dst_image
, dst_res
, dst_x
, dst_y
, orig_dst_z
,
680 src_image
, src_res
, src_x
, src_y
, orig_src_z
,
681 src_width
, src_height
);
683 copy_image(pipe
, dst_res
, dst_level
, dst_x
, dst_y
, dst_z
,
684 src_res
, src_level
, &box
);
689 st_init_copy_image_functions(struct dd_function_table
*functions
)
691 functions
->CopyImageSubData
= st_CopyImageSubData
;