diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index 4a3f62ac133..51d16aa19f7 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -138,10 +138,10 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc) { struct etna_resource *rsc = etna_resource(prsc); - if (rsc->external) { - if (etna_resource_older(etna_resource(rsc->external), rsc)) { - etna_copy_resource(pctx, rsc->external, prsc, 0, 0); - etna_resource(rsc->external)->seqno = rsc->seqno; + if (rsc->render) { + if (etna_resource_older(rsc, etna_resource(rsc->render))) { + etna_copy_resource(pctx, prsc, rsc->render, 0, 0); + rsc->seqno = etna_resource(rsc->render)->seqno; } } else if (etna_resource_needs_flush(rsc)) { etna_copy_resource(pctx, prsc, prsc, 0, 0); diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 6cd5eca2930..2e55421360b 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -472,12 +472,7 @@ etna_resource_create_modifiers(struct pipe_screen *pscreen, static void etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc) { - struct etna_resource *res = etna_resource(prsc); - - if (res->external) - etna_resource(res->external)->seqno++; - else - res->seqno++; + etna_resource(prsc)->seqno++; } static void @@ -501,7 +496,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc) renderonly_scanout_destroy(rsc->scanout, etna_screen(pscreen)->ro); pipe_resource_reference(&rsc->texture, NULL); - pipe_resource_reference(&rsc->external, NULL); + pipe_resource_reference(&rsc->render, NULL); for (unsigned i = 0; i < ETNA_NUM_LOD; i++) FREE(rsc->levels[i].patch_offsets); @@ -587,29 +582,6 @@ etna_resource_from_handle(struct pipe_screen *pscreen, if (!rsc->pending_ctx) goto fail; - if (rsc->layout == ETNA_LAYOUT_LINEAR) { - /* - * Both sampler and pixel pipes can't handle linear, create a compatible - * base resource, where we can attach the imported buffer as an external - * resource. - */ - struct pipe_resource tiled_templat = *tmpl; - - /* - * Remove BIND_SCANOUT to avoid recursion, as etna_resource_create uses - * this function to import the scanout buffer and get a tiled resource. - */ - tiled_templat.bind &= ~PIPE_BIND_SCANOUT; - - ptiled = etna_resource_create(pscreen, &tiled_templat); - if (!ptiled) - goto fail; - - etna_resource(ptiled)->external = prsc; - - return ptiled; - } - return prsc; fail: @@ -630,13 +602,6 @@ etna_resource_get_handle(struct pipe_screen *pscreen, /* Scanout is always attached to the base resource */ struct renderonly_scanout *scanout = rsc->scanout; - /* - * External resources are preferred, so a import->export chain of - * render/sampler incompatible buffers yield the same handle. - */ - if (rsc->external) - rsc = etna_resource(rsc->external); - handle->stride = rsc->levels[0].stride; handle->offset = rsc->levels[0].offset; handle->modifier = layout_to_modifier(rsc->layout); diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h index 5beb8454afc..1c253006471 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h @@ -84,13 +84,10 @@ struct etna_resource { struct etna_resource_level levels[ETNA_NUM_LOD]; - /* When we are rendering to a texture, we need a differently tiled resource */ + /* for when TE doesn't support the base layout */ struct pipe_resource *texture; - /* - * If imported resources have an render/sampler incompatible tiling, we keep - * them as an external resource, which is blitted as needed. - */ - struct pipe_resource *external; + /* for when PE doesn't support the base layout */ + struct pipe_resource *render; enum etna_resource_status status; diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c index c629aab6494..79922f26647 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -108,14 +108,19 @@ etna_set_constant_buffer(struct pipe_context *pctx, } static void -etna_update_render_resource(struct pipe_context *pctx, struct pipe_resource *pres) +etna_update_render_resource(struct pipe_context *pctx, struct etna_resource *base) { - struct etna_resource *res = etna_resource(pres); + struct etna_resource *to = base, *from = base; - if (res->texture && etna_resource_older(res, etna_resource(res->texture))) { - /* The render buffer is older than the texture buffer. Copy it over. */ - etna_copy_resource(pctx, pres, res->texture, 0, pres->last_level); - res->seqno = etna_resource(res->texture)->seqno; + if (base->texture && etna_resource_newer(etna_resource(base->texture), base)) + from = etna_resource(base->texture); + + if (base->render) + to = etna_resource(base->render); + + if ((to != from) && etna_resource_older(to, from)) { + etna_copy_resource(pctx, &to->base, &from->base, 0, base->base.last_level); + to->seqno = from->seqno; } } @@ -138,7 +143,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ - etna_update_render_resource(pctx, cbuf->base.texture); + etna_update_render_resource(pctx, etna_resource(cbuf->prsc)); cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(translate_rs_format(cbuf->base.format)) | @@ -215,7 +220,7 @@ etna_set_framebuffer_state(struct pipe_context *pctx, struct etna_surface *zsbuf = etna_surface(sv->zsbuf); struct etna_resource *res = etna_resource(zsbuf->base.texture); - etna_update_render_resource(pctx, zsbuf->base.texture); + etna_update_render_resource(pctx, etna_resource(zsbuf->prsc)); assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.c b/src/gallium/drivers/etnaviv/etnaviv_surface.c index 44295738008..d93519db6df 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_surface.c +++ b/src/gallium/drivers/etnaviv/etnaviv_surface.c @@ -37,12 +37,47 @@ #include "hw/common.xml.h" +#include "drm-uapi/drm_fourcc.h" + +static struct etna_resource * +etna_render_handle_incompatible(struct pipe_context *pctx, struct pipe_resource *prsc) +{ + struct etna_context *ctx = etna_context(pctx); + struct etna_resource *res = etna_resource(prsc); + bool need_multitiled = ctx->specs.pixel_pipes > 1 && !ctx->specs.single_buffer; + bool want_supertiled = ctx->specs.can_supertile; + + /* Resource is compatible if it is tiled and has multi tiling when required + * TODO: LINEAR_PE feature means render to linear is possible ? + */ + if (res->layout != ETNA_LAYOUT_LINEAR && + (!need_multitiled || (res->layout & ETNA_LAYOUT_BIT_MULTI))) + return res; + + if (!res->render) { + struct pipe_resource templat = *prsc; + unsigned layout = ETNA_LAYOUT_TILED; + if (need_multitiled) + layout |= ETNA_LAYOUT_BIT_MULTI; + if (want_supertiled) + layout |= ETNA_LAYOUT_BIT_SUPER; + + templat.bind &= (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLENDABLE); + res->render = + etna_resource_alloc(pctx->screen, layout, + DRM_FORMAT_MOD_LINEAR, &templat); + assert(res->render); + } + return etna_resource(res->render); +} + static struct pipe_surface * etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_surface *templat) { struct etna_context *ctx = etna_context(pctx); - struct etna_resource *rsc = etna_resource(prsc); + struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc); struct etna_surface *surf = CALLOC_STRUCT(etna_surface); if (!surf) @@ -57,6 +92,7 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc, pipe_reference_init(&surf->base.reference, 1); pipe_resource_reference(&surf->base.texture, &rsc->base); + pipe_resource_reference(&surf->prsc, prsc); /* Allocate a TS for the resource if there isn't one yet, * and it is allowed by the hw (width is a multiple of 16). @@ -148,6 +184,7 @@ static void etna_surface_destroy(struct pipe_context *pctx, struct pipe_surface *psurf) { pipe_resource_reference(&psurf->texture, NULL); + pipe_resource_reference(&etna_surface(psurf)->prsc, NULL); FREE(psurf); } diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.h b/src/gallium/drivers/etnaviv/etnaviv_surface.h index e8cfd209af4..fef85f521e5 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_surface.h +++ b/src/gallium/drivers/etnaviv/etnaviv_surface.h @@ -41,6 +41,8 @@ struct etna_surface { struct etna_resource_level *level; struct etna_reloc reloc[ETNA_MAX_PIXELPIPES]; struct etna_reloc ts_reloc; + /* keep pointer to original resource (for when a render compatible resource is used) */ + struct pipe_resource *prsc; }; static inline struct etna_surface * diff --git a/src/gallium/drivers/etnaviv/etnaviv_texture.c b/src/gallium/drivers/etnaviv/etnaviv_texture.c index a38fd1c4a57..748d3ff3e6f 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_texture.c +++ b/src/gallium/drivers/etnaviv/etnaviv_texture.c @@ -147,8 +147,8 @@ etna_update_sampler_source(struct pipe_sampler_view *view, int num) struct etna_context *ctx = etna_context(view->context); bool enable_sampler_ts = false; - if (base->external && etna_resource_newer(etna_resource(base->external), base)) - from = etna_resource(base->external); + if (base->render && etna_resource_newer(etna_resource(base->render), base)) + from = etna_resource(base->render); if (base->texture) to = etna_resource(base->texture);