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