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;
{
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_TRANSFER_DEPTH_ONLY, box,
+ &trans->trans);
+ if (!trans->ptr)
+ goto fail;
+
+ trans->ptr2 = helper->vtbl->transfer_map(pctx, prsc, level,
+ usage | PIPE_TRANSFER_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_TRANSFER_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);
+ }
+}