1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "state_tracker/st_context.h" 26bf215546Sopenharmony_ci#include "state_tracker/st_cb_bitmap.h" 27bf215546Sopenharmony_ci#include "state_tracker/st_cb_copyimage.h" 28bf215546Sopenharmony_ci#include "state_tracker/st_cb_texture.h" 29bf215546Sopenharmony_ci#include "state_tracker/st_texture.h" 30bf215546Sopenharmony_ci#include "state_tracker/st_util.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "util/u_box.h" 33bf215546Sopenharmony_ci#include "util/format/u_format.h" 34bf215546Sopenharmony_ci#include "util/u_inlines.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/** 38bf215546Sopenharmony_ci * Return an equivalent canonical format without "X" channels. 39bf215546Sopenharmony_ci * 40bf215546Sopenharmony_ci * Copying between incompatible formats is easier when the format is 41bf215546Sopenharmony_ci * canonicalized, meaning that it is in a standard form. 42bf215546Sopenharmony_ci * 43bf215546Sopenharmony_ci * The returned format has the same component sizes and swizzles as 44bf215546Sopenharmony_ci * the source format, the type is changed to UINT or UNORM, depending on 45bf215546Sopenharmony_ci * which one has the most swizzle combinations in their group. 46bf215546Sopenharmony_ci * 47bf215546Sopenharmony_ci * If it's not an array format, return a memcpy-equivalent array format. 48bf215546Sopenharmony_ci * 49bf215546Sopenharmony_ci * The key feature is that swizzled versions of formats of the same 50bf215546Sopenharmony_ci * component size always return the same component type. 51bf215546Sopenharmony_ci * 52bf215546Sopenharmony_ci * X returns A. 53bf215546Sopenharmony_ci * Luminance, intensity, alpha, depth, stencil, and 8-bit and 16-bit packed 54bf215546Sopenharmony_ci * formats are not supported. (same as ARB_copy_image) 55bf215546Sopenharmony_ci */ 56bf215546Sopenharmony_cistatic enum pipe_format 57bf215546Sopenharmony_ciget_canonical_format(struct pipe_screen *screen, 58bf215546Sopenharmony_ci enum pipe_format format) 59bf215546Sopenharmony_ci{ 60bf215546Sopenharmony_ci const struct util_format_description *desc = 61bf215546Sopenharmony_ci util_format_description(format); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci /* Packed formats. Return the equivalent array format. */ 64bf215546Sopenharmony_ci if (format == PIPE_FORMAT_R11G11B10_FLOAT || 65bf215546Sopenharmony_ci format == PIPE_FORMAT_R9G9B9E5_FLOAT) 66bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci if (desc->nr_channels == 4 && 69bf215546Sopenharmony_ci desc->channel[0].size == 10 && 70bf215546Sopenharmony_ci desc->channel[1].size == 10 && 71bf215546Sopenharmony_ci desc->channel[2].size == 10 && 72bf215546Sopenharmony_ci desc->channel[3].size == 2) { 73bf215546Sopenharmony_ci if (desc->swizzle[0] == PIPE_SWIZZLE_X && 74bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_Y && 75bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_Z) 76bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE1(x, format) \ 82bf215546Sopenharmony_ci if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \ 83bf215546Sopenharmony_ci return (screen->get_canonical_format ? \ 84bf215546Sopenharmony_ci screen->get_canonical_format(screen, format) : \ 85bf215546Sopenharmony_ci format) 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE2(x, y, format) \ 88bf215546Sopenharmony_ci if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \ 89bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_##y) \ 90bf215546Sopenharmony_ci return (screen->get_canonical_format ? \ 91bf215546Sopenharmony_ci screen->get_canonical_format(screen, format) : \ 92bf215546Sopenharmony_ci format) 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE3(x, y, z, format) \ 95bf215546Sopenharmony_ci if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \ 96bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_##y && \ 97bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_##z) \ 98bf215546Sopenharmony_ci return (screen->get_canonical_format ? \ 99bf215546Sopenharmony_ci screen->get_canonical_format(screen, format) : \ 100bf215546Sopenharmony_ci format) 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci#define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \ 103bf215546Sopenharmony_ci if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \ 104bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_##y && \ 105bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_##z && \ 106bf215546Sopenharmony_ci desc->swizzle[3] == PIPE_SWIZZLE_##w) \ 107bf215546Sopenharmony_ci return (screen->get_canonical_format ? \ 108bf215546Sopenharmony_ci screen->get_canonical_format(screen, format) : \ 109bf215546Sopenharmony_ci format) 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* Array formats. */ 112bf215546Sopenharmony_ci if (desc->is_array) { 113bf215546Sopenharmony_ci switch (desc->nr_channels) { 114bf215546Sopenharmony_ci case 1: 115bf215546Sopenharmony_ci switch (desc->channel[0].size) { 116bf215546Sopenharmony_ci case 8: 117bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R8_UINT); 118bf215546Sopenharmony_ci break; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci case 16: 121bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R16_UINT); 122bf215546Sopenharmony_ci break; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci case 32: 125bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R32_UINT); 126bf215546Sopenharmony_ci break; 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci break; 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci case 2: 131bf215546Sopenharmony_ci switch (desc->channel[0].size) { 132bf215546Sopenharmony_ci case 8: 133bf215546Sopenharmony_ci /* All formats in each group must be of the same type. 134bf215546Sopenharmony_ci * We can't use UINT for R8G8 while using UNORM for G8R8. 135bf215546Sopenharmony_ci */ 136bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R8G8_UNORM); 137bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G8R8_UNORM); 138bf215546Sopenharmony_ci break; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci case 16: 141bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R16G16_UNORM); 142bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G16R16_UNORM); 143bf215546Sopenharmony_ci break; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci case 32: 146bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R32G32_UINT); 147bf215546Sopenharmony_ci break; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci break; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci case 3: 152bf215546Sopenharmony_ci switch (desc->channel[0].size) { 153bf215546Sopenharmony_ci case 8: 154bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R8G8B8_UINT); 155bf215546Sopenharmony_ci break; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci case 16: 158bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R16G16B16_UINT); 159bf215546Sopenharmony_ci break; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci case 32: 162bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R32G32B32_UINT); 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci break; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci case 4: 168bf215546Sopenharmony_ci switch (desc->channel[0].size) { 169bf215546Sopenharmony_ci case 8: 170bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R8G8B8A8_UNORM); 171bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R8G8B8A8_UNORM); 172bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(Z, Y, X, W, PIPE_FORMAT_B8G8R8A8_UNORM); 173bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(Z, Y, X, 1, PIPE_FORMAT_B8G8R8A8_UNORM); 174bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(W, Z, Y, X, PIPE_FORMAT_A8B8G8R8_UNORM); 175bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(W, Z, Y, 1, PIPE_FORMAT_A8B8G8R8_UNORM); 176bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(Y, Z, W, X, PIPE_FORMAT_A8R8G8B8_UNORM); 177bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(Y, Z, W, 1, PIPE_FORMAT_A8R8G8B8_UNORM); 178bf215546Sopenharmony_ci break; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci case 16: 181bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R16G16B16A16_UINT); 182bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R16G16B16A16_UINT); 183bf215546Sopenharmony_ci break; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci case 32: 186bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R32G32B32A32_UINT); 187bf215546Sopenharmony_ci RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R32G32B32A32_UINT); 188bf215546Sopenharmony_ci break; 189bf215546Sopenharmony_ci } 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci assert(!"unknown array format"); 193bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci assert(!"unknown packed format"); 197bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci/** 201bf215546Sopenharmony_ci * Return true if the swizzle is XYZW in case of a 4-channel format, 202bf215546Sopenharmony_ci * XY in case of a 2-channel format, or X in case of a 1-channel format. 203bf215546Sopenharmony_ci */ 204bf215546Sopenharmony_cistatic bool 205bf215546Sopenharmony_cihas_identity_swizzle(const struct util_format_description *desc) 206bf215546Sopenharmony_ci{ 207bf215546Sopenharmony_ci int i; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci for (i = 0; i < desc->nr_channels; i++) 210bf215546Sopenharmony_ci if (desc->swizzle[i] != PIPE_SWIZZLE_X + i) 211bf215546Sopenharmony_ci return false; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci return true; 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci/** 217bf215546Sopenharmony_ci * Return a canonical format for the given bits and channel size. 218bf215546Sopenharmony_ci */ 219bf215546Sopenharmony_cistatic enum pipe_format 220bf215546Sopenharmony_cicanonical_format_from_bits(struct pipe_screen *screen, 221bf215546Sopenharmony_ci unsigned bits, 222bf215546Sopenharmony_ci unsigned channel_size) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci switch (bits) { 225bf215546Sopenharmony_ci case 8: 226bf215546Sopenharmony_ci if (channel_size == 8) 227bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R8_UINT); 228bf215546Sopenharmony_ci break; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci case 16: 231bf215546Sopenharmony_ci if (channel_size == 8) 232bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R8G8_UINT); 233bf215546Sopenharmony_ci if (channel_size == 16) 234bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R16_UINT); 235bf215546Sopenharmony_ci break; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci case 32: 238bf215546Sopenharmony_ci if (channel_size == 8) 239bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R8G8B8A8_UINT); 240bf215546Sopenharmony_ci if (channel_size == 16) 241bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R16G16_UINT); 242bf215546Sopenharmony_ci if (channel_size == 32) 243bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R32_UINT); 244bf215546Sopenharmony_ci break; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci case 64: 247bf215546Sopenharmony_ci if (channel_size == 16) 248bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R16G16B16A16_UINT); 249bf215546Sopenharmony_ci if (channel_size == 32) 250bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R32G32_UINT); 251bf215546Sopenharmony_ci break; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci case 128: 254bf215546Sopenharmony_ci if (channel_size == 32) 255bf215546Sopenharmony_ci return get_canonical_format(screen, PIPE_FORMAT_R32G32B32A32_UINT); 256bf215546Sopenharmony_ci break; 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci assert(!"impossible format"); 260bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 261bf215546Sopenharmony_ci} 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_cistatic void 264bf215546Sopenharmony_ciblit(struct pipe_context *pipe, 265bf215546Sopenharmony_ci struct pipe_resource *dst, 266bf215546Sopenharmony_ci enum pipe_format dst_format, 267bf215546Sopenharmony_ci unsigned dst_level, 268bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 269bf215546Sopenharmony_ci struct pipe_resource *src, 270bf215546Sopenharmony_ci enum pipe_format src_format, 271bf215546Sopenharmony_ci unsigned src_level, 272bf215546Sopenharmony_ci const struct pipe_box *src_box) 273bf215546Sopenharmony_ci{ 274bf215546Sopenharmony_ci struct pipe_blit_info blit = {{0}}; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci blit.src.resource = src; 277bf215546Sopenharmony_ci blit.dst.resource = dst; 278bf215546Sopenharmony_ci blit.src.format = src_format; 279bf215546Sopenharmony_ci blit.dst.format = dst_format; 280bf215546Sopenharmony_ci blit.src.level = src_level; 281bf215546Sopenharmony_ci blit.dst.level = dst_level; 282bf215546Sopenharmony_ci blit.src.box = *src_box; 283bf215546Sopenharmony_ci u_box_3d(dstx, dsty, dstz, src_box->width, src_box->height, 284bf215546Sopenharmony_ci src_box->depth, &blit.dst.box); 285bf215546Sopenharmony_ci blit.mask = PIPE_MASK_RGBA; 286bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci pipe->blit(pipe, &blit); 289bf215546Sopenharmony_ci} 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_cistatic void 292bf215546Sopenharmony_ciswizzled_copy(struct pipe_context *pipe, 293bf215546Sopenharmony_ci struct pipe_resource *dst, 294bf215546Sopenharmony_ci unsigned dst_level, 295bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 296bf215546Sopenharmony_ci struct pipe_resource *src, 297bf215546Sopenharmony_ci unsigned src_level, 298bf215546Sopenharmony_ci const struct pipe_box *src_box) 299bf215546Sopenharmony_ci{ 300bf215546Sopenharmony_ci const struct util_format_description *src_desc, *dst_desc; 301bf215546Sopenharmony_ci unsigned bits; 302bf215546Sopenharmony_ci enum pipe_format blit_src_format, blit_dst_format; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci /* Get equivalent canonical formats. Those are always array formats and 305bf215546Sopenharmony_ci * copying between compatible canonical formats behaves either like 306bf215546Sopenharmony_ci * memcpy or like swizzled memcpy. The idea is that we won't have to care 307bf215546Sopenharmony_ci * about the channel type from this point on. 308bf215546Sopenharmony_ci * Only the swizzle and channel size. 309bf215546Sopenharmony_ci */ 310bf215546Sopenharmony_ci blit_src_format = get_canonical_format(pipe->screen, src->format); 311bf215546Sopenharmony_ci blit_dst_format = get_canonical_format(pipe->screen, dst->format); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci assert(blit_src_format != PIPE_FORMAT_NONE); 314bf215546Sopenharmony_ci assert(blit_dst_format != PIPE_FORMAT_NONE); 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci src_desc = util_format_description(blit_src_format); 317bf215546Sopenharmony_ci dst_desc = util_format_description(blit_dst_format); 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci assert(src_desc->block.bits == dst_desc->block.bits); 320bf215546Sopenharmony_ci bits = src_desc->block.bits; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci if (dst_desc->channel[0].size == src_desc->channel[0].size) { 323bf215546Sopenharmony_ci /* Only the swizzle is different, which means we can just blit, 324bf215546Sopenharmony_ci * e.g. RGBA -> BGRA. 325bf215546Sopenharmony_ci */ 326bf215546Sopenharmony_ci } else if (has_identity_swizzle(src_desc)) { 327bf215546Sopenharmony_ci /* Src is unswizzled and dst can be swizzled, so src is typecast 328bf215546Sopenharmony_ci * to an equivalent dst-compatible format. 329bf215546Sopenharmony_ci * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8 330bf215546Sopenharmony_ci */ 331bf215546Sopenharmony_ci blit_src_format = 332bf215546Sopenharmony_ci canonical_format_from_bits(pipe->screen, bits, dst_desc->channel[0].size); 333bf215546Sopenharmony_ci } else if (has_identity_swizzle(dst_desc)) { 334bf215546Sopenharmony_ci /* Dst is unswizzled and src can be swizzled, so dst is typecast 335bf215546Sopenharmony_ci * to an equivalent src-compatible format. 336bf215546Sopenharmony_ci * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8 337bf215546Sopenharmony_ci */ 338bf215546Sopenharmony_ci blit_dst_format = 339bf215546Sopenharmony_ci canonical_format_from_bits(pipe->screen, bits, src_desc->channel[0].size); 340bf215546Sopenharmony_ci } else { 341bf215546Sopenharmony_ci assert(!"This should have been handled by handle_complex_copy."); 342bf215546Sopenharmony_ci return; 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci blit(pipe, dst, blit_dst_format, dst_level, dstx, dsty, dstz, 346bf215546Sopenharmony_ci src, blit_src_format, src_level, src_box); 347bf215546Sopenharmony_ci} 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_cistatic bool 350bf215546Sopenharmony_cisame_size_and_swizzle(const struct util_format_description *d1, 351bf215546Sopenharmony_ci const struct util_format_description *d2) 352bf215546Sopenharmony_ci{ 353bf215546Sopenharmony_ci int i; 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci if (d1->layout != d2->layout || 356bf215546Sopenharmony_ci d1->nr_channels != d2->nr_channels || 357bf215546Sopenharmony_ci d1->is_array != d2->is_array) 358bf215546Sopenharmony_ci return false; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci for (i = 0; i < d1->nr_channels; i++) { 361bf215546Sopenharmony_ci if (d1->channel[i].size != d2->channel[i].size) 362bf215546Sopenharmony_ci return false; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci if (d1->swizzle[i] <= PIPE_SWIZZLE_W && 365bf215546Sopenharmony_ci d2->swizzle[i] <= PIPE_SWIZZLE_W && 366bf215546Sopenharmony_ci d1->swizzle[i] != d2->swizzle[i]) 367bf215546Sopenharmony_ci return false; 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci return true; 371bf215546Sopenharmony_ci} 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_cistatic struct pipe_resource * 374bf215546Sopenharmony_cicreate_texture(struct pipe_screen *screen, enum pipe_format format, 375bf215546Sopenharmony_ci unsigned nr_samples, unsigned nr_storage_samples, 376bf215546Sopenharmony_ci unsigned width, unsigned height, unsigned depth) 377bf215546Sopenharmony_ci{ 378bf215546Sopenharmony_ci struct pipe_resource templ; 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 381bf215546Sopenharmony_ci templ.format = format; 382bf215546Sopenharmony_ci templ.width0 = width; 383bf215546Sopenharmony_ci templ.height0 = height; 384bf215546Sopenharmony_ci templ.depth0 = 1; 385bf215546Sopenharmony_ci templ.array_size = depth; 386bf215546Sopenharmony_ci templ.nr_samples = nr_samples; 387bf215546Sopenharmony_ci templ.nr_storage_samples = nr_storage_samples; 388bf215546Sopenharmony_ci templ.usage = PIPE_USAGE_DEFAULT; 389bf215546Sopenharmony_ci templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci if (depth > 1) 392bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D_ARRAY; 393bf215546Sopenharmony_ci else 394bf215546Sopenharmony_ci templ.target = PIPE_TEXTURE_2D; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci return screen->resource_create(screen, &templ); 397bf215546Sopenharmony_ci} 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci/** 400bf215546Sopenharmony_ci * Handle complex format conversions using 2 blits with a temporary texture 401bf215546Sopenharmony_ci * in between, e.g. blitting from B10G10R10A2 to G16R16. 402bf215546Sopenharmony_ci * 403bf215546Sopenharmony_ci * This example is implemented this way: 404bf215546Sopenharmony_ci * 1) First, blit from B10G10R10A2 to R10G10B10A2, which is canonical, so it 405bf215546Sopenharmony_ci * can be reinterpreted as a different canonical format of the same bpp, 406bf215546Sopenharmony_ci * such as R16G16. This blit only swaps R and B 10-bit components. 407bf215546Sopenharmony_ci * 2) Finally, blit the result, which is R10G10B10A2, as R16G16 to G16R16. 408bf215546Sopenharmony_ci * This blit only swaps R and G 16-bit components. 409bf215546Sopenharmony_ci */ 410bf215546Sopenharmony_cistatic bool 411bf215546Sopenharmony_cihandle_complex_copy(struct pipe_context *pipe, 412bf215546Sopenharmony_ci struct pipe_resource *dst, 413bf215546Sopenharmony_ci unsigned dst_level, 414bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 415bf215546Sopenharmony_ci struct pipe_resource *src, 416bf215546Sopenharmony_ci unsigned src_level, 417bf215546Sopenharmony_ci const struct pipe_box *src_box, 418bf215546Sopenharmony_ci enum pipe_format noncanon_format, 419bf215546Sopenharmony_ci enum pipe_format canon_format) 420bf215546Sopenharmony_ci{ 421bf215546Sopenharmony_ci struct pipe_box temp_box; 422bf215546Sopenharmony_ci struct pipe_resource *temp = NULL; 423bf215546Sopenharmony_ci const struct util_format_description *src_desc, *dst_desc; 424bf215546Sopenharmony_ci const struct util_format_description *canon_desc, *noncanon_desc; 425bf215546Sopenharmony_ci bool src_is_canon; 426bf215546Sopenharmony_ci bool src_is_noncanon; 427bf215546Sopenharmony_ci bool dst_is_canon; 428bf215546Sopenharmony_ci bool dst_is_noncanon; 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci src_desc = util_format_description(src->format); 431bf215546Sopenharmony_ci dst_desc = util_format_description(dst->format); 432bf215546Sopenharmony_ci canon_desc = util_format_description(canon_format); 433bf215546Sopenharmony_ci noncanon_desc = util_format_description(noncanon_format); 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci src_is_canon = same_size_and_swizzle(src_desc, canon_desc); 436bf215546Sopenharmony_ci dst_is_canon = same_size_and_swizzle(dst_desc, canon_desc); 437bf215546Sopenharmony_ci src_is_noncanon = same_size_and_swizzle(src_desc, noncanon_desc); 438bf215546Sopenharmony_ci dst_is_noncanon = same_size_and_swizzle(dst_desc, noncanon_desc); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci if (src_is_noncanon) { 441bf215546Sopenharmony_ci /* Simple case - only types differ (e.g. UNORM and UINT). */ 442bf215546Sopenharmony_ci if (dst_is_noncanon) { 443bf215546Sopenharmony_ci blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src, 444bf215546Sopenharmony_ci noncanon_format, src_level, src_box); 445bf215546Sopenharmony_ci return true; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci /* Simple case - only types and swizzles differ. */ 449bf215546Sopenharmony_ci if (dst_is_canon) { 450bf215546Sopenharmony_ci blit(pipe, dst, canon_format, dst_level, dstx, dsty, dstz, src, 451bf215546Sopenharmony_ci noncanon_format, src_level, src_box); 452bf215546Sopenharmony_ci return true; 453bf215546Sopenharmony_ci } 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci /* Use the temporary texture. Src is converted to a canonical format, 456bf215546Sopenharmony_ci * then proceed the generic swizzled_copy. 457bf215546Sopenharmony_ci */ 458bf215546Sopenharmony_ci temp = create_texture(pipe->screen, canon_format, src->nr_samples, 459bf215546Sopenharmony_ci src->nr_storage_samples, src_box->width, 460bf215546Sopenharmony_ci src_box->height, src_box->depth); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth, 463bf215546Sopenharmony_ci &temp_box); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci blit(pipe, temp, canon_format, 0, 0, 0, 0, src, noncanon_format, 466bf215546Sopenharmony_ci src_level, src_box); 467bf215546Sopenharmony_ci swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, temp, 0, 468bf215546Sopenharmony_ci &temp_box); 469bf215546Sopenharmony_ci pipe_resource_reference(&temp, NULL); 470bf215546Sopenharmony_ci return true; 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (dst_is_noncanon) { 474bf215546Sopenharmony_ci /* Simple case - only types and swizzles differ. */ 475bf215546Sopenharmony_ci if (src_is_canon) { 476bf215546Sopenharmony_ci blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src, 477bf215546Sopenharmony_ci canon_format, src_level, src_box); 478bf215546Sopenharmony_ci return true; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci /* Use the temporary texture. First, use the generic copy, but use 482bf215546Sopenharmony_ci * a canonical format in the destination. Then convert */ 483bf215546Sopenharmony_ci temp = create_texture(pipe->screen, canon_format, dst->nr_samples, 484bf215546Sopenharmony_ci dst->nr_storage_samples, src_box->width, 485bf215546Sopenharmony_ci src_box->height, src_box->depth); 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth, 488bf215546Sopenharmony_ci &temp_box); 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci swizzled_copy(pipe, temp, 0, 0, 0, 0, src, src_level, src_box); 491bf215546Sopenharmony_ci blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, temp, 492bf215546Sopenharmony_ci canon_format, 0, &temp_box); 493bf215546Sopenharmony_ci pipe_resource_reference(&temp, NULL); 494bf215546Sopenharmony_ci return true; 495bf215546Sopenharmony_ci } 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci return false; 498bf215546Sopenharmony_ci} 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_cistatic void 501bf215546Sopenharmony_cicopy_image(struct pipe_context *pipe, 502bf215546Sopenharmony_ci struct pipe_resource *dst, 503bf215546Sopenharmony_ci unsigned dst_level, 504bf215546Sopenharmony_ci unsigned dstx, unsigned dsty, unsigned dstz, 505bf215546Sopenharmony_ci struct pipe_resource *src, 506bf215546Sopenharmony_ci unsigned src_level, 507bf215546Sopenharmony_ci const struct pipe_box *src_box) 508bf215546Sopenharmony_ci{ 509bf215546Sopenharmony_ci if (src->format == dst->format || 510bf215546Sopenharmony_ci util_format_is_compressed(src->format) || 511bf215546Sopenharmony_ci util_format_is_compressed(dst->format)) { 512bf215546Sopenharmony_ci pipe->resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, 513bf215546Sopenharmony_ci src, src_level, src_box); 514bf215546Sopenharmony_ci return; 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2 518bf215546Sopenharmony_ci * as a temporary texture in between. 519bf215546Sopenharmony_ci */ 520bf215546Sopenharmony_ci if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, 521bf215546Sopenharmony_ci src_level, src_box, PIPE_FORMAT_B10G10R10A2_UINT, 522bf215546Sopenharmony_ci PIPE_FORMAT_R10G10B10A2_UINT)) 523bf215546Sopenharmony_ci return; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture 526bf215546Sopenharmony_ci * in between. 527bf215546Sopenharmony_ci */ 528bf215546Sopenharmony_ci if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, 529bf215546Sopenharmony_ci src_level, src_box, PIPE_FORMAT_G8R8_UNORM, 530bf215546Sopenharmony_ci PIPE_FORMAT_R8G8_UNORM)) 531bf215546Sopenharmony_ci return; 532bf215546Sopenharmony_ci 533bf215546Sopenharmony_ci /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture 534bf215546Sopenharmony_ci * in between. 535bf215546Sopenharmony_ci */ 536bf215546Sopenharmony_ci if (handle_complex_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, 537bf215546Sopenharmony_ci src_level, src_box, PIPE_FORMAT_G16R16_UNORM, 538bf215546Sopenharmony_ci PIPE_FORMAT_R16G16_UNORM)) 539bf215546Sopenharmony_ci return; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci /* Only allow non-identity swizzling on RGBA8 formats. */ 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci /* Simple copy, memcpy with swizzling, no format conversion. */ 544bf215546Sopenharmony_ci swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, 545bf215546Sopenharmony_ci src_box); 546bf215546Sopenharmony_ci} 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_cistatic void 549bf215546Sopenharmony_cifallback_copy_image(struct st_context *st, 550bf215546Sopenharmony_ci struct gl_texture_image *dst_image, 551bf215546Sopenharmony_ci struct pipe_resource *dst_res, 552bf215546Sopenharmony_ci int dst_x, int dst_y, int dst_z, 553bf215546Sopenharmony_ci struct gl_texture_image *src_image, 554bf215546Sopenharmony_ci struct pipe_resource *src_res, 555bf215546Sopenharmony_ci int src_x, int src_y, int src_z, 556bf215546Sopenharmony_ci int src_w, int src_h) 557bf215546Sopenharmony_ci{ 558bf215546Sopenharmony_ci uint8_t *dst, *src; 559bf215546Sopenharmony_ci int dst_stride, src_stride; 560bf215546Sopenharmony_ci struct pipe_transfer *dst_transfer, *src_transfer; 561bf215546Sopenharmony_ci unsigned line_bytes; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci bool dst_is_compressed = dst_image && _mesa_is_format_compressed(dst_image->TexFormat); 564bf215546Sopenharmony_ci bool src_is_compressed = src_image && _mesa_is_format_compressed(src_image->TexFormat); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci unsigned dst_blk_w = 1, dst_blk_h = 1, src_blk_w = 1, src_blk_h = 1; 567bf215546Sopenharmony_ci if (dst_image) 568bf215546Sopenharmony_ci _mesa_get_format_block_size(dst_image->TexFormat, &dst_blk_w, &dst_blk_h); 569bf215546Sopenharmony_ci if (src_image) 570bf215546Sopenharmony_ci _mesa_get_format_block_size(src_image->TexFormat, &src_blk_w, &src_blk_h); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci unsigned dst_w = src_w; 573bf215546Sopenharmony_ci unsigned dst_h = src_h; 574bf215546Sopenharmony_ci unsigned lines = src_h; 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci if (src_is_compressed && !dst_is_compressed) { 577bf215546Sopenharmony_ci dst_w = DIV_ROUND_UP(dst_w, src_blk_w); 578bf215546Sopenharmony_ci dst_h = DIV_ROUND_UP(dst_h, src_blk_h); 579bf215546Sopenharmony_ci } else if (!src_is_compressed && dst_is_compressed) { 580bf215546Sopenharmony_ci dst_w *= dst_blk_w; 581bf215546Sopenharmony_ci dst_h *= dst_blk_h; 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci if (src_is_compressed) { 584bf215546Sopenharmony_ci lines = DIV_ROUND_UP(lines, src_blk_h); 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci if (src_image) 588bf215546Sopenharmony_ci line_bytes = _mesa_format_row_stride(src_image->TexFormat, src_w); 589bf215546Sopenharmony_ci else 590bf215546Sopenharmony_ci line_bytes = _mesa_format_row_stride(dst_image->TexFormat, dst_w); 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci if (dst_image) { 593bf215546Sopenharmony_ci st_MapTextureImage( 594bf215546Sopenharmony_ci st->ctx, dst_image, dst_z, 595bf215546Sopenharmony_ci dst_x, dst_y, dst_w, dst_h, 596bf215546Sopenharmony_ci GL_MAP_WRITE_BIT, &dst, &dst_stride); 597bf215546Sopenharmony_ci } else { 598bf215546Sopenharmony_ci dst = pipe_texture_map(st->pipe, dst_res, 0, dst_z, 599bf215546Sopenharmony_ci PIPE_MAP_WRITE, 600bf215546Sopenharmony_ci dst_x, dst_y, dst_w, dst_h, 601bf215546Sopenharmony_ci &dst_transfer); 602bf215546Sopenharmony_ci dst_stride = dst_transfer->stride; 603bf215546Sopenharmony_ci } 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci if (src_image) { 606bf215546Sopenharmony_ci st_MapTextureImage( 607bf215546Sopenharmony_ci st->ctx, src_image, src_z, 608bf215546Sopenharmony_ci src_x, src_y, src_w, src_h, 609bf215546Sopenharmony_ci GL_MAP_READ_BIT, &src, &src_stride); 610bf215546Sopenharmony_ci } else { 611bf215546Sopenharmony_ci src = pipe_texture_map(st->pipe, src_res, 0, src_z, 612bf215546Sopenharmony_ci PIPE_MAP_READ, 613bf215546Sopenharmony_ci src_x, src_y, src_w, src_h, 614bf215546Sopenharmony_ci &src_transfer); 615bf215546Sopenharmony_ci src_stride = src_transfer->stride; 616bf215546Sopenharmony_ci } 617bf215546Sopenharmony_ci 618bf215546Sopenharmony_ci for (int y = 0; y < lines; y++) { 619bf215546Sopenharmony_ci memcpy(dst, src, line_bytes); 620bf215546Sopenharmony_ci dst += dst_stride; 621bf215546Sopenharmony_ci src += src_stride; 622bf215546Sopenharmony_ci } 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci if (dst_image) { 625bf215546Sopenharmony_ci st_UnmapTextureImage(st->ctx, dst_image, dst_z); 626bf215546Sopenharmony_ci } else { 627bf215546Sopenharmony_ci pipe_texture_unmap(st->pipe, dst_transfer); 628bf215546Sopenharmony_ci } 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_ci if (src_image) { 631bf215546Sopenharmony_ci st_UnmapTextureImage(st->ctx, src_image, src_z); 632bf215546Sopenharmony_ci } else { 633bf215546Sopenharmony_ci pipe_texture_unmap(st->pipe, src_transfer); 634bf215546Sopenharmony_ci } 635bf215546Sopenharmony_ci} 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_civoid 638bf215546Sopenharmony_cist_CopyImageSubData(struct gl_context *ctx, 639bf215546Sopenharmony_ci struct gl_texture_image *src_image, 640bf215546Sopenharmony_ci struct gl_renderbuffer *src_renderbuffer, 641bf215546Sopenharmony_ci int src_x, int src_y, int src_z, 642bf215546Sopenharmony_ci struct gl_texture_image *dst_image, 643bf215546Sopenharmony_ci struct gl_renderbuffer *dst_renderbuffer, 644bf215546Sopenharmony_ci int dst_x, int dst_y, int dst_z, 645bf215546Sopenharmony_ci int src_width, int src_height) 646bf215546Sopenharmony_ci{ 647bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 648bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 649bf215546Sopenharmony_ci struct pipe_resource *src_res, *dst_res; 650bf215546Sopenharmony_ci struct pipe_box box; 651bf215546Sopenharmony_ci int src_level, dst_level; 652bf215546Sopenharmony_ci int orig_src_z = src_z, orig_dst_z = dst_z; 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 655bf215546Sopenharmony_ci st_invalidate_readpix_cache(st); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci if (src_image) { 658bf215546Sopenharmony_ci struct gl_texture_image *src = src_image; 659bf215546Sopenharmony_ci struct gl_texture_object *stObj = src_image->TexObject; 660bf215546Sopenharmony_ci src_res = src->pt; 661bf215546Sopenharmony_ci src_level = stObj->pt != src_res ? 0 : src_image->Level; 662bf215546Sopenharmony_ci src_z += src_image->Face; 663bf215546Sopenharmony_ci if (src_image->TexObject->Immutable) { 664bf215546Sopenharmony_ci src_level += src_image->TexObject->Attrib.MinLevel; 665bf215546Sopenharmony_ci src_z += src_image->TexObject->Attrib.MinLayer; 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci } else { 668bf215546Sopenharmony_ci src_res = src_renderbuffer->texture; 669bf215546Sopenharmony_ci src_level = 0; 670bf215546Sopenharmony_ci } 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci if (dst_image) { 673bf215546Sopenharmony_ci struct gl_texture_image *dst = dst_image; 674bf215546Sopenharmony_ci struct gl_texture_object *stObj = dst_image->TexObject; 675bf215546Sopenharmony_ci dst_res = dst->pt; 676bf215546Sopenharmony_ci dst_level = stObj->pt != dst_res ? 0 : dst_image->Level; 677bf215546Sopenharmony_ci dst_z += dst_image->Face; 678bf215546Sopenharmony_ci if (dst_image->TexObject->Immutable) { 679bf215546Sopenharmony_ci dst_level += dst_image->TexObject->Attrib.MinLevel; 680bf215546Sopenharmony_ci dst_z += dst_image->TexObject->Attrib.MinLayer; 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci } else { 683bf215546Sopenharmony_ci dst_res = dst_renderbuffer->texture; 684bf215546Sopenharmony_ci dst_level = 0; 685bf215546Sopenharmony_ci } 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci u_box_2d_zslice(src_x, src_y, src_z, src_width, src_height, &box); 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci if ((src_image && st_compressed_format_fallback(st, src_image->TexFormat)) || 690bf215546Sopenharmony_ci (dst_image && st_compressed_format_fallback(st, dst_image->TexFormat))) { 691bf215546Sopenharmony_ci fallback_copy_image(st, dst_image, dst_res, dst_x, dst_y, orig_dst_z, 692bf215546Sopenharmony_ci src_image, src_res, src_x, src_y, orig_src_z, 693bf215546Sopenharmony_ci src_width, src_height); 694bf215546Sopenharmony_ci } else { 695bf215546Sopenharmony_ci copy_image(pipe, dst_res, dst_level, dst_x, dst_y, dst_z, 696bf215546Sopenharmony_ci src_res, src_level, &box); 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci} 699