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  *    Christian Gmeiner <christian.gmeiner (at) gmail.com>
     26  */
     27 
     28 #include "etnaviv_context.h"
     29 
     30 #include "etnaviv_blend.h"
     31 #include "etnaviv_clear_blit.h"
     32 #include "etnaviv_compiler.h"
     33 #include "etnaviv_debug.h"
     34 #include "etnaviv_emit.h"
     35 #include "etnaviv_fence.h"
     36 #include "etnaviv_query.h"
     37 #include "etnaviv_rasterizer.h"
     38 #include "etnaviv_screen.h"
     39 #include "etnaviv_shader.h"
     40 #include "etnaviv_state.h"
     41 #include "etnaviv_surface.h"
     42 #include "etnaviv_texture.h"
     43 #include "etnaviv_transfer.h"
     44 #include "etnaviv_translate.h"
     45 #include "etnaviv_zsa.h"
     46 
     47 #include "pipe/p_context.h"
     48 #include "pipe/p_state.h"
     49 #include "util/u_blitter.h"
     50 #include "util/u_memory.h"
     51 #include "util/u_prim.h"
     52 
     53 #include "hw/common.xml.h"
     54 
     55 static void
     56 etna_context_destroy(struct pipe_context *pctx)
     57 {
     58    struct etna_context *ctx = etna_context(pctx);
     59 
     60    if (ctx->primconvert)
     61       util_primconvert_destroy(ctx->primconvert);
     62 
     63    if (ctx->blitter)
     64       util_blitter_destroy(ctx->blitter);
     65 
     66    if (ctx->stream)
     67       etna_cmd_stream_del(ctx->stream);
     68 
     69    slab_destroy_child(&ctx->transfer_pool);
     70 
     71    FREE(pctx);
     72 }
     73 
     74 /* Update render state where needed based on draw operation */
     75 static void
     76 etna_update_state_for_draw(struct etna_context *ctx, const struct pipe_draw_info *info)
     77 {
     78    /* Handle primitive restart:
     79     * - If not an indexed draw, we don't care about the state of the primitive restart bit.
     80     * - Otherwise, set the bit in INDEX_STREAM_CONTROL in the index buffer state
     81     *   accordingly
     82     * - If the value of the INDEX_STREAM_CONTROL register changed due to this, or
     83     *   primitive restart is enabled and the restart index changed, mark the index
     84     *   buffer state as dirty
     85     */
     86 
     87    if (info->indexed) {
     88       uint32_t new_control = ctx->index_buffer.FE_INDEX_STREAM_CONTROL;
     89 
     90       if (info->primitive_restart)
     91          new_control |= VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;
     92       else
     93          new_control &= ~VIVS_FE_INDEX_STREAM_CONTROL_PRIMITIVE_RESTART;
     94 
     95       if (ctx->index_buffer.FE_INDEX_STREAM_CONTROL != new_control ||
     96           (info->primitive_restart && ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX != info->restart_index)) {
     97          ctx->index_buffer.FE_INDEX_STREAM_CONTROL = new_control;
     98          ctx->index_buffer.FE_PRIMITIVE_RESTART_INDEX = info->restart_index;
     99          ctx->dirty |= ETNA_DIRTY_INDEX_BUFFER;
    100       }
    101    }
    102 }
    103 
    104 
    105 static void
    106 etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
    107 {
    108    struct etna_context *ctx = etna_context(pctx);
    109    struct pipe_framebuffer_state *pfb = &ctx->framebuffer_s;
    110    uint32_t draw_mode;
    111    unsigned i;
    112 
    113    if (ctx->vertex_elements == NULL || ctx->vertex_elements->num_elements == 0)
    114       return; /* Nothing to do */
    115 
    116    if (!(ctx->prim_hwsupport & (1 << info->mode))) {
    117       struct primconvert_context *primconvert = ctx->primconvert;
    118       util_primconvert_save_index_buffer(primconvert, &ctx->index_buffer.ib);
    119       util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer);
    120       util_primconvert_draw_vbo(primconvert, info);
    121       return;
    122    }
    123 
    124    int prims = u_decomposed_prims_for_vertices(info->mode, info->count);
    125    if (unlikely(prims <= 0)) {
    126       DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode);
    127       return;
    128    }
    129 
    130    draw_mode = translate_draw_mode(info->mode);
    131    if (draw_mode == ETNA_NO_MATCH) {
    132       BUG("Unsupported draw mode");
    133       return;
    134    }
    135 
    136    if (info->indexed && !ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo) {
    137       BUG("Unsupported or no index buffer");
    138       return;
    139    }
    140 
    141    /* Update any derived state */
    142    if (!etna_state_update(ctx))
    143       return;
    144 
    145    /*
    146     * Figure out the buffers/features we need:
    147     */
    148    if (etna_depth_enabled(ctx))
    149       resource_written(ctx, pfb->zsbuf->texture);
    150 
    151    if (etna_stencil_enabled(ctx))
    152       resource_written(ctx, pfb->zsbuf->texture);
    153 
    154    for (i = 0; i < pfb->nr_cbufs; i++) {
    155       struct pipe_resource *surf;
    156 
    157       if (!pfb->cbufs[i])
    158          continue;
    159 
    160       surf = pfb->cbufs[i]->texture;
    161       resource_written(ctx, surf);
    162    }
    163 
    164    /* Mark constant buffers as being read */
    165    resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_VERTEX].buffer);
    166    resource_read(ctx, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].buffer);
    167 
    168    /* Mark VBOs as being read */
    169    for (i = 0; i < ctx->vertex_buffer.count; i++) {
    170       assert(!ctx->vertex_buffer.vb[i].user_buffer);
    171       resource_read(ctx, ctx->vertex_buffer.vb[i].buffer);
    172    }
    173 
    174    /* Mark index buffer as being read */
    175    resource_read(ctx, ctx->index_buffer.ib.buffer);
    176 
    177    /* Mark textures as being read */
    178    for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
    179       if (ctx->sampler_view[i])
    180          resource_read(ctx, ctx->sampler_view[i]->texture);
    181 
    182    ctx->stats.prims_emitted += u_reduced_prims_for_vertices(info->mode, info->count);
    183    ctx->stats.draw_calls++;
    184 
    185    /* Update state for this draw operation */
    186    etna_update_state_for_draw(ctx, info);
    187 
    188    /* First, sync state, then emit DRAW_PRIMITIVES or DRAW_INDEXED_PRIMITIVES */
    189    etna_emit_state(ctx);
    190 
    191    if (info->indexed)
    192       etna_draw_indexed_primitives(ctx->stream, draw_mode, info->start, prims, info->index_bias);
    193    else
    194       etna_draw_primitives(ctx->stream, draw_mode, info->start, prims);
    195 
    196    if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) {
    197       /* Stall the FE after every draw operation.  This allows better
    198        * debug of GPU hang conditions, as the FE will indicate which
    199        * draw op has caused the hang. */
    200       etna_stall(ctx->stream, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
    201    }
    202 
    203    if (DBG_ENABLED(ETNA_DBG_FLUSH_ALL))
    204       pctx->flush(pctx, NULL, 0);
    205 
    206    if (ctx->framebuffer.cbuf)
    207       etna_resource(ctx->framebuffer.cbuf->texture)->seqno++;
    208    if (ctx->framebuffer.zsbuf)
    209       etna_resource(ctx->framebuffer.zsbuf->texture)->seqno++;
    210 }
    211 
    212 static void
    213 etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
    214            enum pipe_flush_flags flags)
    215 {
    216    struct etna_context *ctx = etna_context(pctx);
    217 
    218    etna_cmd_stream_flush(ctx->stream);
    219 
    220    if (fence)
    221       *fence = etna_fence_create(pctx);
    222 }
    223 
    224 static void
    225 etna_cmd_stream_reset_notify(struct etna_cmd_stream *stream, void *priv)
    226 {
    227    struct etna_context *ctx = priv;
    228    struct etna_resource *rsc, *rsc_tmp;
    229 
    230    etna_set_state(stream, VIVS_GL_API_MODE, VIVS_GL_API_MODE_OPENGL);
    231    etna_set_state(stream, VIVS_GL_VERTEX_ELEMENT_CONFIG, 0x00000001);
    232    etna_set_state(stream, VIVS_RA_EARLY_DEPTH, 0x00000031);
    233    etna_set_state(stream, VIVS_PA_W_CLIP_LIMIT, 0x34000001);
    234 
    235    ctx->dirty = ~0L;
    236 
    237    /* go through all the used resources and clear their status flag */
    238    LIST_FOR_EACH_ENTRY_SAFE(rsc, rsc_tmp, &ctx->used_resources, list)
    239    {
    240       debug_assert(rsc->status != 0);
    241       rsc->status = 0;
    242       rsc->pending_ctx = NULL;
    243       list_delinit(&rsc->list);
    244    }
    245 
    246    assert(LIST_IS_EMPTY(&ctx->used_resources));
    247 }
    248 
    249 struct pipe_context *
    250 etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
    251 {
    252    struct etna_context *ctx = CALLOC_STRUCT(etna_context);
    253    struct etna_screen *screen;
    254    struct pipe_context *pctx;
    255 
    256    if (ctx == NULL)
    257       return NULL;
    258 
    259    pctx = &ctx->base;
    260    pctx->priv = ctx;
    261    pctx->screen = pscreen;
    262 
    263    screen = etna_screen(pscreen);
    264    ctx->stream = etna_cmd_stream_new(screen->pipe, 0x2000, &etna_cmd_stream_reset_notify, ctx);
    265    if (ctx->stream == NULL)
    266       goto fail;
    267 
    268    /* context ctxate setup */
    269    ctx->specs = screen->specs;
    270    ctx->screen = screen;
    271    /* need some sane default in case state tracker doesn't set some state: */
    272    ctx->sample_mask = 0xffff;
    273 
    274    list_inithead(&ctx->used_resources);
    275 
    276    /*  Set sensible defaults for state */
    277    etna_cmd_stream_reset_notify(ctx->stream, ctx);
    278 
    279    pctx->destroy = etna_context_destroy;
    280    pctx->draw_vbo = etna_draw_vbo;
    281    pctx->flush = etna_flush;
    282 
    283    /* creation of compile states */
    284    pctx->create_blend_state = etna_blend_state_create;
    285    pctx->create_rasterizer_state = etna_rasterizer_state_create;
    286    pctx->create_depth_stencil_alpha_state = etna_zsa_state_create;
    287 
    288    etna_clear_blit_init(pctx);
    289    etna_query_context_init(pctx);
    290    etna_state_init(pctx);
    291    etna_surface_init(pctx);
    292    etna_shader_init(pctx);
    293    etna_texture_init(pctx);
    294    etna_transfer_init(pctx);
    295 
    296    ctx->blitter = util_blitter_create(pctx);
    297    if (!ctx->blitter)
    298       goto fail;
    299 
    300    /* Generate the bitmask of supported draw primitives. */
    301    ctx->prim_hwsupport = 1 << PIPE_PRIM_POINTS |
    302                          1 << PIPE_PRIM_LINES |
    303                          1 << PIPE_PRIM_LINE_STRIP |
    304                          1 << PIPE_PRIM_TRIANGLES |
    305                          1 << PIPE_PRIM_TRIANGLE_STRIP |
    306                          1 << PIPE_PRIM_TRIANGLE_FAN;
    307 
    308    if (VIV_FEATURE(ctx->screen, chipMinorFeatures2, LINE_LOOP))
    309       ctx->prim_hwsupport |= 1 << PIPE_PRIM_LINE_LOOP;
    310 
    311    ctx->primconvert = util_primconvert_create(pctx, ctx->prim_hwsupport);
    312    if (!ctx->primconvert)
    313       goto fail;
    314 
    315    slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
    316 
    317    return pctx;
    318 
    319 fail:
    320    pctx->destroy(pctx);
    321 
    322    return NULL;
    323 }
    324