Home | History | Annotate | Download | only in etnaviv
      1 /*
      2  * Copyright (c) 2012-2015 Etnaviv Project
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sub license,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the
     12  * next paragraph) shall be included in all copies or substantial portions
     13  * of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *    Wladimir J. van der Laan <laanwj (at) gmail.com>
     25  */
     26 
     27 #include "etnaviv_clear_blit.h"
     28 
     29 #include "hw/common.xml.h"
     30 
     31 #include "etnaviv_context.h"
     32 #include "etnaviv_emit.h"
     33 #include "etnaviv_emit.h"
     34 #include "etnaviv_format.h"
     35 #include "etnaviv_resource.h"
     36 #include "etnaviv_surface.h"
     37 #include "etnaviv_translate.h"
     38 
     39 #include "pipe/p_defines.h"
     40 #include "pipe/p_state.h"
     41 #include "util/u_blitter.h"
     42 #include "util/u_inlines.h"
     43 #include "util/u_memory.h"
     44 #include "util/u_surface.h"
     45 
     46 /* Save current state for blitter operation */
     47 static void
     48 etna_blit_save_state(struct etna_context *ctx)
     49 {
     50    util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer.vb);
     51    util_blitter_save_vertex_elements(ctx->blitter, ctx->vertex_elements);
     52    util_blitter_save_vertex_shader(ctx->blitter, ctx->vs);
     53    util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
     54    util_blitter_save_viewport(ctx->blitter, &ctx->viewport_s);
     55    util_blitter_save_scissor(ctx->blitter, &ctx->scissor_s);
     56    util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
     57    util_blitter_save_blend(ctx->blitter, ctx->blend);
     58    util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
     59    util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref_s);
     60    util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
     61    util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer_s);
     62    util_blitter_save_fragment_sampler_states(ctx->blitter,
     63          ctx->num_fragment_samplers, (void **)ctx->sampler);
     64    util_blitter_save_fragment_sampler_views(ctx->blitter,
     65          ctx->num_fragment_sampler_views, ctx->sampler_view);
     66 }
     67 
     68 /* Generate clear command for a surface (non-fast clear case) */
     69 void
     70 etna_rs_gen_clear_surface(struct etna_context *ctx, struct etna_surface *surf,
     71                           uint32_t clear_value)
     72 {
     73    struct etna_resource *dst = etna_resource(surf->base.texture);
     74    uint32_t format = translate_rs_format(surf->base.format);
     75 
     76    if (format == ETNA_NO_MATCH) {
     77       BUG("etna_rs_gen_clear_surface: Unhandled clear fmt %s", util_format_name(surf->base.format));
     78       format = RS_FORMAT_A8R8G8B8;
     79       assert(0);
     80    }
     81 
     82    /* use tiled clear if width is multiple of 16 */
     83    bool tiled_clear = (surf->surf.padded_width & ETNA_RS_WIDTH_MASK) == 0 &&
     84                       (surf->surf.padded_height & ETNA_RS_HEIGHT_MASK) == 0;
     85 
     86    etna_compile_rs_state( ctx, &surf->clear_command, &(struct rs_state) {
     87       .source_format = format,
     88       .dest_format = format,
     89       .dest = dst->bo,
     90       .dest_offset = surf->surf.offset,
     91       .dest_stride = surf->surf.stride,
     92       .dest_padded_height = surf->surf.padded_height,
     93       .dest_tiling = tiled_clear ? dst->layout : ETNA_LAYOUT_LINEAR,
     94       .dither = {0xffffffff, 0xffffffff},
     95       .width = surf->surf.padded_width, /* These must be padded to 16x4 if !LINEAR, otherwise RS will hang */
     96       .height = surf->surf.padded_height,
     97       .clear_value = {clear_value},
     98       .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_ENABLED1,
     99       .clear_bits = 0xffff
    100    });
    101 }
    102 
    103 static void
    104 etna_blit_clear_color(struct pipe_context *pctx, struct pipe_surface *dst,
    105                       const union pipe_color_union *color)
    106 {
    107    struct etna_context *ctx = etna_context(pctx);
    108    struct etna_surface *surf = etna_surface(dst);
    109    uint32_t new_clear_value = translate_clear_color(surf->base.format, color);
    110 
    111    if (surf->surf.ts_size) { /* TS: use precompiled clear command */
    112       ctx->framebuffer.TS_COLOR_CLEAR_VALUE = new_clear_value;
    113 
    114       if (!DBG_ENABLED(ETNA_DBG_NO_AUTODISABLE) &&
    115           VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) {
    116          /* Set number of color tiles to be filled */
    117          etna_set_state(ctx->stream, VIVS_TS_COLOR_AUTO_DISABLE_COUNT,
    118                         surf->surf.padded_width * surf->surf.padded_height / 16);
    119          ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_COLOR_AUTO_DISABLE;
    120       }
    121 
    122       ctx->dirty |= ETNA_DIRTY_TS;
    123    } else if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */
    124       /* If clear color changed, re-generate stored command */
    125       etna_rs_gen_clear_surface(ctx, surf, new_clear_value);
    126    }
    127 
    128    etna_submit_rs_state(ctx, &surf->clear_command);
    129    surf->level->clear_value = new_clear_value;
    130    resource_written(ctx, surf->base.texture);
    131    etna_resource(surf->base.texture)->seqno++;
    132 }
    133 
    134 static void
    135 etna_blit_clear_zs(struct pipe_context *pctx, struct pipe_surface *dst,
    136                    unsigned buffers, double depth, unsigned stencil)
    137 {
    138    struct etna_context *ctx = etna_context(pctx);
    139    struct etna_surface *surf = etna_surface(dst);
    140    uint32_t new_clear_value = translate_clear_depth_stencil(surf->base.format, depth, stencil);
    141    uint32_t new_clear_bits = 0, clear_bits_depth, clear_bits_stencil;
    142 
    143    /* Get the channels to clear */
    144    switch (surf->base.format) {
    145    case PIPE_FORMAT_Z16_UNORM:
    146       clear_bits_depth = 0xffff;
    147       clear_bits_stencil = 0;
    148       break;
    149    case PIPE_FORMAT_X8Z24_UNORM:
    150    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
    151       clear_bits_depth = 0xeeee;
    152       clear_bits_stencil = 0x1111;
    153       break;
    154    default:
    155       clear_bits_depth = clear_bits_stencil = 0xffff;
    156       break;
    157    }
    158 
    159    if (buffers & PIPE_CLEAR_DEPTH)
    160       new_clear_bits |= clear_bits_depth;
    161    if (buffers & PIPE_CLEAR_STENCIL)
    162       new_clear_bits |= clear_bits_stencil;
    163 
    164    /* FIXME: when tile status is enabled, this becomes more complex as
    165     * we may separately clear the depth from the stencil.  In this case,
    166     * we want to resolve the surface, and avoid using the tile status.
    167     * We may be better off recording the pending clear operation,
    168     * delaying the actual clear to the first use.  This way, we can merge
    169     * consecutive clears together. */
    170    if (surf->surf.ts_size) { /* TS: use precompiled clear command */
    171       /* Set new clear depth value */
    172       ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value;
    173       if (!DBG_ENABLED(ETNA_DBG_NO_AUTODISABLE) &&
    174           VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) {
    175          /* Set number of depth tiles to be filled */
    176          etna_set_state(ctx->stream, VIVS_TS_DEPTH_AUTO_DISABLE_COUNT,
    177                         surf->surf.padded_width * surf->surf.padded_height / 16);
    178          ctx->framebuffer.TS_MEM_CONFIG |= VIVS_TS_MEM_CONFIG_DEPTH_AUTO_DISABLE;
    179       }
    180 
    181       ctx->dirty |= ETNA_DIRTY_TS;
    182    } else {
    183       if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */
    184          /* If clear depth value changed, re-generate stored command */
    185          etna_rs_gen_clear_surface(ctx, surf, new_clear_value);
    186       }
    187       /* Update the channels to be cleared */
    188       etna_modify_rs_clearbits(&surf->clear_command, new_clear_bits);
    189    }
    190 
    191    etna_submit_rs_state(ctx, &surf->clear_command);
    192    surf->level->clear_value = new_clear_value;
    193    resource_written(ctx, surf->base.texture);
    194    etna_resource(surf->base.texture)->seqno++;
    195 }
    196 
    197 static void
    198 etna_clear(struct pipe_context *pctx, unsigned buffers,
    199            const union pipe_color_union *color, double depth, unsigned stencil)
    200 {
    201    struct etna_context *ctx = etna_context(pctx);
    202 
    203    /* Flush color and depth cache before clearing anything.
    204     * This is especially important when coming from another surface, as
    205     * otherwise it may clear part of the old surface instead. */
    206    etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH);
    207    etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
    208 
    209    /* Preparation: Flush the TS if needed. This must be done after flushing
    210     * color and depth, otherwise it can result in crashes */
    211    bool need_ts_flush = false;
    212    if ((buffers & PIPE_CLEAR_COLOR) && ctx->framebuffer_s.nr_cbufs) {
    213       struct etna_surface *surf = etna_surface(ctx->framebuffer_s.cbufs[0]);
    214       if (surf->surf.ts_size)
    215          need_ts_flush = true;
    216    }
    217    if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL) {
    218       struct etna_surface *surf = etna_surface(ctx->framebuffer_s.zsbuf);
    219 
    220       if (surf->surf.ts_size)
    221          need_ts_flush = true;
    222    }
    223 
    224    if (need_ts_flush)
    225       etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH);
    226 
    227    /* No need to set up the TS here as RS clear operations (in contrast to
    228     * resolve and copy) do not require the TS state.
    229     */
    230    if (buffers & PIPE_CLEAR_COLOR) {
    231       for (int idx = 0; idx < ctx->framebuffer_s.nr_cbufs; ++idx) {
    232          etna_blit_clear_color(pctx, ctx->framebuffer_s.cbufs[idx],
    233                                &color[idx]);
    234       }
    235    }
    236 
    237    /* Flush the color and depth caches before each RS clear operation
    238     * This fixes a hang on GC600. */
    239    if (buffers & PIPE_CLEAR_DEPTHSTENCIL && buffers & PIPE_CLEAR_COLOR)
    240       etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE,
    241                      VIVS_GL_FLUSH_CACHE_COLOR | VIVS_GL_FLUSH_CACHE_DEPTH);
    242 
    243    if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ctx->framebuffer_s.zsbuf != NULL)
    244       etna_blit_clear_zs(pctx, ctx->framebuffer_s.zsbuf, buffers, depth, stencil);
    245 
    246    etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
    247 }
    248 
    249 static void
    250 etna_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst,
    251                          const union pipe_color_union *color, unsigned dstx,
    252                          unsigned dsty, unsigned width, unsigned height,
    253                          bool render_condition_enabled)
    254 {
    255    struct etna_context *ctx = etna_context(pctx);
    256 
    257    /* XXX could fall back to RS when target area is full screen / resolveable
    258     * and no TS. */
    259    etna_blit_save_state(ctx);
    260    util_blitter_clear_render_target(ctx->blitter, dst, color, dstx, dsty, width, height);
    261 }
    262 
    263 static void
    264 etna_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst,
    265                          unsigned clear_flags, double depth, unsigned stencil,
    266                          unsigned dstx, unsigned dsty, unsigned width,
    267                          unsigned height, bool render_condition_enabled)
    268 {
    269    struct etna_context *ctx = etna_context(pctx);
    270 
    271    /* XXX could fall back to RS when target area is full screen / resolveable
    272     * and no TS. */
    273    etna_blit_save_state(ctx);
    274    util_blitter_clear_depth_stencil(ctx->blitter, dst, clear_flags, depth,
    275                                     stencil, dstx, dsty, width, height);
    276 }
    277 
    278 static void
    279 etna_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst,
    280                           unsigned dst_level, unsigned dstx, unsigned dsty,
    281                           unsigned dstz, struct pipe_resource *src,
    282                           unsigned src_level, const struct pipe_box *src_box)
    283 {
    284    struct etna_context *ctx = etna_context(pctx);
    285 
    286    /* The resource must be of the same format. */
    287    assert(src->format == dst->format);
    288    /* Resources with nr_samples > 1 are not allowed. */
    289    assert(src->nr_samples <= 1 && dst->nr_samples <= 1);
    290 
    291    /* XXX we can use the RS as a literal copy engine here
    292     * the only complexity is tiling; the size of the boxes needs to be aligned
    293     * to the tile size
    294     * how to handle the case where a resource is copied from/to a non-aligned
    295     * position?
    296     * from non-aligned: can fall back to rendering-based copy?
    297     * to non-aligned: can fall back to rendering-based copy?
    298     * XXX this goes wrong when source surface is supertiled.
    299     */
    300    if (util_blitter_is_copy_supported(ctx->blitter, dst, src)) {
    301       etna_blit_save_state(ctx);
    302       util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz,
    303                                 src, src_level, src_box);
    304    } else {
    305       util_resource_copy_region(pctx, dst, dst_level, dstx, dsty, dstz, src,
    306                                 src_level, src_box);
    307    }
    308 }
    309 
    310 static bool
    311 etna_manual_blit(struct etna_resource *dst, struct etna_resource_level *dst_lev,
    312                  unsigned int dst_offset, struct etna_resource *src,
    313                  struct etna_resource_level *src_lev, unsigned int src_offset,
    314                  const struct pipe_blit_info *blit_info)
    315 {
    316    void *smap, *srow, *dmap, *drow;
    317    size_t tile_size;
    318 
    319    assert(src->layout == ETNA_LAYOUT_TILED);
    320    assert(dst->layout == ETNA_LAYOUT_TILED);
    321    assert(src->base.nr_samples == 0);
    322    assert(dst->base.nr_samples == 0);
    323 
    324    tile_size = util_format_get_blocksize(blit_info->src.format) * 4 * 4;
    325 
    326    smap = etna_bo_map(src->bo);
    327    if (!smap)
    328       return false;
    329 
    330    dmap = etna_bo_map(dst->bo);
    331    if (!dmap)
    332       return false;
    333 
    334    srow = smap + src_offset;
    335    drow = dmap + dst_offset;
    336 
    337    etna_bo_cpu_prep(src->bo, DRM_ETNA_PREP_READ);
    338    etna_bo_cpu_prep(dst->bo, DRM_ETNA_PREP_WRITE);
    339 
    340    for (int y = 0; y < blit_info->src.box.height; y += 4) {
    341       memcpy(drow, srow, tile_size * blit_info->src.box.width);
    342       srow += src_lev->stride * 4;
    343       drow += dst_lev->stride * 4;
    344    }
    345 
    346    etna_bo_cpu_fini(dst->bo);
    347    etna_bo_cpu_fini(src->bo);
    348 
    349    return true;
    350 }
    351 
    352 static bool
    353 etna_try_rs_blit(struct pipe_context *pctx,
    354                  const struct pipe_blit_info *blit_info)
    355 {
    356    struct etna_context *ctx = etna_context(pctx);
    357    struct etna_resource *src = etna_resource(blit_info->src.resource);
    358    struct etna_resource *dst = etna_resource(blit_info->dst.resource);
    359    struct compiled_rs_state copy_to_screen;
    360    uint32_t ts_mem_config = 0;
    361    int msaa_xscale = 1, msaa_yscale = 1;
    362 
    363    /* Ensure that the level is valid */
    364    assert(blit_info->src.level <= src->base.last_level);
    365    assert(blit_info->dst.level <= dst->base.last_level);
    366 
    367    if (!translate_samples_to_xyscale(src->base.nr_samples, &msaa_xscale, &msaa_yscale, NULL))
    368       return FALSE;
    369 
    370    /* The width/height are in pixels; they do not change as a result of
    371     * multi-sampling. So, when blitting from a 4x multisampled surface
    372     * to a non-multisampled surface, the width and height will be
    373     * identical. As we do not support scaling, reject different sizes. */
    374    if (blit_info->dst.box.width != blit_info->src.box.width ||
    375        blit_info->dst.box.height != blit_info->src.box.height) {
    376       DBG("scaling requested: source %dx%d destination %dx%d",
    377           blit_info->src.box.width, blit_info->src.box.height,
    378           blit_info->dst.box.width, blit_info->dst.box.height);
    379       return FALSE;
    380    }
    381 
    382    /* No masks - RS can't copy specific channels */
    383    unsigned mask = util_format_get_mask(blit_info->dst.format);
    384    if ((blit_info->mask & mask) != mask) {
    385       DBG("sub-mask requested: 0x%02x vs format mask 0x%02x", blit_info->mask, mask);
    386       return FALSE;
    387    }
    388 
    389    unsigned src_format = etna_compatible_rs_format(blit_info->src.format);
    390    unsigned dst_format = etna_compatible_rs_format(blit_info->src.format);
    391    if (translate_rs_format(src_format) == ETNA_NO_MATCH ||
    392        translate_rs_format(dst_format) == ETNA_NO_MATCH ||
    393        blit_info->scissor_enable || blit_info->src.box.x != 0 ||
    394        blit_info->src.box.y != 0 || blit_info->dst.box.x != 0 ||
    395        blit_info->dst.box.y != 0 ||
    396        blit_info->dst.box.depth != blit_info->src.box.depth ||
    397        blit_info->dst.box.depth != 1) {
    398       return FALSE;
    399    }
    400 
    401    /* Ensure that the Z coordinate is sane */
    402    if (dst->base.target != PIPE_TEXTURE_CUBE)
    403       assert(blit_info->dst.box.z == 0);
    404    if (src->base.target != PIPE_TEXTURE_CUBE)
    405       assert(blit_info->src.box.z == 0);
    406 
    407    assert(blit_info->src.box.z < src->base.array_size);
    408    assert(blit_info->dst.box.z < dst->base.array_size);
    409 
    410    struct etna_resource_level *src_lev = &src->levels[blit_info->src.level];
    411    struct etna_resource_level *dst_lev = &dst->levels[blit_info->dst.level];
    412 
    413    /* we may be given coordinates up to the padded width to avoid
    414     * any alignment issues with different tiling formats */
    415    assert((blit_info->src.box.x + blit_info->src.box.width) * msaa_xscale <= src_lev->padded_width);
    416    assert((blit_info->src.box.y + blit_info->src.box.height) * msaa_yscale <= src_lev->padded_height);
    417    assert(blit_info->dst.box.x + blit_info->dst.box.width <= dst_lev->padded_width);
    418    assert(blit_info->dst.box.y + blit_info->dst.box.height <= dst_lev->padded_height);
    419 
    420    unsigned src_offset =
    421       src_lev->offset + blit_info->src.box.z * src_lev->layer_stride;
    422    unsigned dst_offset =
    423       dst_lev->offset + blit_info->dst.box.z * dst_lev->layer_stride;
    424 
    425    if (src_lev->padded_width <= ETNA_RS_WIDTH_MASK ||
    426        dst_lev->padded_width <= ETNA_RS_WIDTH_MASK ||
    427        src_lev->padded_height <= ETNA_RS_HEIGHT_MASK ||
    428        dst_lev->padded_height <= ETNA_RS_HEIGHT_MASK)
    429       goto manual;
    430 
    431    /* If the width is not aligned to the RS width, but is within our
    432     * padding, adjust the width to suite the RS width restriction.
    433     * Note: the RS width/height are converted to source samples here. */
    434    unsigned int width = blit_info->src.box.width * msaa_xscale;
    435    unsigned int height = blit_info->src.box.height * msaa_yscale;
    436    unsigned int w_align = ETNA_RS_WIDTH_MASK + 1;
    437    unsigned int h_align = (ETNA_RS_HEIGHT_MASK + 1) * ctx->specs.pixel_pipes;
    438 
    439    if (width & (w_align - 1) && width >= src_lev->width * msaa_xscale && width >= dst_lev->width)
    440       width = align(width, w_align);
    441 
    442    if (height & (h_align - 1) && height >= src_lev->height * msaa_yscale && height >= dst_lev->height)
    443       height = align(height, h_align);
    444 
    445    /* The padded dimensions are in samples */
    446    if (width > src_lev->padded_width ||
    447        width > dst_lev->padded_width * msaa_xscale ||
    448        height > src_lev->padded_height ||
    449        height > dst_lev->padded_height * msaa_yscale)
    450       goto manual;
    451 
    452    if (src->base.nr_samples > 1) {
    453       uint32_t msaa_format = translate_msaa_format(src_format);
    454       assert(msaa_format != ETNA_NO_MATCH);
    455       ts_mem_config |= VIVS_TS_MEM_CONFIG_MSAA | msaa_format;
    456    }
    457 
    458    uint32_t to_flush = 0;
    459 
    460    if (src->base.bind & PIPE_BIND_RENDER_TARGET)
    461       to_flush |= VIVS_GL_FLUSH_CACHE_COLOR;
    462    if (src->base.bind & PIPE_BIND_DEPTH_STENCIL)
    463       to_flush |= VIVS_GL_FLUSH_CACHE_DEPTH;
    464 
    465    if (to_flush) {
    466       etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, to_flush);
    467       etna_stall(ctx->stream, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
    468    }
    469 
    470    /* Set up color TS to source surface before blit, if needed */
    471    if (src->levels[blit_info->src.level].ts_size) {
    472       struct etna_reloc reloc;
    473       unsigned ts_offset =
    474          src_lev->ts_offset + blit_info->src.box.z * src_lev->ts_layer_stride;
    475 
    476       etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG,
    477                      VIVS_TS_MEM_CONFIG_COLOR_FAST_CLEAR | ts_mem_config);
    478 
    479       memset(&reloc, 0, sizeof(struct etna_reloc));
    480       reloc.bo = src->ts_bo;
    481       reloc.offset = ts_offset;
    482       reloc.flags = ETNA_RELOC_READ;
    483       etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_STATUS_BASE, &reloc);
    484 
    485       memset(&reloc, 0, sizeof(struct etna_reloc));
    486       reloc.bo = src->bo;
    487       reloc.offset = src_offset;
    488       reloc.flags = ETNA_RELOC_READ;
    489       etna_set_state_reloc(ctx->stream, VIVS_TS_COLOR_SURFACE_BASE, &reloc);
    490 
    491       etna_set_state(ctx->stream, VIVS_TS_COLOR_CLEAR_VALUE,
    492                      src->levels[blit_info->src.level].clear_value);
    493    } else {
    494       etna_set_state(ctx->stream, VIVS_TS_MEM_CONFIG, ts_mem_config);
    495    }
    496    ctx->dirty |= ETNA_DIRTY_TS;
    497 
    498    /* Kick off RS here */
    499    etna_compile_rs_state(ctx, &copy_to_screen, &(struct rs_state) {
    500       .source_format = translate_rs_format(src_format),
    501       .source_tiling = src->layout,
    502       .source = src->bo,
    503       .source_offset = src_offset,
    504       .source_stride = src_lev->stride,
    505       .source_padded_height = src_lev->padded_height,
    506       .dest_format = translate_rs_format(dst_format),
    507       .dest_tiling = dst->layout,
    508       .dest = dst->bo,
    509       .dest_offset = dst_offset,
    510       .dest_stride = dst_lev->stride,
    511       .dest_padded_height = dst_lev->padded_height,
    512       .downsample_x = msaa_xscale > 1,
    513       .downsample_y = msaa_yscale > 1,
    514       .swap_rb = translate_rb_src_dst_swap(src->base.format, dst->base.format),
    515       .dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit?
    516       .clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED,
    517       .width = width,
    518       .height = height
    519    });
    520 
    521    etna_submit_rs_state(ctx, &copy_to_screen);
    522    resource_written(ctx, &dst->base);
    523    dst->seqno++;
    524 
    525    return TRUE;
    526 
    527 manual:
    528    if (src->layout == ETNA_LAYOUT_TILED && dst->layout == ETNA_LAYOUT_TILED) {
    529       etna_resource_wait(pctx, dst);
    530       etna_resource_wait(pctx, src);
    531       return etna_manual_blit(dst, dst_lev, dst_offset, src, src_lev, src_offset, blit_info);
    532    }
    533 
    534    return FALSE;
    535 }
    536 
    537 static void
    538 etna_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
    539 {
    540    /* This is a more extended version of resource_copy_region */
    541    /* TODO Some cases can be handled by RS; if not, fall back to rendering or
    542     * even CPU copy block of pixels from info->src to info->dst
    543     * (resource, level, box, format);
    544     * function is used for scaling, flipping in x and y direction (negative
    545     * width/height), format conversion, mask and filter and even a scissor rectangle
    546     *
    547     * What can the RS do for us:
    548     *   convert between tiling formats (layouts)
    549     *   downsample 2x in x and y
    550     *   convert between a limited number of pixel formats
    551     *
    552     * For the rest, fall back to util_blitter
    553     * XXX this goes wrong when source surface is supertiled. */
    554    struct etna_context *ctx = etna_context(pctx);
    555    struct pipe_blit_info info = *blit_info;
    556 
    557    if (info.src.resource->nr_samples > 1 &&
    558        info.dst.resource->nr_samples <= 1 &&
    559        !util_format_is_depth_or_stencil(info.src.resource->format) &&
    560        !util_format_is_pure_integer(info.src.resource->format)) {
    561       DBG("color resolve unimplemented");
    562       return;
    563    }
    564 
    565    if (etna_try_rs_blit(pctx, blit_info))
    566       return;
    567 
    568    if (util_try_blit_via_copy_region(pctx, blit_info))
    569       return;
    570 
    571    if (info.mask & PIPE_MASK_S) {
    572       DBG("cannot blit stencil, skipping");
    573       info.mask &= ~PIPE_MASK_S;
    574    }
    575 
    576    if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
    577       DBG("blit unsupported %s -> %s",
    578           util_format_short_name(info.src.resource->format),
    579           util_format_short_name(info.dst.resource->format));
    580       return;
    581    }
    582 
    583    etna_blit_save_state(ctx);
    584    util_blitter_blit(ctx->blitter, &info);
    585 }
    586 
    587 static void
    588 etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
    589 {
    590    struct etna_resource *rsc = etna_resource(prsc);
    591 
    592    if (rsc->scanout)
    593       etna_copy_resource(pctx, rsc->scanout->prime, prsc, 0, 0);
    594 }
    595 
    596 void
    597 etna_copy_resource(struct pipe_context *pctx, struct pipe_resource *dst,
    598                    struct pipe_resource *src, int first_level, int last_level)
    599 {
    600    struct etna_resource *src_priv = etna_resource(src);
    601    struct etna_resource *dst_priv = etna_resource(dst);
    602 
    603    assert(src->format == dst->format);
    604    assert(src->array_size == dst->array_size);
    605    assert(last_level <= dst->last_level && last_level <= src->last_level);
    606 
    607    struct pipe_blit_info blit = {};
    608    blit.mask = util_format_get_mask(dst->format);
    609    blit.filter = PIPE_TEX_FILTER_NEAREST;
    610    blit.src.resource = src;
    611    blit.src.format = src->format;
    612    blit.dst.resource = dst;
    613    blit.dst.format = dst->format;
    614    blit.dst.box.depth = blit.src.box.depth = 1;
    615 
    616    /* Copy each level and each layer */
    617    for (int level = first_level; level <= last_level; level++) {
    618       blit.src.level = blit.dst.level = level;
    619       blit.src.box.width = blit.dst.box.width =
    620          MIN2(src_priv->levels[level].width, dst_priv->levels[level].width);
    621       blit.src.box.height = blit.dst.box.height =
    622          MIN2(src_priv->levels[level].height, dst_priv->levels[level].height);
    623 
    624       for (int layer = 0; layer < dst->array_size; layer++) {
    625          blit.src.box.z = blit.dst.box.z = layer;
    626          pctx->blit(pctx, &blit);
    627       }
    628    }
    629 }
    630 
    631 void
    632 etna_clear_blit_init(struct pipe_context *pctx)
    633 {
    634    pctx->clear = etna_clear;
    635    pctx->clear_render_target = etna_clear_render_target;
    636    pctx->clear_depth_stencil = etna_clear_depth_stencil;
    637    pctx->resource_copy_region = etna_resource_copy_region;
    638    pctx->blit = etna_blit;
    639    pctx->flush_resource = etna_flush_resource;
    640 }
    641