#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_screen *screen = ctx->screen;
+ struct etna_resource *res = etna_resource(prsc);
+ bool need_multitiled = screen->specs.pixel_pipes > 1 && !screen->specs.single_buffer;
+ bool want_supertiled = screen->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_screen *screen = ctx->screen;
+ struct etna_resource *rsc = etna_render_handle_incompatible(pctx, prsc);
struct etna_surface *surf = CALLOC_STRUCT(etna_surface);
if (!surf)
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).
* indicate the tile status module bypasses the memory
* offset and MMU. */
- if (VIV_FEATURE(ctx->screen, chipFeatures, FAST_CLEAR) &&
- VIV_FEATURE(ctx->screen, chipMinorFeatures0, MC20) &&
- !DBG_ENABLED(ETNA_DBG_NO_TS) && !rsc->ts_bo &&
+ if (VIV_FEATURE(screen, chipFeatures, FAST_CLEAR) &&
+ VIV_FEATURE(screen, chipMinorFeatures0, MC20) &&
+ !rsc->ts_bo &&
+ /* needs to be RS/BLT compatible for transfer_map/unmap */
(rsc->levels[level].padded_width & ETNA_RS_WIDTH_MASK) == 0 &&
- (rsc->levels[level].padded_height & ETNA_RS_HEIGHT_MASK) == 0) {
+ (rsc->levels[level].padded_height & ETNA_RS_HEIGHT_MASK) == 0 &&
+ etna_resource_hw_tileable(screen->specs.use_blt, prsc)) {
etna_screen_resource_alloc_ts(pctx->screen, rsc);
}
surf->base.texture = &rsc->base;
- surf->base.format = rsc->base.format;
+ surf->base.format = templat->format;
surf->base.width = rsc->levels[level].width;
surf->base.height = rsc->levels[level].height;
surf->base.writable = templat->writable; /* what is this for anyway */
struct etna_resource_level *lev = &rsc->levels[level];
/* Setup template relocations for this surface */
- for (unsigned pipe = 0; pipe < ctx->specs.pixel_pipes; ++pipe) {
+ for (unsigned pipe = 0; pipe < screen->specs.pixel_pipes; ++pipe) {
surf->reloc[pipe].bo = rsc->bo;
surf->reloc[pipe].offset = surf->surf.offset;
surf->reloc[pipe].flags = 0;
surf->ts_reloc.offset = surf->surf.ts_offset;
surf->ts_reloc.flags = 0;
- /* This (ab)uses the RS as a plain buffer memset().
- * Currently uses a fixed row size of 64 bytes. Some benchmarking with
- * different sizes may be in order. */
- struct etna_bo *ts_bo = etna_resource(surf->base.texture)->ts_bo;
- etna_compile_rs_state(ctx, &surf->clear_command, &(struct rs_state) {
- .source_format = RS_FORMAT_A8R8G8B8,
- .dest_format = RS_FORMAT_A8R8G8B8,
- .dest = ts_bo,
- .dest_offset = surf->surf.ts_offset,
- .dest_stride = 0x40,
- .dest_tiling = ETNA_LAYOUT_TILED,
- .dither = {0xffffffff, 0xffffffff},
- .width = 16,
- .height = etna_align_up(surf->surf.ts_size / 0x40, 4),
- .clear_value = {ctx->specs.ts_clear_value},
- .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1,
- .clear_bits = 0xffff
- });
+ if (!screen->specs.use_blt) {
+ /* This (ab)uses the RS as a plain buffer memset().
+ * Currently uses a fixed row size of 64 bytes. Some benchmarking with
+ * different sizes may be in order. */
+ struct etna_bo *ts_bo = etna_resource(surf->base.texture)->ts_bo;
+ etna_compile_rs_state(ctx, &surf->clear_command, &(struct rs_state) {
+ .source_format = RS_FORMAT_A8R8G8B8,
+ .dest_format = RS_FORMAT_A8R8G8B8,
+ .dest = ts_bo,
+ .dest_offset = surf->surf.ts_offset,
+ .dest_stride = 0x40,
+ .dest_tiling = ETNA_LAYOUT_TILED,
+ .dither = {0xffffffff, 0xffffffff},
+ .width = 16,
+ .height = etna_align_up(surf->surf.ts_size / 0x40, 4),
+ .clear_value = {screen->specs.ts_clear_value},
+ .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1,
+ .clear_bits = 0xffff
+ });
+ }
} else {
- etna_rs_gen_clear_surface(ctx, surf, surf->level->clear_value);
+ if (!screen->specs.use_blt)
+ etna_rs_gen_clear_surface(ctx, surf, surf->level->clear_value);
}
return &surf->base;
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);
}