#include "util/u_memory.h"
#include "util/u_blitter.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_debug.h"
#include "lima_resource.h"
#include "lima_bo.h"
#include "lima_util.h"
-#include "lima_tiling.h"
+#include "pan_tiling.h"
static struct pipe_resource *
lima_resource_create_scanout(struct pipe_screen *pscreen,
res->levels[level].width = aligned_width;
res->levels[level].stride = stride;
res->levels[level].offset = size;
+ res->levels[level].layer_stride = util_format_get_stride(pres->format, align(width, 16)) * align(height, 16);
/* The start address of each level <= 10 must be 64-aligned
* in order to be able to pass the addresses
int count)
{
struct lima_screen *screen = lima_screen(pscreen);
- bool should_tile = false;
+ bool should_tile = lima_debug & LIMA_DEBUG_NO_TILING ? false : true;
unsigned width, height;
bool should_align_dimensions;
+ bool has_user_modifiers = true;
+
+ if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)
+ has_user_modifiers = false;
/* VBOs/PBOs are untiled (and 1 height). */
if (templat->target == PIPE_BUFFER)
if (templat->bind & (PIPE_BIND_LINEAR | PIPE_BIND_SCANOUT))
should_tile = false;
- /* if linear buffer is not allowed, alloc fail */
- if (!should_tile && !drm_find_modifier(DRM_FORMAT_MOD_LINEAR, modifiers, count))
- return NULL;
+ /* If there's no user modifiers and buffer is shared we use linear */
+ 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))
+ should_tile = false;
if (should_tile || (templat->bind & PIPE_BIND_RENDER_TARGET) ||
(templat->bind & PIPE_BIND_DEPTH_STENCIL)) {
lima_resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *templat)
{
- static const uint64_t modifiers[] = {
- DRM_FORMAT_MOD_LINEAR,
- };
- return _lima_resource_create_with_modifiers(pscreen, templat, modifiers, ARRAY_SIZE(modifiers));
+ const uint64_t mod = DRM_FORMAT_MOD_INVALID;
+
+ return _lima_resource_create_with_modifiers(pscreen, templat, &mod, 1);
}
static struct pipe_resource *
struct lima_resource *res = lima_resource(pres);
if (res->bo)
- lima_bo_free(res->bo);
+ lima_bo_unreference(res->bo);
if (res->scanout)
renderonly_scanout_destroy(res->scanout, screen->ro);
+ if (res->damage.region)
+ FREE(res->damage.region);
+
FREE(res);
}
else
res->levels[0].width = pres->width0;
- handle->modifier = DRM_FORMAT_MOD_LINEAR;
- res->tiled = false;
+ switch (handle->modifier) {
+ case DRM_FORMAT_MOD_LINEAR:
+ res->tiled = false;
+ break;
+ case DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED:
+ res->tiled = true;
+ break;
+ case DRM_FORMAT_MOD_INVALID:
+ /* Modifier wasn't specified and it's shared buffer. We create these
+ * as linear, so disable tiling.
+ */
+ res->tiled = false;
+ break;
+ default:
+ fprintf(stderr, "Attempted to import unsupported modifier 0x%llx\n",
+ (long long)handle->modifier);
+ goto err_out;
+ }
return pres;
return NULL;
}
-static boolean
+static bool
lima_resource_get_handle(struct pipe_screen *pscreen,
struct pipe_context *pctx,
struct pipe_resource *pres,
struct lima_screen *screen = lima_screen(pscreen);
struct lima_resource *res = lima_resource(pres);
- handle->modifier = DRM_FORMAT_MOD_LINEAR;
+ if (res->tiled)
+ handle->modifier = DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED;
+ else
+ handle->modifier = DRM_FORMAT_MOD_LINEAR;
if (handle->type == WINSYS_HANDLE_TYPE_KMS && screen->ro &&
renderonly_get_handle(res->scanout, handle))
- return TRUE;
+ return true;
if (!lima_bo_export(res->bo, handle))
- return FALSE;
+ return false;
handle->stride = res->levels[0].stride;
- return TRUE;
+ return true;
+}
+
+static void
+get_scissor_from_box(struct pipe_scissor_state *s,
+ const struct pipe_box *b, int h)
+{
+ int y = h - (b->y + b->height);
+ /* region in tile unit */
+ s->minx = b->x >> 4;
+ s->miny = y >> 4;
+ s->maxx = (b->x + b->width + 0xf) >> 4;
+ s->maxy = (y + b->height + 0xf) >> 4;
+}
+
+static void
+get_damage_bound_box(struct pipe_resource *pres,
+ const struct pipe_box *rects,
+ unsigned int nrects,
+ struct pipe_scissor_state *bound)
+{
+ struct pipe_box b = rects[0];
+
+ for (int i = 1; i < nrects; i++)
+ u_box_union_2d(&b, &b, rects + i);
+
+ int ret = u_box_clip_2d(&b, &b, pres->width0, pres->height0);
+ if (ret < 0)
+ memset(bound, 0, sizeof(*bound));
+ else
+ get_scissor_from_box(bound, &b, pres->height0);
+}
+
+static void
+lima_resource_set_damage_region(struct pipe_screen *pscreen,
+ struct pipe_resource *pres,
+ unsigned int nrects,
+ const struct pipe_box *rects)
+{
+ struct lima_resource *res = lima_resource(pres);
+ struct lima_damage_region *damage = &res->damage;
+ int i;
+
+ if (damage->region) {
+ FREE(damage->region);
+ damage->region = NULL;
+ damage->num_region = 0;
+ }
+
+ if (!nrects)
+ return;
+
+ /* check full damage
+ *
+ * TODO: currently only check if there is any single damage
+ * region that can cover the full render target; there may
+ * be some accurate way, but a single window size damage
+ * region is most of the case from weston
+ */
+ for (i = 0; i < nrects; i++) {
+ if (rects[i].x <= 0 && rects[i].y <= 0 &&
+ rects[i].x + rects[i].width >= pres->width0 &&
+ rects[i].y + rects[i].height >= pres->height0)
+ return;
+ }
+
+ struct pipe_scissor_state *bound = &damage->bound;
+ get_damage_bound_box(pres, rects, nrects, bound);
+
+ damage->region = CALLOC(nrects, sizeof(*damage->region));
+ if (!damage->region)
+ return;
+
+ for (i = 0; i < nrects; i++)
+ get_scissor_from_box(damage->region + i, rects + i,
+ pres->height0);
+
+ /* is region aligned to tiles? */
+ damage->aligned = true;
+ for (i = 0; i < nrects; i++) {
+ if (rects[i].x & 0xf || rects[i].y & 0xf ||
+ rects[i].width & 0xf || rects[i].height & 0xf) {
+ damage->aligned = false;
+ break;
+ }
+ }
+
+ damage->num_region = nrects;
}
void
screen->base.resource_from_handle = lima_resource_from_handle;
screen->base.resource_destroy = lima_resource_destroy;
screen->base.resource_get_handle = lima_resource_get_handle;
+ screen->base.set_damage_region = lima_resource_set_damage_region;
}
static struct pipe_surface *
surf->tiled_w = align(psurf->width, 16) >> 4;
surf->tiled_h = align(psurf->height, 16) >> 4;
+ surf->reload = true;
+
struct lima_context *ctx = lima_context(pctx);
if (ctx->plb_pp_stream) {
struct lima_ctx_plb_pp_stream_key key = {
struct lima_ctx_plb_pp_stream *s = entry->data;
if (--s->refcnt == 0) {
if (s->bo)
- lima_bo_free(s->bo);
+ lima_bo_unreference(s->bo);
_mesa_hash_table_remove(ctx->plb_pp_stream, entry);
ralloc_free(s);
}
* range, so no need to sync */
if (pres->usage != PIPE_USAGE_STREAM) {
if (usage & PIPE_TRANSFER_READ_WRITE) {
- if (lima_need_flush(ctx, bo, usage & PIPE_TRANSFER_WRITE))
- lima_flush(ctx);
+ lima_flush_submit_accessing_bo(ctx, bo, usage & PIPE_TRANSFER_WRITE);
unsigned op = usage & PIPE_TRANSFER_WRITE ?
LIMA_GEM_WAIT_WRITE : LIMA_GEM_WAIT_READ;
trans->staging = malloc(ptrans->stride * ptrans->box.height * ptrans->box.depth);
- if (usage & PIPE_TRANSFER_READ)
- lima_load_tiled_image(trans->staging, bo->map + res->levels[level].offset,
- &ptrans->box,
- ptrans->stride,
- res->levels[level].stride,
- util_format_get_blocksize(pres->format));
+ if (usage & PIPE_TRANSFER_READ) {
+ unsigned i;
+ for (i = 0; i < ptrans->box.depth; i++)
+ panfrost_load_tiled_image(
+ trans->staging + i * ptrans->stride * ptrans->box.height,
+ bo->map + res->levels[level].offset + (i + box->z) * res->levels[level].layer_stride,
+ ptrans->box.x, ptrans->box.y,
+ ptrans->box.width, ptrans->box.height,
+ ptrans->stride,
+ res->levels[level].stride,
+ pres->format);
+ }
return trans->staging;
} else {
ptrans->stride = res->levels[level].stride;
- ptrans->layer_stride = ptrans->stride * box->height;
+ ptrans->layer_stride = res->levels[level].layer_stride;
return bo->map + res->levels[level].offset +
- box->z * ptrans->layer_stride +
+ box->z * res->levels[level].layer_stride +
box->y / util_format_get_blockheight(pres->format) * ptrans->stride +
box->x / util_format_get_blockwidth(pres->format) *
util_format_get_blocksize(pres->format);
if (trans->staging) {
pres = &res->base;
- if (ptrans->usage & PIPE_TRANSFER_WRITE)
- lima_store_tiled_image(bo->map + res->levels[ptrans->level].offset, trans->staging,
- &ptrans->box,
- res->levels[ptrans->level].stride,
- ptrans->stride,
- util_format_get_blocksize(pres->format));
+ if (ptrans->usage & PIPE_TRANSFER_WRITE) {
+ unsigned i;
+ for (i = 0; i < ptrans->box.depth; i++)
+ panfrost_store_tiled_image(
+ bo->map + res->levels[ptrans->level].offset + (i + ptrans->box.z) * res->levels[ptrans->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);
+ }
free(trans->staging);
}