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