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"
30 #include "state_tracker/st_util.h"
32 #include "util/u_box.h"
33 #include "util/format/u_format.h"
34 #include "util/u_inlines.h"
38 * Return an equivalent canonical format without "X" channels.
40 * Copying between incompatible formats is easier when the format is
41 * canonicalized, meaning that it is in a standard form.
43 * The returned format has the same component sizes and swizzles as
44 * the source format, the type is changed to UINT or UNORM, depending on
45 * which one has the most swizzle combinations in their group.
47 * If it's not an array format, return a memcpy-equivalent array format.
49 * The key feature is that swizzled versions of formats of the same
50 * component size always return the same component type.
53 * Luminance, intensity, alpha, depth, stencil, and 8-bit and 16-bit packed
54 * formats are not supported. (same as ARB_copy_image)
56 static enum pipe_format
57 get_canonical_format(enum pipe_format format
)
59 const struct util_format_description
*desc
=
60 util_format_description(format
);
62 /* Packed formats. Return the equivalent array format. */
63 if (format
== PIPE_FORMAT_R11G11B10_FLOAT
||
64 format
== PIPE_FORMAT_R9G9B9E5_FLOAT
)
65 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
67 if (desc
->nr_channels
== 4 &&
68 desc
->channel
[0].size
== 10 &&
69 desc
->channel
[1].size
== 10 &&
70 desc
->channel
[2].size
== 10 &&
71 desc
->channel
[3].size
== 2) {
72 if (desc
->swizzle
[0] == PIPE_SWIZZLE_X
&&
73 desc
->swizzle
[1] == PIPE_SWIZZLE_Y
&&
74 desc
->swizzle
[2] == PIPE_SWIZZLE_Z
)
75 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
77 return PIPE_FORMAT_NONE
;
80 #define RETURN_FOR_SWIZZLE1(x, format) \
81 if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \
84 #define RETURN_FOR_SWIZZLE2(x, y, format) \
85 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
86 desc->swizzle[1] == PIPE_SWIZZLE_##y) \
89 #define RETURN_FOR_SWIZZLE3(x, y, z, format) \
90 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
91 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
92 desc->swizzle[2] == PIPE_SWIZZLE_##z) \
95 #define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \
96 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
97 desc->swizzle[1] == PIPE_SWIZZLE_##y && \
98 desc->swizzle[2] == PIPE_SWIZZLE_##z && \
99 desc->swizzle[3] == PIPE_SWIZZLE_##w) \
103 if (desc
->is_array
) {
104 switch (desc
->nr_channels
) {
106 switch (desc
->channel
[0].size
) {
108 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R8_UINT
);
112 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R16_UINT
);
116 RETURN_FOR_SWIZZLE1(X
, PIPE_FORMAT_R32_UINT
);
122 switch (desc
->channel
[0].size
) {
124 /* All formats in each group must be of the same type.
125 * We can't use UINT for R8G8 while using UNORM for G8R8.
127 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R8G8_UNORM
);
128 RETURN_FOR_SWIZZLE2(Y
, X
, PIPE_FORMAT_G8R8_UNORM
);
132 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R16G16_UNORM
);
133 RETURN_FOR_SWIZZLE2(Y
, X
, PIPE_FORMAT_G16R16_UNORM
);
137 RETURN_FOR_SWIZZLE2(X
, Y
, PIPE_FORMAT_R32G32_UINT
);
143 switch (desc
->channel
[0].size
) {
145 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R8G8B8_UINT
);
149 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R16G16B16_UINT
);
153 RETURN_FOR_SWIZZLE3(X
, Y
, Z
, PIPE_FORMAT_R32G32B32_UINT
);
159 switch (desc
->channel
[0].size
) {
161 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R8G8B8A8_UNORM
);
162 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R8G8B8A8_UNORM
);
163 RETURN_FOR_SWIZZLE4(Z
, Y
, X
, W
, PIPE_FORMAT_B8G8R8A8_UNORM
);
164 RETURN_FOR_SWIZZLE4(Z
, Y
, X
, 1, PIPE_FORMAT_B8G8R8A8_UNORM
);
165 RETURN_FOR_SWIZZLE4(W
, Z
, Y
, X
, PIPE_FORMAT_A8B8G8R8_UNORM
);
166 RETURN_FOR_SWIZZLE4(W
, Z
, Y
, 1, PIPE_FORMAT_A8B8G8R8_UNORM
);
167 RETURN_FOR_SWIZZLE4(Y
, Z
, W
, X
, PIPE_FORMAT_A8R8G8B8_UNORM
);
168 RETURN_FOR_SWIZZLE4(Y
, Z
, W
, 1, PIPE_FORMAT_A8R8G8B8_UNORM
);
172 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R16G16B16A16_UINT
);
173 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R16G16B16A16_UINT
);
177 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, W
, PIPE_FORMAT_R32G32B32A32_UINT
);
178 RETURN_FOR_SWIZZLE4(X
, Y
, Z
, 1, PIPE_FORMAT_R32G32B32A32_UINT
);
183 assert(!"unknown array format");
184 return PIPE_FORMAT_NONE
;
187 assert(!"unknown packed format");
188 return PIPE_FORMAT_NONE
;
192 * Return true if the swizzle is XYZW in case of a 4-channel format,
193 * XY in case of a 2-channel format, or X in case of a 1-channel format.
196 has_identity_swizzle(const struct util_format_description
*desc
)
200 for (i
= 0; i
< desc
->nr_channels
; i
++)
201 if (desc
->swizzle
[i
] != PIPE_SWIZZLE_X
+ i
)
208 * Return a canonical format for the given bits and channel size.
210 static enum pipe_format
211 canonical_format_from_bits(unsigned bits
, unsigned channel_size
)
215 if (channel_size
== 8)
216 return get_canonical_format(PIPE_FORMAT_R8_UINT
);
220 if (channel_size
== 8)
221 return get_canonical_format(PIPE_FORMAT_R8G8_UINT
);
222 if (channel_size
== 16)
223 return get_canonical_format(PIPE_FORMAT_R16_UINT
);
227 if (channel_size
== 8)
228 return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT
);
229 if (channel_size
== 16)
230 return get_canonical_format(PIPE_FORMAT_R16G16_UINT
);
231 if (channel_size
== 32)
232 return get_canonical_format(PIPE_FORMAT_R32_UINT
);
236 if (channel_size
== 16)
237 return get_canonical_format(PIPE_FORMAT_R16G16B16A16_UINT
);
238 if (channel_size
== 32)
239 return get_canonical_format(PIPE_FORMAT_R32G32_UINT
);
243 if (channel_size
== 32)
244 return get_canonical_format(PIPE_FORMAT_R32G32B32A32_UINT
);
248 assert(!"impossible format");
249 return PIPE_FORMAT_NONE
;
253 blit(struct pipe_context
*pipe
,
254 struct pipe_resource
*dst
,
255 enum pipe_format dst_format
,
257 unsigned dstx
, unsigned dsty
, unsigned dstz
,
258 struct pipe_resource
*src
,
259 enum pipe_format src_format
,
261 const struct pipe_box
*src_box
)
263 struct pipe_blit_info blit
= {{0}};
265 blit
.src
.resource
= src
;
266 blit
.dst
.resource
= dst
;
267 blit
.src
.format
= src_format
;
268 blit
.dst
.format
= dst_format
;
269 blit
.src
.level
= src_level
;
270 blit
.dst
.level
= dst_level
;
271 blit
.src
.box
= *src_box
;
272 u_box_3d(dstx
, dsty
, dstz
, src_box
->width
, src_box
->height
,
273 src_box
->depth
, &blit
.dst
.box
);
274 blit
.mask
= PIPE_MASK_RGBA
;
275 blit
.filter
= PIPE_TEX_FILTER_NEAREST
;
277 pipe
->blit(pipe
, &blit
);
281 swizzled_copy(struct pipe_context
*pipe
,
282 struct pipe_resource
*dst
,
284 unsigned dstx
, unsigned dsty
, unsigned dstz
,
285 struct pipe_resource
*src
,
287 const struct pipe_box
*src_box
)
289 const struct util_format_description
*src_desc
, *dst_desc
;
291 enum pipe_format blit_src_format
, blit_dst_format
;
293 /* Get equivalent canonical formats. Those are always array formats and
294 * copying between compatible canonical formats behaves either like
295 * memcpy or like swizzled memcpy. The idea is that we won't have to care
296 * about the channel type from this point on.
297 * Only the swizzle and channel size.
299 blit_src_format
= get_canonical_format(src
->format
);
300 blit_dst_format
= get_canonical_format(dst
->format
);
302 assert(blit_src_format
!= PIPE_FORMAT_NONE
);
303 assert(blit_dst_format
!= PIPE_FORMAT_NONE
);
305 src_desc
= util_format_description(blit_src_format
);
306 dst_desc
= util_format_description(blit_dst_format
);
308 assert(src_desc
->block
.bits
== dst_desc
->block
.bits
);
309 bits
= src_desc
->block
.bits
;
311 if (dst_desc
->channel
[0].size
== src_desc
->channel
[0].size
) {
312 /* Only the swizzle is different, which means we can just blit,
315 } else if (has_identity_swizzle(src_desc
)) {
316 /* Src is unswizzled and dst can be swizzled, so src is typecast
317 * to an equivalent dst-compatible format.
318 * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8
321 canonical_format_from_bits(bits
, dst_desc
->channel
[0].size
);
322 } else if (has_identity_swizzle(dst_desc
)) {
323 /* Dst is unswizzled and src can be swizzled, so dst is typecast
324 * to an equivalent src-compatible format.
325 * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8
328 canonical_format_from_bits(bits
, src_desc
->channel
[0].size
);
330 assert(!"This should have been handled by handle_complex_copy.");
334 blit(pipe
, dst
, blit_dst_format
, dst_level
, dstx
, dsty
, dstz
,
335 src
, blit_src_format
, src_level
, src_box
);
339 same_size_and_swizzle(const struct util_format_description
*d1
,
340 const struct util_format_description
*d2
)
344 if (d1
->layout
!= d2
->layout
||
345 d1
->nr_channels
!= d2
->nr_channels
||
346 d1
->is_array
!= d2
->is_array
)
349 for (i
= 0; i
< d1
->nr_channels
; i
++) {
350 if (d1
->channel
[i
].size
!= d2
->channel
[i
].size
)
353 if (d1
->swizzle
[i
] <= PIPE_SWIZZLE_W
&&
354 d2
->swizzle
[i
] <= PIPE_SWIZZLE_W
&&
355 d1
->swizzle
[i
] != d2
->swizzle
[i
])
362 static struct pipe_resource
*
363 create_texture(struct pipe_screen
*screen
, enum pipe_format format
,
364 unsigned nr_samples
, unsigned nr_storage_samples
,
365 unsigned width
, unsigned height
, unsigned depth
)
367 struct pipe_resource templ
;
369 memset(&templ
, 0, sizeof(templ
));
370 templ
.format
= format
;
371 templ
.width0
= width
;
372 templ
.height0
= height
;
374 templ
.array_size
= depth
;
375 templ
.nr_samples
= nr_samples
;
376 templ
.nr_storage_samples
= nr_storage_samples
;
377 templ
.usage
= PIPE_USAGE_DEFAULT
;
378 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
381 templ
.target
= PIPE_TEXTURE_2D_ARRAY
;
383 templ
.target
= PIPE_TEXTURE_2D
;
385 return screen
->resource_create(screen
, &templ
);
389 * Handle complex format conversions using 2 blits with a temporary texture
390 * in between, e.g. blitting from B10G10R10A2 to G16R16.
392 * This example is implemented this way:
393 * 1) First, blit from B10G10R10A2 to R10G10B10A2, which is canonical, so it
394 * can be reinterpreted as a different canonical format of the same bpp,
395 * such as R16G16. This blit only swaps R and B 10-bit components.
396 * 2) Finally, blit the result, which is R10G10B10A2, as R16G16 to G16R16.
397 * This blit only swaps R and G 16-bit components.
400 handle_complex_copy(struct pipe_context
*pipe
,
401 struct pipe_resource
*dst
,
403 unsigned dstx
, unsigned dsty
, unsigned dstz
,
404 struct pipe_resource
*src
,
406 const struct pipe_box
*src_box
,
407 enum pipe_format noncanon_format
,
408 enum pipe_format canon_format
)
410 struct pipe_box temp_box
;
411 struct pipe_resource
*temp
= NULL
;
412 const struct util_format_description
*src_desc
, *dst_desc
;
413 const struct util_format_description
*canon_desc
, *noncanon_desc
;
415 bool src_is_noncanon
;
417 bool dst_is_noncanon
;
419 src_desc
= util_format_description(src
->format
);
420 dst_desc
= util_format_description(dst
->format
);
421 canon_desc
= util_format_description(canon_format
);
422 noncanon_desc
= util_format_description(noncanon_format
);
424 src_is_canon
= same_size_and_swizzle(src_desc
, canon_desc
);
425 dst_is_canon
= same_size_and_swizzle(dst_desc
, canon_desc
);
426 src_is_noncanon
= same_size_and_swizzle(src_desc
, noncanon_desc
);
427 dst_is_noncanon
= same_size_and_swizzle(dst_desc
, noncanon_desc
);
429 if (src_is_noncanon
) {
430 /* Simple case - only types differ (e.g. UNORM and UINT). */
431 if (dst_is_noncanon
) {
432 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
433 noncanon_format
, src_level
, src_box
);
437 /* Simple case - only types and swizzles differ. */
439 blit(pipe
, dst
, canon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
440 noncanon_format
, src_level
, src_box
);
444 /* Use the temporary texture. Src is converted to a canonical format,
445 * then proceed the generic swizzled_copy.
447 temp
= create_texture(pipe
->screen
, canon_format
, src
->nr_samples
,
448 src
->nr_storage_samples
, src_box
->width
,
449 src_box
->height
, src_box
->depth
);
451 u_box_3d(0, 0, 0, src_box
->width
, src_box
->height
, src_box
->depth
,
454 blit(pipe
, temp
, canon_format
, 0, 0, 0, 0, src
, noncanon_format
,
456 swizzled_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, temp
, 0,
458 pipe_resource_reference(&temp
, NULL
);
462 if (dst_is_noncanon
) {
463 /* Simple case - only types and swizzles differ. */
465 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, src
,
466 canon_format
, src_level
, src_box
);
470 /* Use the temporary texture. First, use the generic copy, but use
471 * a canonical format in the destination. Then convert */
472 temp
= create_texture(pipe
->screen
, canon_format
, dst
->nr_samples
,
473 dst
->nr_storage_samples
, src_box
->width
,
474 src_box
->height
, src_box
->depth
);
476 u_box_3d(0, 0, 0, src_box
->width
, src_box
->height
, src_box
->depth
,
479 swizzled_copy(pipe
, temp
, 0, 0, 0, 0, src
, src_level
, src_box
);
480 blit(pipe
, dst
, noncanon_format
, dst_level
, dstx
, dsty
, dstz
, temp
,
481 canon_format
, 0, &temp_box
);
482 pipe_resource_reference(&temp
, NULL
);
490 copy_image(struct pipe_context
*pipe
,
491 struct pipe_resource
*dst
,
493 unsigned dstx
, unsigned dsty
, unsigned dstz
,
494 struct pipe_resource
*src
,
496 const struct pipe_box
*src_box
)
498 if (src
->format
== dst
->format
||
499 util_format_is_compressed(src
->format
) ||
500 util_format_is_compressed(dst
->format
)) {
501 pipe
->resource_copy_region(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
,
502 src
, src_level
, src_box
);
506 /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2
507 * as a temporary texture in between.
509 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
510 src_level
, src_box
, PIPE_FORMAT_B10G10R10A2_UINT
,
511 PIPE_FORMAT_R10G10B10A2_UINT
))
514 /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture
517 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
518 src_level
, src_box
, PIPE_FORMAT_G8R8_UNORM
,
519 PIPE_FORMAT_R8G8_UNORM
))
522 /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture
525 if (handle_complex_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
,
526 src_level
, src_box
, PIPE_FORMAT_G16R16_UNORM
,
527 PIPE_FORMAT_R16G16_UNORM
))
530 /* Only allow non-identity swizzling on RGBA8 formats. */
532 /* Simple copy, memcpy with swizzling, no format conversion. */
533 swizzled_copy(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
, src_level
,
538 fallback_copy_image(struct st_context
*st
,
539 struct gl_texture_image
*dst_image
,
540 struct pipe_resource
*dst_res
,
541 int dst_x
, int dst_y
, int dst_z
,
542 struct gl_texture_image
*src_image
,
543 struct pipe_resource
*src_res
,
544 int src_x
, int src_y
, int src_z
,
545 int src_w
, int src_h
)
548 int dst_stride
, src_stride
;
549 struct pipe_transfer
*dst_transfer
, *src_transfer
;
552 bool dst_is_compressed
= dst_image
&& _mesa_is_format_compressed(dst_image
->TexFormat
);
553 bool src_is_compressed
= src_image
&& _mesa_is_format_compressed(src_image
->TexFormat
);
555 unsigned dst_blk_w
= 1, dst_blk_h
= 1, src_blk_w
= 1, src_blk_h
= 1;
557 _mesa_get_format_block_size(dst_image
->TexFormat
, &dst_blk_w
, &dst_blk_h
);
559 _mesa_get_format_block_size(src_image
->TexFormat
, &src_blk_w
, &src_blk_h
);
561 unsigned dst_w
= src_w
;
562 unsigned dst_h
= src_h
;
563 unsigned lines
= src_h
;
565 if (src_is_compressed
&& !dst_is_compressed
) {
566 dst_w
= DIV_ROUND_UP(dst_w
, src_blk_w
);
567 dst_h
= DIV_ROUND_UP(dst_h
, src_blk_h
);
568 } else if (!src_is_compressed
&& dst_is_compressed
) {
572 if (src_is_compressed
) {
573 lines
= DIV_ROUND_UP(lines
, src_blk_h
);
577 line_bytes
= _mesa_format_row_stride(src_image
->TexFormat
, src_w
);
579 line_bytes
= _mesa_format_row_stride(dst_image
->TexFormat
, dst_w
);
582 st
->ctx
->Driver
.MapTextureImage(
583 st
->ctx
, dst_image
, dst_z
,
584 dst_x
, dst_y
, dst_w
, dst_h
,
585 GL_MAP_WRITE_BIT
, &dst
, &dst_stride
);
587 dst
= pipe_transfer_map(st
->pipe
, dst_res
, 0, dst_z
,
589 dst_x
, dst_y
, dst_w
, dst_h
,
591 dst_stride
= dst_transfer
->stride
;
595 st
->ctx
->Driver
.MapTextureImage(
596 st
->ctx
, src_image
, src_z
,
597 src_x
, src_y
, src_w
, src_h
,
598 GL_MAP_READ_BIT
, &src
, &src_stride
);
600 src
= pipe_transfer_map(st
->pipe
, src_res
, 0, src_z
,
602 src_x
, src_y
, src_w
, src_h
,
604 src_stride
= src_transfer
->stride
;
607 for (int y
= 0; y
< lines
; y
++) {
608 memcpy(dst
, src
, line_bytes
);
614 st
->ctx
->Driver
.UnmapTextureImage(st
->ctx
, dst_image
, dst_z
);
616 pipe_transfer_unmap(st
->pipe
, dst_transfer
);
620 st
->ctx
->Driver
.UnmapTextureImage(st
->ctx
, src_image
, src_z
);
622 pipe_transfer_unmap(st
->pipe
, src_transfer
);
627 st_CopyImageSubData(struct gl_context
*ctx
,
628 struct gl_texture_image
*src_image
,
629 struct gl_renderbuffer
*src_renderbuffer
,
630 int src_x
, int src_y
, int src_z
,
631 struct gl_texture_image
*dst_image
,
632 struct gl_renderbuffer
*dst_renderbuffer
,
633 int dst_x
, int dst_y
, int dst_z
,
634 int src_width
, int src_height
)
636 struct st_context
*st
= st_context(ctx
);
637 struct pipe_context
*pipe
= st
->pipe
;
638 struct pipe_resource
*src_res
, *dst_res
;
640 int src_level
, dst_level
;
641 int orig_src_z
= src_z
, orig_dst_z
= dst_z
;
643 st_flush_bitmap_cache(st
);
644 st_invalidate_readpix_cache(st
);
647 struct st_texture_image
*src
= st_texture_image(src_image
);
648 struct st_texture_object
*stObj
= st_texture_object(src_image
->TexObject
);
650 src_level
= stObj
->pt
!= src_res
? 0 : src_image
->Level
;
651 src_z
+= src_image
->Face
;
652 if (src_image
->TexObject
->Immutable
) {
653 src_level
+= src_image
->TexObject
->MinLevel
;
654 src_z
+= src_image
->TexObject
->MinLayer
;
657 struct st_renderbuffer
*src
= st_renderbuffer(src_renderbuffer
);
658 src_res
= src
->texture
;
663 struct st_texture_image
*dst
= st_texture_image(dst_image
);
664 struct st_texture_object
*stObj
= st_texture_object(dst_image
->TexObject
);
666 dst_level
= stObj
->pt
!= dst_res
? 0 : dst_image
->Level
;
667 dst_z
+= dst_image
->Face
;
668 if (dst_image
->TexObject
->Immutable
) {
669 dst_level
+= dst_image
->TexObject
->MinLevel
;
670 dst_z
+= dst_image
->TexObject
->MinLayer
;
673 struct st_renderbuffer
*dst
= st_renderbuffer(dst_renderbuffer
);
674 dst_res
= dst
->texture
;
678 u_box_2d_zslice(src_x
, src_y
, src_z
, src_width
, src_height
, &box
);
680 if ((src_image
&& st_compressed_format_fallback(st
, src_image
->TexFormat
)) ||
681 (dst_image
&& st_compressed_format_fallback(st
, dst_image
->TexFormat
))) {
682 fallback_copy_image(st
, dst_image
, dst_res
, dst_x
, dst_y
, orig_dst_z
,
683 src_image
, src_res
, src_x
, src_y
, orig_src_z
,
684 src_width
, src_height
);
686 copy_image(pipe
, dst_res
, dst_level
, dst_x
, dst_y
, dst_z
,
687 src_res
, src_level
, &box
);
692 st_init_copy_image_functions(struct dd_function_table
*functions
)
694 functions
->CopyImageSubData
= st_CopyImageSubData
;