diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-07-22 10:17:30 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-07-22 10:17:30 +0000 |
commit | ca11beabae33eb59fb981b8adf50b1d47a2a98f0 (patch) | |
tree | 3e4691a396e6e54cd54224a190663d5cf976625b /lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c | |
parent | 27c8a50e8bbde7d28b1fc46d715a4c469e24f2c4 (diff) |
Import Mesa 21.1.5
Diffstat (limited to 'lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c')
-rw-r--r-- | lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c | 137 |
1 files changed, 130 insertions, 7 deletions
diff --git a/lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c b/lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c index 0ba8abdf7..47898e0bd 100644 --- a/lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c +++ b/lib/mesa/src/gallium/auxiliary/util/u_transfer_helper.c @@ -148,8 +148,8 @@ u_transfer_helper_resource_destroy(struct pipe_screen *pscreen, static bool needs_pack(unsigned usage) { - return (usage & PIPE_TRANSFER_READ) && - !(usage & (PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE | PIPE_TRANSFER_DISCARD_RANGE)); + return (usage & PIPE_MAP_READ) && + !(usage & (PIPE_MAP_DISCARD_WHOLE_RESOURCE | PIPE_MAP_DISCARD_RANGE)); } /* In the case of transfer_map of a multi-sample resource, call back into @@ -351,13 +351,14 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, const struct pipe_box *box) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; - struct u_transfer *trans = u_transfer(ptrans); + /* using the function here hits an assert for the deinterleave cases */ + struct u_transfer *trans = (struct u_transfer *)ptrans; enum pipe_format iformat, format = ptrans->resource->format; unsigned width = box->width; unsigned height = box->height; void *src, *dst; - if (!(ptrans->usage & PIPE_TRANSFER_WRITE)) + if (!(ptrans->usage & PIPE_MAP_WRITE)) return; if (trans->ss) { @@ -401,7 +402,7 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, src, ptrans->stride, width, height); - /* fallthru */ + FALLTHROUGH; case PIPE_FORMAT_X32_S8X24_UINT: dst = (uint8_t *)trans->ptr2 + (box->y * trans->trans2->stride) + @@ -418,7 +419,7 @@ flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, util_format_z32_unorm_unpack_z_32unorm(dst, trans->trans->stride, src, ptrans->stride, width, height); - /* fallthru */ + FALLTHROUGH; case PIPE_FORMAT_X24S8_UINT: dst = (uint8_t *)trans->ptr2 + (box->y * trans->trans2->stride) + @@ -494,7 +495,7 @@ u_transfer_helper_transfer_unmap(struct pipe_context *pctx, if (handle_transfer(ptrans->resource)) { struct u_transfer *trans = u_transfer(ptrans); - if (!(ptrans->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) { + if (!(ptrans->usage & PIPE_MAP_FLUSH_EXPLICIT)) { struct pipe_box box; u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); flush_region(pctx, ptrans, &box); @@ -544,3 +545,125 @@ u_transfer_helper_destroy(struct u_transfer_helper *helper) { free(helper); } + + +/* these two functions 'deinterleave' are meant to be used without the corresponding + * resource_create/destroy hooks, as they perform the interleaving on-the-fly + * + * drivers should expect to be passed the same buffer repeatedly with the format changed + * to indicate which component is being mapped + */ +void * +u_transfer_helper_deinterleave_transfer_map(struct pipe_context *pctx, + struct pipe_resource *prsc, + unsigned level, unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **pptrans) +{ + struct u_transfer_helper *helper = pctx->screen->transfer_helper; + struct u_transfer *trans; + struct pipe_transfer *ptrans; + enum pipe_format format = prsc->format; + unsigned width = box->width; + unsigned height = box->height; + + if (!((helper->separate_stencil && util_format_is_depth_and_stencil(format)) || + (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8))) + return helper->vtbl->transfer_map(pctx, prsc, level, usage, box, pptrans); + + debug_assert(box->depth == 1); + + trans = calloc(1, sizeof(*trans)); + if (!trans) + return NULL; + + ptrans = &trans->base; + pipe_resource_reference(&ptrans->resource, prsc); + ptrans->level = level; + ptrans->usage = usage; + ptrans->box = *box; + ptrans->stride = util_format_get_stride(format, box->width); + ptrans->layer_stride = ptrans->stride * box->height; + + trans->staging = malloc(ptrans->layer_stride); + if (!trans->staging) + goto fail; + + trans->ptr = helper->vtbl->transfer_map(pctx, prsc, level, usage | PIPE_MAP_DEPTH_ONLY, box, + &trans->trans); + if (!trans->ptr) + goto fail; + + trans->ptr2 = helper->vtbl->transfer_map(pctx, prsc, level, + usage | PIPE_MAP_STENCIL_ONLY, box, &trans->trans2); + if (needs_pack(usage)) { + switch (prsc->format) { + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + util_format_z32_float_s8x24_uint_pack_z_float(trans->staging, + ptrans->stride, + trans->ptr, + trans->trans->stride, + width, height); + util_format_z32_float_s8x24_uint_pack_s_8uint(trans->staging, + ptrans->stride, + trans->ptr2, + trans->trans2->stride, + width, height); + break; + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + util_format_z24_unorm_s8_uint_pack_separate(trans->staging, + ptrans->stride, + trans->ptr, + trans->trans->stride, + trans->ptr2, + trans->trans2->stride, + width, height); + break; + default: + unreachable("Unexpected format"); + } + } + + *pptrans = ptrans; + return trans->staging; + +fail: + if (trans->trans) + helper->vtbl->transfer_unmap(pctx, trans->trans); + if (trans->trans2) + helper->vtbl->transfer_unmap(pctx, trans->trans2); + pipe_resource_reference(&ptrans->resource, NULL); + free(trans->staging); + free(trans); + return NULL; +} + +void +u_transfer_helper_deinterleave_transfer_unmap(struct pipe_context *pctx, + struct pipe_transfer *ptrans) +{ + struct u_transfer_helper *helper = pctx->screen->transfer_helper; + enum pipe_format format = ptrans->resource->format; + + if ((helper->separate_stencil && util_format_is_depth_and_stencil(format)) || + (format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && helper->separate_z32s8)) { + struct u_transfer *trans = (struct u_transfer *)ptrans; + + if (!(ptrans->usage & PIPE_MAP_FLUSH_EXPLICIT)) { + struct pipe_box box; + u_box_2d(0, 0, ptrans->box.width, ptrans->box.height, &box); + flush_region(pctx, ptrans, &box); + } + + helper->vtbl->transfer_unmap(pctx, trans->trans); + if (trans->trans2) + helper->vtbl->transfer_unmap(pctx, trans->trans2); + + pipe_resource_reference(&ptrans->resource, NULL); + + free(trans->staging); + free(trans); + } else { + helper->vtbl->transfer_unmap(pctx, ptrans); + } +} |