1/* 2 * Copyright © 2017 Red Hat 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include "pipe/p_screen.h" 25 26#include "util/u_box.h" 27#include "util/format/u_format.h" 28#include "util/format/u_format_rgtc.h" 29#include "util/format/u_format_zs.h" 30#include "util/u_inlines.h" 31#include "util/u_transfer_helper.h" 32 33 34struct u_transfer_helper { 35 const struct u_transfer_vtbl *vtbl; 36 bool separate_z32s8; /**< separate z32 and s8 */ 37 bool separate_stencil; /**< separate stencil for all formats */ 38 bool fake_rgtc; 39 bool msaa_map; 40 bool z24_in_z32f; /* the z24 values are stored in a z32 - translate them. */ 41}; 42 43static inline bool need_interleave_path(struct u_transfer_helper *helper, 44 enum pipe_format format) 45{ 46 if (helper->separate_stencil && util_format_is_depth_and_stencil(format)) 47 return true; 48 if (helper->separate_z32s8 && format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT) 49 return true; 50 /* this isn't interleaving, but still needs conversions on that path. */ 51 if (helper->z24_in_z32f && format == PIPE_FORMAT_Z24X8_UNORM) 52 return true; 53 return false; 54} 55 56static inline bool handle_transfer(struct pipe_resource *prsc) 57{ 58 struct u_transfer_helper *helper = prsc->screen->transfer_helper; 59 60 if (helper->vtbl->get_internal_format) { 61 enum pipe_format internal_format = 62 helper->vtbl->get_internal_format(prsc); 63 if (internal_format != prsc->format) 64 return true; 65 } 66 67 if (helper->msaa_map && (prsc->nr_samples > 1)) 68 return true; 69 70 return false; 71} 72 73/* The pipe_transfer ptr could either be the driver's, or u_transfer, 74 * depending on whether we are intervening or not. Check handle_transfer() 75 * before dereferencing. 76 */ 77struct u_transfer { 78 struct pipe_transfer base; 79 /* Note that in case of MSAA resolve for transfer plus z32s8 or fake rgtc 80 * we end up with stacked u_transfer's. The MSAA resolve case doesn't call 81 * helper->vtbl fxns directly, but calls back to pctx->transfer_map()/etc 82 * so the format related handling can work in conjunction with MSAA resolve. 83 */ 84 struct pipe_transfer *trans; /* driver's transfer */ 85 struct pipe_transfer *trans2; /* 2nd transfer for s8 stencil buffer in z32s8 */ 86 void *ptr, *ptr2; /* ptr to trans, and trans2 */ 87 void *staging; /* staging buffer */ 88 struct pipe_resource *ss; /* staging resource for MSAA resolves */ 89}; 90 91static inline struct u_transfer * 92u_transfer(struct pipe_transfer *ptrans) 93{ 94 assert(handle_transfer(ptrans->resource)); 95 return (struct u_transfer *)ptrans; 96} 97 98struct pipe_resource * 99u_transfer_helper_resource_create(struct pipe_screen *pscreen, 100 const struct pipe_resource *templ) 101{ 102 struct u_transfer_helper *helper = pscreen->transfer_helper; 103 enum pipe_format format = templ->format; 104 struct pipe_resource *prsc; 105 106 if ((helper->separate_stencil && util_format_is_depth_and_stencil(format)) || 107 (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)) { 108 struct pipe_resource t = *templ; 109 struct pipe_resource *stencil; 110 111 t.format = util_format_get_depth_only(format); 112 113 prsc = helper->vtbl->resource_create(pscreen, &t); 114 if (!prsc) 115 return NULL; 116 117 prsc->format = format; /* frob the format back to the "external" format */ 118 119 t.format = PIPE_FORMAT_S8_UINT; 120 stencil = helper->vtbl->resource_create(pscreen, &t); 121 122 if (!stencil) { 123 helper->vtbl->resource_destroy(pscreen, prsc); 124 return NULL; 125 } 126 127 helper->vtbl->set_stencil(prsc, stencil); 128 } else if ((util_format_description(format)->layout == UTIL_FORMAT_LAYOUT_RGTC) && 129 helper->fake_rgtc) { 130 struct pipe_resource t = *templ; 131 t.format = PIPE_FORMAT_R8G8B8A8_UNORM; 132 133 prsc = helper->vtbl->resource_create(pscreen, &t); 134 if (!prsc) 135 return NULL; 136 137 prsc->format = format; /* frob the format back to the "external" format */ 138 } else { 139 /* normal case, no special handling: */ 140 prsc = helper->vtbl->resource_create(pscreen, templ); 141 if (!prsc) 142 return NULL; 143 } 144 145 return prsc; 146} 147 148void 149u_transfer_helper_resource_destroy(struct pipe_screen *pscreen, 150 struct pipe_resource *prsc) 151{ 152 struct u_transfer_helper *helper = pscreen->transfer_helper; 153 154 if (helper->vtbl->get_stencil) { 155 struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc); 156 157 pipe_resource_reference(&stencil, NULL); 158 } 159 160 helper->vtbl->resource_destroy(pscreen, prsc); 161} 162 163static bool needs_pack(unsigned usage) 164{ 165 return (usage & PIPE_MAP_READ) && 166 !(usage & (PIPE_MAP_DISCARD_WHOLE_RESOURCE | PIPE_MAP_DISCARD_RANGE)); 167} 168 169/* In the case of transfer_map of a multi-sample resource, call back into 170 * pctx->transfer_map() to map the staging resource, to handle cases of 171 * MSAA + separate_z32s8 or fake_rgtc 172 */ 173static void * 174transfer_map_msaa(struct pipe_context *pctx, 175 struct pipe_resource *prsc, 176 unsigned level, unsigned usage, 177 const struct pipe_box *box, 178 struct pipe_transfer **pptrans) 179{ 180 struct pipe_screen *pscreen = pctx->screen; 181 struct u_transfer *trans = calloc(1, sizeof(*trans)); 182 if (!trans) 183 return NULL; 184 struct pipe_transfer *ptrans = &trans->base; 185 186 pipe_resource_reference(&ptrans->resource, prsc); 187 ptrans->level = level; 188 ptrans->usage = usage; 189 ptrans->box = *box; 190 191 struct pipe_resource tmpl = { 192 .target = prsc->target, 193 .format = prsc->format, 194 .width0 = box->width, 195 .height0 = box->height, 196 .depth0 = 1, 197 .array_size = 1, 198 }; 199 trans->ss = pscreen->resource_create(pscreen, &tmpl); 200 if (!trans->ss) { 201 free(trans); 202 return NULL; 203 } 204 205 if (needs_pack(usage)) { 206 struct pipe_blit_info blit; 207 memset(&blit, 0, sizeof(blit)); 208 209 blit.src.resource = ptrans->resource; 210 blit.src.format = ptrans->resource->format; 211 blit.src.level = ptrans->level; 212 blit.src.box = *box; 213 214 blit.dst.resource = trans->ss; 215 blit.dst.format = trans->ss->format; 216 blit.dst.box.width = box->width; 217 blit.dst.box.height = box->height; 218 blit.dst.box.depth = 1; 219 220 blit.mask = util_format_get_mask(prsc->format); 221 blit.filter = PIPE_TEX_FILTER_NEAREST; 222 223 pctx->blit(pctx, &blit); 224 } 225 226 struct pipe_box map_box = *box; 227 map_box.x = 0; 228 map_box.y = 0; 229 230 void *ss_map = pctx->texture_map(pctx, trans->ss, 0, usage, &map_box, 231 &trans->trans); 232 if (!ss_map) { 233 free(trans); 234 return NULL; 235 } 236 237 ptrans->stride = trans->trans->stride; 238 *pptrans = ptrans; 239 return ss_map; 240} 241 242void * 243u_transfer_helper_transfer_map(struct pipe_context *pctx, 244 struct pipe_resource *prsc, 245 unsigned level, unsigned usage, 246 const struct pipe_box *box, 247 struct pipe_transfer **pptrans) 248{ 249 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 250 struct u_transfer *trans; 251 struct pipe_transfer *ptrans; 252 enum pipe_format format = prsc->format; 253 unsigned width = box->width; 254 unsigned height = box->height; 255 256 if (!handle_transfer(prsc)) 257 return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans); 258 259 if (helper->msaa_map && (prsc->nr_samples > 1)) 260 return transfer_map_msaa(pctx, prsc, level, usage, box, pptrans); 261 262 assert(box->depth == 1); 263 264 trans = calloc(1, sizeof(*trans)); 265 if (!trans) 266 return NULL; 267 268 ptrans = &trans->base; 269 pipe_resource_reference(&ptrans->resource, prsc); 270 ptrans->level = level; 271 ptrans->usage = usage; 272 ptrans->box = *box; 273 ptrans->stride = util_format_get_stride(format, box->width); 274 ptrans->layer_stride = ptrans->stride * box->height; 275 276 trans->staging = malloc(ptrans->layer_stride); 277 if (!trans->staging) 278 goto fail; 279 280 trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage, box, 281 &trans->trans); 282 if (!trans->ptr) 283 goto fail; 284 285 if (util_format_is_depth_and_stencil(prsc->format)) { 286 struct pipe_resource *stencil = helper->vtbl->get_stencil(prsc); 287 trans->ptr2 = helper->vtbl->transfer_map(pctx, stencil, level, 288 usage, box, &trans->trans2); 289 290 if (needs_pack(usage)) { 291 switch (prsc->format) { 292 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 293 util_format_z32_float_s8x24_uint_pack_z_float(trans->staging, 294 ptrans->stride, 295 trans->ptr, 296 trans->trans->stride, 297 width, height); 298 util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging, 299 ptrans->stride, 300 trans->ptr2, 301 trans->trans2->stride, 302 width, height); 303 break; 304 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 305 assert(!helper->z24_in_z32f); 306 util_format_z24_unorm_s8_uint_pack_separate(trans->staging, 307 ptrans->stride, 308 trans->ptr, 309 trans->trans->stride, 310 trans->ptr2, 311 trans->trans2->stride, 312 width, height); 313 break; 314 default: 315 unreachable("Unexpected format"); 316 } 317 } 318 } else if (util_format_description(prsc->format)->layout == UTIL_FORMAT_LAYOUT_RGTC) { 319 if (needs_pack(usage)) { 320 switch (prsc->format) { 321 case PIPE_FORMAT_RGTC1_UNORM: 322 case PIPE_FORMAT_RGTC1_SNORM: 323 case PIPE_FORMAT_LATC1_UNORM: 324 case PIPE_FORMAT_LATC1_SNORM: 325 util_format_rgtc1_unorm_pack_rgba_8unorm(trans->staging, 326 ptrans->stride, 327 trans->ptr, 328 trans->trans->stride, 329 width, height); 330 break; 331 case PIPE_FORMAT_RGTC2_UNORM: 332 case PIPE_FORMAT_RGTC2_SNORM: 333 case PIPE_FORMAT_LATC2_UNORM: 334 case PIPE_FORMAT_LATC2_SNORM: 335 util_format_rgtc2_unorm_pack_rgba_8unorm(trans->staging, 336 ptrans->stride, 337 trans->ptr, 338 trans->trans->stride, 339 width, height); 340 break; 341 default: 342 assert(!"Unexpected format"); 343 break; 344 } 345 } 346 } else { 347 unreachable("bleh"); 348 } 349 350 *pptrans = ptrans; 351 return trans->staging; 352 353fail: 354 if (trans->trans) 355 helper->vtbl->transfer_unmap(pctx, trans->trans); 356 if (trans->trans2) 357 helper->vtbl->transfer_unmap(pctx, trans->trans2); 358 pipe_resource_reference(&ptrans->resource, NULL); 359 free(trans->staging); 360 free(trans); 361 return NULL; 362} 363 364static void 365flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, 366 const struct pipe_box *box) 367{ 368 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 369 /* using the function here hits an assert for the deinterleave cases */ 370 struct u_transfer *trans = (struct u_transfer *)ptrans; 371 enum pipe_format iformat, format = ptrans->resource->format; 372 unsigned width = box->width; 373 unsigned height = box->height; 374 void *src, *dst; 375 376 if (!(ptrans->usage & PIPE_MAP_WRITE)) 377 return; 378 379 if (trans->ss) { 380 struct pipe_blit_info blit; 381 memset(&blit, 0, sizeof(blit)); 382 383 blit.src.resource = trans->ss; 384 blit.src.format = trans->ss->format; 385 blit.src.box = *box; 386 387 blit.dst.resource = ptrans->resource; 388 blit.dst.format = ptrans->resource->format; 389 blit.dst.level = ptrans->level; 390 391 u_box_2d(ptrans->box.x + box->x, 392 ptrans->box.y + box->y, 393 box->width, box->height, 394 &blit.dst.box); 395 396 blit.mask = util_format_get_mask(ptrans->resource->format); 397 blit.filter = PIPE_TEX_FILTER_NEAREST; 398 399 pctx->blit(pctx, &blit); 400 401 return; 402 } 403 404 iformat = helper->vtbl->get_internal_format(ptrans->resource); 405 406 src = (uint8_t *)trans->staging + 407 (box->y * ptrans->stride) + 408 (box->x * util_format_get_blocksize(format)); 409 dst = (uint8_t *)trans->ptr + 410 (box->y * trans->trans->stride) + 411 (box->x * util_format_get_blocksize(iformat)); 412 413 switch (format) { 414 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 415 util_format_z32_float_s8x24_uint_unpack_z_float(dst, 416 trans->trans->stride, 417 src, 418 ptrans->stride, 419 width, height); 420 FALLTHROUGH; 421 case PIPE_FORMAT_X32_S8X24_UINT: 422 dst = (uint8_t *)trans->ptr2 + 423 (box->y * trans->trans2->stride) + 424 (box->x * util_format_get_blocksize(PIPE_FORMAT_S8_UINT)); 425 426 util_format_z32_float_s8x24_uint_unpack_s_8uint(dst, 427 trans->trans2->stride, 428 src, 429 ptrans->stride, 430 width, height); 431 break; 432 case PIPE_FORMAT_Z24X8_UNORM: 433 util_format_z24x8_unorm_unpack_z_float(dst, trans->trans->stride, 434 src, ptrans->stride, 435 width, height); 436 break; 437 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 438 if (helper->z24_in_z32f) { 439 util_format_z24_unorm_s8_uint_unpack_z_float(dst, trans->trans->stride, 440 src, ptrans->stride, 441 width, height); 442 } else { 443 /* just do a strided 32-bit copy for depth; s8 can become garbage x8 */ 444 util_format_z32_unorm_unpack_z_32unorm(dst, trans->trans->stride, 445 src, ptrans->stride, 446 width, height); 447 } 448 FALLTHROUGH; 449 case PIPE_FORMAT_X24S8_UINT: 450 dst = (uint8_t *)trans->ptr2 + 451 (box->y * trans->trans2->stride) + 452 (box->x * util_format_get_blocksize(PIPE_FORMAT_S8_UINT)); 453 454 util_format_z24_unorm_s8_uint_unpack_s_8uint(dst, trans->trans2->stride, 455 src, ptrans->stride, 456 width, height); 457 break; 458 459 case PIPE_FORMAT_RGTC1_UNORM: 460 case PIPE_FORMAT_RGTC1_SNORM: 461 case PIPE_FORMAT_LATC1_UNORM: 462 case PIPE_FORMAT_LATC1_SNORM: 463 util_format_rgtc1_unorm_unpack_rgba_8unorm(dst, 464 trans->trans->stride, 465 src, 466 ptrans->stride, 467 width, height); 468 break; 469 case PIPE_FORMAT_RGTC2_UNORM: 470 case PIPE_FORMAT_RGTC2_SNORM: 471 case PIPE_FORMAT_LATC2_UNORM: 472 case PIPE_FORMAT_LATC2_SNORM: 473 util_format_rgtc2_unorm_unpack_rgba_8unorm(dst, 474 trans->trans->stride, 475 src, 476 ptrans->stride, 477 width, height); 478 break; 479 default: 480 assert(!"Unexpected staging transfer type"); 481 break; 482 } 483} 484 485void 486u_transfer_helper_transfer_flush_region(struct pipe_context *pctx, 487 struct pipe_transfer *ptrans, 488 const struct pipe_box *box) 489{ 490 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 491 492 if (handle_transfer(ptrans->resource)) { 493 struct u_transfer *trans = u_transfer(ptrans); 494 495 /* handle MSAA case, since there could be multiple levels of 496 * wrapped transfer, call pctx->transfer_flush_region() 497 * instead of helper->vtbl->transfer_flush_region() 498 */ 499 if (trans->ss) { 500 pctx->transfer_flush_region(pctx, trans->trans, box); 501 flush_region(pctx, ptrans, box); 502 return; 503 } 504 505 flush_region(pctx, ptrans, box); 506 507 helper->vtbl->transfer_flush_region(pctx, trans->trans, box); 508 if (trans->trans2) 509 helper->vtbl->transfer_flush_region(pctx, trans->trans2, box); 510 511 } else { 512 helper->vtbl->transfer_flush_region(pctx, ptrans, box); 513 } 514} 515 516void 517u_transfer_helper_transfer_unmap(struct pipe_context *pctx, 518 struct pipe_transfer *ptrans) 519{ 520 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 521 522 if (handle_transfer(ptrans->resource)) { 523 struct u_transfer *trans = u_transfer(ptrans); 524 525 if (!(ptrans->usage & PIPE_MAP_FLUSH_EXPLICIT)) { 526 struct pipe_box box; 527 u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); 528 if (trans->ss) 529 pctx->transfer_flush_region(pctx, trans->trans, &box); 530 flush_region(pctx, ptrans, &box); 531 } 532 533 /* in MSAA case, there could be multiple levels of wrapping 534 * so don't call helper->vtbl->transfer_unmap() directly 535 */ 536 if (trans->ss) { 537 pctx->texture_unmap(pctx, trans->trans); 538 pipe_resource_reference(&trans->ss, NULL); 539 } else { 540 helper->vtbl->transfer_unmap(pctx, trans->trans); 541 if (trans->trans2) 542 helper->vtbl->transfer_unmap(pctx, trans->trans2); 543 } 544 545 pipe_resource_reference(&ptrans->resource, NULL); 546 547 free(trans->staging); 548 free(trans); 549 } else { 550 helper->vtbl->transfer_unmap(pctx, ptrans); 551 } 552} 553 554struct u_transfer_helper * 555u_transfer_helper_create(const struct u_transfer_vtbl *vtbl, 556 bool separate_z32s8, 557 bool separate_stencil, 558 bool fake_rgtc, 559 bool msaa_map, 560 bool z24_in_z32f) 561{ 562 struct u_transfer_helper *helper = calloc(1, sizeof(*helper)); 563 564 helper->vtbl = vtbl; 565 helper->separate_z32s8 = separate_z32s8; 566 helper->separate_stencil = separate_stencil; 567 helper->fake_rgtc = fake_rgtc; 568 helper->msaa_map = msaa_map; 569 helper->z24_in_z32f = z24_in_z32f; 570 571 return helper; 572} 573 574void 575u_transfer_helper_destroy(struct u_transfer_helper *helper) 576{ 577 free(helper); 578} 579 580 581/* these two functions 'deinterleave' are meant to be used without the corresponding 582 * resource_create/destroy hooks, as they perform the interleaving on-the-fly 583 * 584 * drivers should expect to be passed the same buffer repeatedly with the format changed 585 * to indicate which component is being mapped 586 */ 587void * 588u_transfer_helper_deinterleave_transfer_map(struct pipe_context *pctx, 589 struct pipe_resource *prsc, 590 unsigned level, unsigned usage, 591 const struct pipe_box *box, 592 struct pipe_transfer **pptrans) 593{ 594 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 595 struct u_transfer *trans; 596 struct pipe_transfer *ptrans; 597 enum pipe_format format = prsc->format; 598 unsigned width = box->width; 599 unsigned height = box->height; 600 601 if (!need_interleave_path(helper, format)) 602 return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans); 603 604 assert(box->depth == 1); 605 606 trans = calloc(1, sizeof(*trans)); 607 if (!trans) 608 return NULL; 609 610 ptrans = &trans->base; 611 pipe_resource_reference(&ptrans->resource, prsc); 612 ptrans->level = level; 613 ptrans->usage = usage; 614 ptrans->box = *box; 615 ptrans->stride = util_format_get_stride(format, box->width); 616 ptrans->layer_stride = ptrans->stride * box->height; 617 618 bool has_stencil = util_format_is_depth_and_stencil(format); 619 620 trans->staging = malloc(ptrans->layer_stride); 621 if (!trans->staging) 622 goto fail; 623 624 trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage | PIPE_MAP_DEPTH_ONLY, box, 625 &trans->trans); 626 if (!trans->ptr) 627 goto fail; 628 629 trans->ptr2 = NULL; 630 if (has_stencil) 631 trans->ptr2 = helper->vtbl->transfer_map(pctx, prsc, level, 632 usage | PIPE_MAP_STENCIL_ONLY, box, &trans->trans2); 633 if (needs_pack(usage)) { 634 switch (prsc->format) { 635 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 636 util_format_z32_float_s8x24_uint_pack_z_float(trans->staging, 637 ptrans->stride, 638 trans->ptr, 639 trans->trans->stride, 640 width, height); 641 util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging, 642 ptrans->stride, 643 trans->ptr2, 644 trans->trans2->stride, 645 width, height); 646 break; 647 case PIPE_FORMAT_Z24_UNORM_S8_UINT: 648 if (helper->z24_in_z32f) { 649 util_format_z24_unorm_s8_uint_pack_separate_z32(trans->staging, 650 ptrans->stride, 651 trans->ptr, 652 trans->trans->stride, 653 trans->ptr2, 654 trans->trans2->stride, 655 width, height); 656 } else { 657 util_format_z24_unorm_s8_uint_pack_separate(trans->staging, 658 ptrans->stride, 659 trans->ptr, 660 trans->trans->stride, 661 trans->ptr2, 662 trans->trans2->stride, 663 width, height); 664 } 665 break; 666 case PIPE_FORMAT_Z24X8_UNORM: 667 assert(helper->z24_in_z32f); 668 util_format_z24x8_unorm_pack_z_float(trans->staging, ptrans->stride, 669 trans->ptr, trans->trans->stride, 670 width, height); 671 break; 672 default: 673 unreachable("Unexpected format"); 674 } 675 } 676 677 *pptrans = ptrans; 678 return trans->staging; 679 680fail: 681 if (trans->trans) 682 helper->vtbl->transfer_unmap(pctx, trans->trans); 683 if (trans->trans2) 684 helper->vtbl->transfer_unmap(pctx, trans->trans2); 685 pipe_resource_reference(&ptrans->resource, NULL); 686 free(trans->staging); 687 free(trans); 688 return NULL; 689} 690 691void 692u_transfer_helper_deinterleave_transfer_unmap(struct pipe_context *pctx, 693 struct pipe_transfer *ptrans) 694{ 695 struct u_transfer_helper *helper = pctx->screen->transfer_helper; 696 enum pipe_format format = ptrans->resource->format; 697 698 if (!need_interleave_path(helper, format)) { 699 helper->vtbl->transfer_unmap(pctx, ptrans); 700 return; 701 } 702 703 struct u_transfer *trans = (struct u_transfer *)ptrans; 704 705 if (!(ptrans->usage & PIPE_MAP_FLUSH_EXPLICIT)) { 706 struct pipe_box box; 707 u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); 708 flush_region(pctx, ptrans, &box); 709 } 710 711 helper->vtbl->transfer_unmap(pctx, trans->trans); 712 if (trans->trans2) 713 helper->vtbl->transfer_unmap(pctx, trans->trans2); 714 715 pipe_resource_reference(&ptrans->resource, NULL); 716 717 free(trans->staging); 718 free(trans); 719} 720