return NULL;
}
+ res->modifier_constant = true;
+
switch (handle->modifier) {
case DRM_FORMAT_MOD_LINEAR:
res->tiled = false;
else
handle->modifier = DRM_FORMAT_MOD_LINEAR;
+ res->modifier_constant = true;
+
if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
renderonly_get_handle(res->scanout, handle))
return true;
}
+static bool
+lima_should_convert_linear(struct lima_resource *res,
+ struct pipe_transfer *ptrans)
+{
+ if (res->modifier_constant)
+ return false;
+
+ /* Overwriting the entire resource indicates streaming, for which
+ * linear layout is most efficient due to the lack of expensive
+ * conversion.
+ *
+ * For now we just switch to linear after a number of complete
+ * overwrites to keep things simple, but we could do better.
+ */
+
+ unsigned depth = res->base.target == PIPE_TEXTURE_3D ?
+ res->base.depth0 : res->base.array_size;
+ bool entire_overwrite =
+ res->base.last_level == 0 &&
+ ptrans->box.width == res->base.width0 &&
+ ptrans->box.height == res->base.height0 &&
+ ptrans->box.depth == depth &&
+ ptrans->box.x == 0 &&
+ ptrans->box.y == 0 &&
+ ptrans->box.z == 0;
+
+ if (entire_overwrite)
+ ++res->full_updates;
+
+ return res->full_updates >= LAYOUT_CONVERT_THRESHOLD;
+}
+
static void
lima_transfer_unmap_inner(struct lima_context *ctx,
struct pipe_transfer *ptrans)
pres = &res->base;
if (trans->base.usage & PIPE_MAP_WRITE) {
unsigned i;
- for (i = 0; i < trans->base.box.depth; i++)
- panfrost_store_tiled_image(
- bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
- trans->staging + i * ptrans->stride * ptrans->box.height,
- ptrans->box.x, ptrans->box.y,
- ptrans->box.width, ptrans->box.height,
- res->levels[ptrans->level].stride,
- ptrans->stride,
- pres->format);
+ if (lima_should_convert_linear(res, ptrans)) {
+ /* It's safe to re-use the same BO since tiled BO always has
+ * aligned dimensions */
+ for (i = 0; i < trans->base.box.depth; i++) {
+ util_copy_rect(bo->map + res->levels[0].offset +
+ (i + trans->base.box.z) * res->levels[0].stride,
+ res->base.format,
+ res->levels[0].stride,
+ 0, 0,
+ ptrans->box.width,
+ ptrans->box.height,
+ trans->staging + i * ptrans->stride * ptrans->box.height,
+ ptrans->stride,
+ 0, 0);
+ }
+ res->tiled = false;
+ res->modifier_constant = true;
+ /* Update texture descriptor */
+ ctx->dirty |= LIMA_CONTEXT_DIRTY_TEXTURES;
+ } else {
+ for (i = 0; i < trans->base.box.depth; i++)
+ panfrost_store_tiled_image(
+ bo->map + res->levels[trans->base.level].offset + (i + trans->base.box.z) * res->levels[trans->base.level].layer_stride,
+ trans->staging + i * ptrans->stride * ptrans->box.height,
+ ptrans->box.x, ptrans->box.y,
+ ptrans->box.width, ptrans->box.height,
+ res->levels[ptrans->level].stride,
+ ptrans->stride,
+ pres->format);
+ }
}
}
}