#include "lima_resource.h"
#include "lima_bo.h"
#include "lima_util.h"
+
+#include "pan_minmax_cache.h"
#include "pan_tiling.h"
static struct pipe_resource *
if (!has_user_modifiers && (templat->bind & PIPE_BIND_SHARED))
should_tile = false;
- if (drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
- should_tile = false;
-
if (has_user_modifiers &&
!drm_find_modifier(DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED,
modifiers, count))
struct lima_resource *res = lima_resource(pres);
res->tiled = should_tile;
+ if (templat->bind & PIPE_BIND_INDEX_BUFFER)
+ res->index_cache = CALLOC_STRUCT(panfrost_minmax_cache);
+
debug_printf("%s: pres=%p width=%u height=%u depth=%u target=%d "
"bind=%x usage=%d tile=%d last_level=%d\n", __func__,
pres, pres->width0, pres->height0, pres->depth0,
if (res->damage.region)
FREE(res->damage.region);
+ if (res->index_cache)
+ FREE(res->index_cache);
+
FREE(res);
}
const struct pipe_resource *templat,
struct winsys_handle *handle, unsigned usage)
{
- struct lima_resource *res;
- struct lima_screen *screen = lima_screen(pscreen);
+ if (templat->bind & (PIPE_BIND_SAMPLER_VIEW |
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_DEPTH_STENCIL)) {
+ /* sampler hardware need offset alignment 64, while render hardware
+ * need offset alignment 8, but due to render target may be reloaded
+ * which uses the sampler, set alignment requrement to 64 for all
+ */
+ if (handle->offset & 0x3f) {
+ debug_error("import buffer offset not properly aligned\n");
+ return NULL;
+ }
+ }
- res = CALLOC_STRUCT(lima_resource);
+ struct lima_resource *res = CALLOC_STRUCT(lima_resource);
if (!res)
return NULL;
*pres = *templat;
pres->screen = pscreen;
pipe_reference_init(&pres->reference, 1);
- res->levels[0].offset = 0;
+ res->levels[0].offset = handle->offset;
res->levels[0].stride = handle->stride;
+ struct lima_screen *screen = lima_screen(pscreen);
res->bo = lima_bo_import(screen, handle);
if (!res->bo) {
FREE(res);
return NULL;
}
- /* check alignment for the buffer */
- if (pres->bind & PIPE_BIND_RENDER_TARGET) {
- unsigned width, height, stride, size;
-
- width = align(pres->width0, 16);
- height = align(pres->height0, 16);
- stride = util_format_get_stride(pres->format, width);
- size = util_format_get_2d_size(pres->format, stride, height);
-
- if (res->levels[0].stride != stride || res->bo->size < size) {
- debug_error("import buffer not properly aligned\n");
- goto err_out;
- }
-
- res->levels[0].width = width;
- }
- else
- res->levels[0].width = pres->width0;
-
switch (handle->modifier) {
case DRM_FORMAT_MOD_LINEAR:
res->tiled = false;
goto err_out;
}
+ /* check alignment for the buffer */
+ if (res->tiled ||
+ (pres->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL))) {
+ unsigned width, height, stride, size;
+
+ width = align(pres->width0, 16);
+ height = align(pres->height0, 16);
+ stride = util_format_get_stride(pres->format, width);
+ size = util_format_get_2d_size(pres->format, stride, height);
+
+ if (res->levels[0].stride != stride || res->bo->size < size) {
+ debug_error("import buffer not properly aligned\n");
+ goto err_out;
+ }
+
+ res->levels[0].width = width;
+ }
+ else
+ res->levels[0].width = pres->width0;
+
return pres;
err_out:
surf->tiled_w = align(psurf->width, 16) >> 4;
surf->tiled_h = align(psurf->height, 16) >> 4;
- surf->reload = true;
+ surf->reload = 0;
+ if (util_format_has_stencil(util_format_description(psurf->format)))
+ surf->reload |= PIPE_CLEAR_STENCIL;
+ if (util_format_has_depth(util_format_description(psurf->format)))
+ surf->reload |= PIPE_CLEAR_DEPTH;
+ if (!util_format_is_depth_or_stencil(psurf->format))
+ surf->reload |= PIPE_CLEAR_COLOR0;
return &surf->base;
}
return trans->staging;
} else {
+ unsigned dpw = PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_WRITE |
+ PIPE_TRANSFER_PERSISTENT;
+ if ((usage & dpw) == dpw && res->index_cache)
+ return NULL;
+
ptrans->stride = res->levels[level].stride;
ptrans->layer_stride = res->levels[level].layer_stride;
+ if ((usage & PIPE_TRANSFER_WRITE) && (usage & PIPE_TRANSFER_MAP_DIRECTLY))
+ panfrost_minmax_cache_invalidate(res->index_cache, ptrans);
+
return bo->map + res->levels[level].offset +
box->z * res->levels[level].layer_stride +
box->y / util_format_get_blockheight(pres->format) * ptrans->stride +
}
static void
-lima_transfer_unmap(struct pipe_context *pctx,
- struct pipe_transfer *ptrans)
+lima_transfer_unmap_inner(struct lima_context *ctx,
+ struct pipe_transfer *ptrans)
{
- struct lima_context *ctx = lima_context(pctx);
- struct lima_transfer *trans = lima_transfer(ptrans);
+
struct lima_resource *res = lima_resource(ptrans->resource);
+ struct lima_transfer *trans = lima_transfer(ptrans);
struct lima_bo *bo = res->bo;
struct pipe_resource *pres;
if (trans->staging) {
pres = &res->base;
- if (ptrans->usage & PIPE_TRANSFER_WRITE) {
+ if (trans->base.usage & PIPE_TRANSFER_WRITE) {
unsigned i;
- for (i = 0; i < ptrans->box.depth; i++)
+ for (i = 0; i < trans->base.box.depth; i++)
panfrost_store_tiled_image(
- bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->level].layer_stride,
+ 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,
ptrans->stride,
pres->format);
}
- free(trans->staging);
}
+}
+
+static void
+lima_transfer_unmap(struct pipe_context *pctx,
+ struct pipe_transfer *ptrans)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_transfer *trans = lima_transfer(ptrans);
+ struct lima_resource *res = lima_resource(ptrans->resource);
+
+ lima_transfer_unmap_inner(ctx, ptrans);
+ if (trans->staging)
+ free(trans->staging);
+ panfrost_minmax_cache_invalidate(res->index_cache, ptrans);
pipe_resource_reference(&ptrans->resource, NULL);
slab_free(&ctx->transfer_pool, trans);
}
+static void
+lima_texture_subdata(struct pipe_context *pctx,
+ struct pipe_resource *prsc,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box,
+ const void *data,
+ unsigned stride,
+ unsigned layer_stride)
+{
+ struct lima_context *ctx = lima_context(pctx);
+ struct lima_resource *res = lima_resource(prsc);
+
+ if (!res->tiled) {
+ u_default_texture_subdata(pctx, prsc, level, usage, box,
+ data, stride, layer_stride);
+ return;
+ }
+
+ assert(!(usage & PIPE_TRANSFER_READ));
+
+ struct lima_transfer t = {
+ .base = {
+ .resource = prsc,
+ .usage = PIPE_TRANSFER_WRITE,
+ .level = level,
+ .box = *box,
+ .stride = stride,
+ .layer_stride = layer_stride,
+ },
+ .staging = (void *)data,
+ };
+
+ lima_flush_job_accessing_bo(ctx, res->bo, true);
+ lima_bo_wait(res->bo, LIMA_GEM_WAIT_WRITE, PIPE_TIMEOUT_INFINITE);
+ if (!lima_bo_map(res->bo))
+ return;
+
+ lima_transfer_unmap_inner(ctx, &t.base);
+}
+
void
lima_resource_context_init(struct lima_context *ctx)
{
ctx->base.create_surface = lima_surface_create;
ctx->base.surface_destroy = lima_surface_destroy;
- /* TODO: optimize these functions to read/write data directly
- * from/to target instead of creating a staging memory for tiled
- * buffer indirectly
- */
ctx->base.buffer_subdata = u_default_buffer_subdata;
- ctx->base.texture_subdata = u_default_texture_subdata;
+ ctx->base.texture_subdata = lima_texture_subdata;
+ /* TODO: optimize resource_copy_region to do copy directly
+ * between 2 tiled or tiled and linear resources instead of
+ * using staging buffer.
+ */
ctx->base.resource_copy_region = util_resource_copy_region;
ctx->base.blit = lima_blit;