diff options
Diffstat (limited to 'src/gallium/drivers/etnaviv/etnaviv_resource.c')
-rw-r--r-- | src/gallium/drivers/etnaviv/etnaviv_resource.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 45d5f69169e..4437eedfcab 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -33,6 +33,7 @@ #include "etnaviv_screen.h" #include "etnaviv_translate.h" +#include "util/hash_table.h" #include "util/u_inlines.h" #include "util/u_memory.h" @@ -280,7 +281,6 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, rsc->addressing_mode = mode; pipe_reference_init(&rsc->base.reference, 1); - list_inithead(&rsc->list); size = setup_miptree(rsc, paddingX, paddingY, msaa_xscale, msaa_yscale); @@ -301,6 +301,11 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout, memset(map, 0, size); } + rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + if (!rsc->pending_ctx) + goto free_rsc; + return &rsc->base; free_rsc: @@ -462,8 +467,14 @@ etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc) static void etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) { + struct etna_screen *screen = etna_screen(pscreen); struct etna_resource *rsc = etna_resource(prsc); + mtx_lock(&screen->lock); + _mesa_set_remove_key(screen->used_resources, rsc); + _mesa_set_destroy(rsc->pending_ctx, NULL); + mtx_unlock(&screen->lock); + if (rsc->bo) etna_bo_del(rsc->bo); @@ -473,8 +484,6 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) if (rsc->scanout) renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro); - list_delinit(&rsc->list); - pipe_resource_reference(&rsc->texture, NULL); pipe_resource_reference(&rsc->external, NULL); @@ -511,7 +520,6 @@ etna_resource_from_handle(struct pipe_screen *pscreen, *prsc = *tmpl; pipe_reference_init(&prsc->reference, 1); - list_inithead(&rsc->list); prsc->screen = pscreen; rsc->bo = etna_screen_bo_from_handle(pscreen, handle, &level->stride); @@ -558,6 +566,11 @@ etna_resource_from_handle(struct pipe_screen *pscreen, goto fail; } + rsc->pending_ctx = _mesa_set_create(NULL, _mesa_hash_pointer, + _mesa_key_pointer_equal); + if (!rsc->pending_ctx) + goto fail; + if (rsc->layout == ETNA_LAYOUT_LINEAR) { /* * Both sampler and pixel pipes can't handle linear, create a compatible @@ -632,20 +645,39 @@ void etna_resource_used(struct etna_context *ctx, struct pipe_resource *prsc, enum etna_resource_status status) { + struct etna_screen *screen = ctx->screen; + struct set_entry *entry; struct etna_resource *rsc; if (!prsc) return; rsc = etna_resource(prsc); + + mtx_lock(&screen->lock); + + /* + * if we are pending read or write by any other context or + * if reading a resource pending a write, then + * flush all the contexts to maintain coherency + */ + if (((status & ETNA_PENDING_WRITE) && rsc->status) || + ((status & ETNA_PENDING_READ) && (rsc->status & ETNA_PENDING_WRITE))) { + set_foreach(rsc->pending_ctx, entry) { + struct etna_context *extctx = (struct etna_context *)entry->key; + struct pipe_context *pctx = &extctx->base; + + pctx->flush(pctx, NULL, 0); + } + rsc->status = 0; + } + rsc->status |= status; - /* TODO resources can actually be shared across contexts, - * so I'm not sure a single list-head will do the trick? */ - debug_assert((rsc->pending_ctx == ctx) || !rsc->pending_ctx); - list_delinit(&rsc->list); - list_addtail(&rsc->list, &ctx->used_resources); - rsc->pending_ctx = ctx; + _mesa_set_add(screen->used_resources, rsc); + _mesa_set_add(rsc->pending_ctx, ctx); + + mtx_unlock(&screen->lock); } bool |