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_fbo.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/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(enum pipe_format format) 58{ 59 const struct util_format_description *desc = 60 util_format_description(format); 61 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); 66 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); 76 77 return PIPE_FORMAT_NONE; 78 } 79 80#define RETURN_FOR_SWIZZLE1(x, format) \ 81 if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \ 82 return format 83 84#define RETURN_FOR_SWIZZLE2(x, y, format) \ 85 if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \ 86 desc->swizzle[1] == PIPE_SWIZZLE_##y) \ 87 return format 88 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) \ 93 return format 94 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) \ 100 return format 101 102 /* Array formats. */ 103 if (desc->is_array) { 104 switch (desc->nr_channels) { 105 case 1: 106 switch (desc->channel[0].size) { 107 case 8: 108 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R8_UINT); 109 break; 110 111 case 16: 112 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R16_UINT); 113 break; 114 115 case 32: 116 RETURN_FOR_SWIZZLE1(X, PIPE_FORMAT_R32_UINT); 117 break; 118 } 119 break; 120 121 case 2: 122 switch (desc->channel[0].size) { 123 case 8: 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. 126 */ 127 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R8G8_UNORM); 128 RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G8R8_UNORM); 129 break; 130 131 case 16: 132 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R16G16_UNORM); 133 RETURN_FOR_SWIZZLE2(Y, X, PIPE_FORMAT_G16R16_UNORM); 134 break; 135 136 case 32: 137 RETURN_FOR_SWIZZLE2(X, Y, PIPE_FORMAT_R32G32_UINT); 138 break; 139 } 140 break; 141 142 case 3: 143 switch (desc->channel[0].size) { 144 case 8: 145 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R8G8B8_UINT); 146 break; 147 148 case 16: 149 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R16G16B16_UINT); 150 break; 151 152 case 32: 153 RETURN_FOR_SWIZZLE3(X, Y, Z, PIPE_FORMAT_R32G32B32_UINT); 154 break; 155 } 156 break; 157 158 case 4: 159 switch (desc->channel[0].size) { 160 case 8: 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); 169 break; 170 171 case 16: 172 RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R16G16B16A16_UINT); 173 RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R16G16B16A16_UINT); 174 break; 175 176 case 32: 177 RETURN_FOR_SWIZZLE4(X, Y, Z, W, PIPE_FORMAT_R32G32B32A32_UINT); 178 RETURN_FOR_SWIZZLE4(X, Y, Z, 1, PIPE_FORMAT_R32G32B32A32_UINT); 179 break; 180 } 181 } 182 183 assert(!"unknown array format"); 184 return PIPE_FORMAT_NONE; 185 } 186 187 assert(!"unknown packed format"); 188 return PIPE_FORMAT_NONE; 189} 190 191/** 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. 194 */ 195static bool 196has_identity_swizzle(const struct util_format_description *desc) 197{ 198 int i; 199 200 for (i = 0; i < desc->nr_channels; i++) 201 if (desc->swizzle[i] != PIPE_SWIZZLE_X + i) 202 return false; 203 204 return true; 205} 206 207/** 208 * Return a canonical format for the given bits and channel size. 209 */ 210static enum pipe_format 211canonical_format_from_bits(unsigned bits, unsigned channel_size) 212{ 213 switch (bits) { 214 case 8: 215 if (channel_size == 8) 216 return get_canonical_format(PIPE_FORMAT_R8_UINT); 217 break; 218 219 case 16: 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); 224 break; 225 226 case 32: 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); 233 break; 234 235 case 64: 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); 240 break; 241 242 case 128: 243 if (channel_size == 32) 244 return get_canonical_format(PIPE_FORMAT_R32G32B32A32_UINT); 245 break; 246 } 247 248 assert(!"impossible format"); 249 return PIPE_FORMAT_NONE; 250} 251 252static void 253blit(struct pipe_context *pipe, 254 struct pipe_resource *dst, 255 enum pipe_format dst_format, 256 unsigned dst_level, 257 unsigned dstx, unsigned dsty, unsigned dstz, 258 struct pipe_resource *src, 259 enum pipe_format src_format, 260 unsigned src_level, 261 const struct pipe_box *src_box) 262{ 263 struct pipe_blit_info blit = {{0}}; 264 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; 276 277 pipe->blit(pipe, &blit); 278} 279 280static void 281swizzled_copy(struct pipe_context *pipe, 282 struct pipe_resource *dst, 283 unsigned dst_level, 284 unsigned dstx, unsigned dsty, unsigned dstz, 285 struct pipe_resource *src, 286 unsigned src_level, 287 const struct pipe_box *src_box) 288{ 289 const struct util_format_description *src_desc, *dst_desc; 290 unsigned bits; 291 enum pipe_format blit_src_format, blit_dst_format; 292 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. 298 */ 299 blit_src_format = get_canonical_format(src->format); 300 blit_dst_format = get_canonical_format(dst->format); 301 302 assert(blit_src_format != PIPE_FORMAT_NONE); 303 assert(blit_dst_format != PIPE_FORMAT_NONE); 304 305 src_desc = util_format_description(blit_src_format); 306 dst_desc = util_format_description(blit_dst_format); 307 308 assert(src_desc->block.bits == dst_desc->block.bits); 309 bits = src_desc->block.bits; 310 311 if (dst_desc->channel[0].size == src_desc->channel[0].size) { 312 /* Only the swizzle is different, which means we can just blit, 313 * e.g. RGBA -> BGRA. 314 */ 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 319 */ 320 blit_src_format = 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 326 */ 327 blit_dst_format = 328 canonical_format_from_bits(bits, src_desc->channel[0].size); 329 } else { 330 assert(!"This should have been handled by handle_complex_copy."); 331 return; 332 } 333 334 blit(pipe, dst, blit_dst_format, dst_level, dstx, dsty, dstz, 335 src, blit_src_format, src_level, src_box); 336} 337 338static bool 339same_size_and_swizzle(const struct util_format_description *d1, 340 const struct util_format_description *d2) 341{ 342 int i; 343 344 if (d1->layout != d2->layout || 345 d1->nr_channels != d2->nr_channels || 346 d1->is_array != d2->is_array) 347 return false; 348 349 for (i = 0; i < d1->nr_channels; i++) { 350 if (d1->channel[i].size != d2->channel[i].size) 351 return false; 352 353 if (d1->swizzle[i] <= PIPE_SWIZZLE_W && 354 d2->swizzle[i] <= PIPE_SWIZZLE_W && 355 d1->swizzle[i] != d2->swizzle[i]) 356 return false; 357 } 358 359 return true; 360} 361 362static struct pipe_resource * 363create_texture(struct pipe_screen *screen, enum pipe_format format, 364 unsigned nr_samples, unsigned nr_storage_samples, 365 unsigned width, unsigned height, unsigned depth) 366{ 367 struct pipe_resource templ; 368 369 memset(&templ, 0, sizeof(templ)); 370 templ.format = format; 371 templ.width0 = width; 372 templ.height0 = height; 373 templ.depth0 = 1; 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; 379 380 if (depth > 1) 381 templ.target = PIPE_TEXTURE_2D_ARRAY; 382 else 383 templ.target = PIPE_TEXTURE_2D; 384 385 return screen->resource_create(screen, &templ); 386} 387 388/** 389 * Handle complex format conversions using 2 blits with a temporary texture 390 * in between, e.g. blitting from B10G10R10A2 to G16R16. 391 * 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. 398 */ 399static bool 400handle_complex_copy(struct pipe_context *pipe, 401 struct pipe_resource *dst, 402 unsigned dst_level, 403 unsigned dstx, unsigned dsty, unsigned dstz, 404 struct pipe_resource *src, 405 unsigned src_level, 406 const struct pipe_box *src_box, 407 enum pipe_format noncanon_format, 408 enum pipe_format canon_format) 409{ 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; 414 bool src_is_canon; 415 bool src_is_noncanon; 416 bool dst_is_canon; 417 bool dst_is_noncanon; 418 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); 423 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); 428 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); 434 return true; 435 } 436 437 /* Simple case - only types and swizzles differ. */ 438 if (dst_is_canon) { 439 blit(pipe, dst, canon_format, dst_level, dstx, dsty, dstz, src, 440 noncanon_format, src_level, src_box); 441 return true; 442 } 443 444 /* Use the temporary texture. Src is converted to a canonical format, 445 * then proceed the generic swizzled_copy. 446 */ 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); 450 451 u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth, 452 &temp_box); 453 454 blit(pipe, temp, canon_format, 0, 0, 0, 0, src, noncanon_format, 455 src_level, src_box); 456 swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, temp, 0, 457 &temp_box); 458 pipe_resource_reference(&temp, NULL); 459 return true; 460 } 461 462 if (dst_is_noncanon) { 463 /* Simple case - only types and swizzles differ. */ 464 if (src_is_canon) { 465 blit(pipe, dst, noncanon_format, dst_level, dstx, dsty, dstz, src, 466 canon_format, src_level, src_box); 467 return true; 468 } 469 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); 475 476 u_box_3d(0, 0, 0, src_box->width, src_box->height, src_box->depth, 477 &temp_box); 478 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); 483 return true; 484 } 485 486 return false; 487} 488 489static void 490copy_image(struct pipe_context *pipe, 491 struct pipe_resource *dst, 492 unsigned dst_level, 493 unsigned dstx, unsigned dsty, unsigned dstz, 494 struct pipe_resource *src, 495 unsigned src_level, 496 const struct pipe_box *src_box) 497{ 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); 503 return; 504 } 505 506 /* Copying to/from B10G10R10*2 needs 2 blits with R10G10B10A2 507 * as a temporary texture in between. 508 */ 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)) 512 return; 513 514 /* Copying to/from G8R8 needs 2 blits with R8G8 as a temporary texture 515 * in between. 516 */ 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)) 520 return; 521 522 /* Copying to/from G16R16 needs 2 blits with R16G16 as a temporary texture 523 * in between. 524 */ 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)) 528 return; 529 530 /* Only allow non-identity swizzling on RGBA8 formats. */ 531 532 /* Simple copy, memcpy with swizzling, no format conversion. */ 533 swizzled_copy(pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, 534 src_box); 535} 536 537static void 538fallback_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) 546{ 547 uint8_t *dst, *src; 548 int dst_stride, src_stride; 549 struct pipe_transfer *dst_transfer, *src_transfer; 550 unsigned line_bytes; 551 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); 554 555 unsigned dst_blk_w = 1, dst_blk_h = 1, src_blk_w = 1, src_blk_h = 1; 556 if (dst_image) 557 _mesa_get_format_block_size(dst_image->TexFormat, &dst_blk_w, &dst_blk_h); 558 if (src_image) 559 _mesa_get_format_block_size(src_image->TexFormat, &src_blk_w, &src_blk_h); 560 561 unsigned dst_w = src_w; 562 unsigned dst_h = src_h; 563 unsigned lines = src_h; 564 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) { 569 dst_w *= dst_blk_w; 570 dst_h *= dst_blk_h; 571 } 572 if (src_is_compressed) { 573 lines = DIV_ROUND_UP(lines, src_blk_h); 574 } 575 576 if (src_image) 577 line_bytes = _mesa_format_row_stride(src_image->TexFormat, src_w); 578 else 579 line_bytes = _mesa_format_row_stride(dst_image->TexFormat, dst_w); 580 581 if (dst_image) { 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); 586 } else { 587 dst = pipe_transfer_map(st->pipe, dst_res, 0, dst_z, 588 PIPE_TRANSFER_WRITE, 589 dst_x, dst_y, dst_w, dst_h, 590 &dst_transfer); 591 dst_stride = dst_transfer->stride; 592 } 593 594 if (src_image) { 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); 599 } else { 600 src = pipe_transfer_map(st->pipe, src_res, 0, src_z, 601 PIPE_TRANSFER_READ, 602 src_x, src_y, src_w, src_h, 603 &src_transfer); 604 src_stride = src_transfer->stride; 605 } 606 607 for (int y = 0; y < lines; y++) { 608 memcpy(dst, src, line_bytes); 609 dst += dst_stride; 610 src += src_stride; 611 } 612 613 if (dst_image) { 614 st->ctx->Driver.UnmapTextureImage(st->ctx, dst_image, dst_z); 615 } else { 616 pipe_transfer_unmap(st->pipe, dst_transfer); 617 } 618 619 if (src_image) { 620 st->ctx->Driver.UnmapTextureImage(st->ctx, src_image, src_z); 621 } else { 622 pipe_transfer_unmap(st->pipe, src_transfer); 623 } 624} 625 626static void 627st_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) 635{ 636 struct st_context *st = st_context(ctx); 637 struct pipe_context *pipe = st->pipe; 638 struct pipe_resource *src_res, *dst_res; 639 struct pipe_box box; 640 int src_level, dst_level; 641 int orig_src_z = src_z, orig_dst_z = dst_z; 642 643 st_flush_bitmap_cache(st); 644 st_invalidate_readpix_cache(st); 645 646 if (src_image) { 647 struct st_texture_image *src = st_texture_image(src_image); 648 src_res = src->pt; 649 src_level = src_image->Level; 650 src_z += src_image->Face; 651 if (src_image->TexObject->Immutable) { 652 src_level += src_image->TexObject->MinLevel; 653 src_z += src_image->TexObject->MinLayer; 654 } 655 } else { 656 struct st_renderbuffer *src = st_renderbuffer(src_renderbuffer); 657 src_res = src->texture; 658 src_level = 0; 659 } 660 661 if (dst_image) { 662 struct st_texture_image *dst = st_texture_image(dst_image); 663 dst_res = dst->pt; 664 dst_level = dst_image->Level; 665 dst_z += dst_image->Face; 666 if (dst_image->TexObject->Immutable) { 667 dst_level += dst_image->TexObject->MinLevel; 668 dst_z += dst_image->TexObject->MinLayer; 669 } 670 } else { 671 struct st_renderbuffer *dst = st_renderbuffer(dst_renderbuffer); 672 dst_res = dst->texture; 673 dst_level = 0; 674 } 675 676 u_box_2d_zslice(src_x, src_y, src_z, src_width, src_height, &box); 677 678 if ((src_image && st_compressed_format_fallback(st, src_image->TexFormat)) || 679 (dst_image && st_compressed_format_fallback(st, dst_image->TexFormat))) { 680 fallback_copy_image(st, dst_image, dst_res, dst_x, dst_y, orig_dst_z, 681 src_image, src_res, src_x, src_y, orig_src_z, 682 src_width, src_height); 683 } else { 684 copy_image(pipe, dst_res, dst_level, dst_x, dst_y, dst_z, 685 src_res, src_level, &box); 686 } 687} 688 689void 690st_init_copy_image_functions(struct dd_function_table *functions) 691{ 692 functions->CopyImageSubData = st_CopyImageSubData; 693} 694