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 #ifndef H_ETNA_EMIT
     28 #define H_ETNA_EMIT
     29 
     30 #include "etnaviv_screen.h"
     31 #include "etnaviv_util.h"
     32 #include "hw/cmdstream.xml.h"
     33 
     34 struct etna_context;
     35 struct compiled_rs_state;
     36 
     37 struct etna_coalesce {
     38    uint32_t start;
     39    uint32_t last_reg;
     40    uint32_t last_fixp;
     41 };
     42 
     43 static inline void
     44 etna_emit_load_state(struct etna_cmd_stream *stream, const uint16_t offset,
     45                      const uint16_t count, const int fixp)
     46 {
     47    uint32_t v;
     48 
     49    v = VIV_FE_LOAD_STATE_HEADER_OP_LOAD_STATE |
     50        COND(fixp, VIV_FE_LOAD_STATE_HEADER_FIXP) |
     51        VIV_FE_LOAD_STATE_HEADER_OFFSET(offset) |
     52        (VIV_FE_LOAD_STATE_HEADER_COUNT(count) &
     53         VIV_FE_LOAD_STATE_HEADER_COUNT__MASK);
     54 
     55    etna_cmd_stream_emit(stream, v);
     56 }
     57 
     58 static inline void
     59 etna_set_state(struct etna_cmd_stream *stream, uint32_t address, uint32_t value)
     60 {
     61    etna_cmd_stream_reserve(stream, 2);
     62    etna_emit_load_state(stream, address >> 2, 1, 0);
     63    etna_cmd_stream_emit(stream, value);
     64 }
     65 
     66 static inline void
     67 etna_set_state_reloc(struct etna_cmd_stream *stream, uint32_t address,
     68                      const struct etna_reloc *reloc)
     69 {
     70    etna_cmd_stream_reserve(stream, 2);
     71    etna_emit_load_state(stream, address >> 2, 1, 0);
     72    etna_cmd_stream_reloc(stream, reloc);
     73 }
     74 
     75 static inline void
     76 etna_set_state_multi(struct etna_cmd_stream *stream, uint32_t base,
     77                      uint32_t num, const uint32_t *values)
     78 {
     79    if (num == 0)
     80       return;
     81 
     82    etna_cmd_stream_reserve(stream, 1 + num + 1); /* 1 extra for potential alignment */
     83    etna_emit_load_state(stream, base >> 2, num, 0);
     84 
     85    for (uint32_t i = 0; i < num; i++)
     86       etna_cmd_stream_emit(stream, values[i]);
     87 
     88    /* add potential padding */
     89    if ((num % 2) == 0)
     90       etna_cmd_stream_emit(stream, 0);
     91 }
     92 
     93 void
     94 etna_stall(struct etna_cmd_stream *stream, uint32_t from, uint32_t to);
     95 
     96 static inline void
     97 etna_draw_primitives(struct etna_cmd_stream *stream, uint32_t primitive_type,
     98                      uint32_t start, uint32_t count)
     99 {
    100    etna_cmd_stream_reserve(stream, 4);
    101 
    102    etna_cmd_stream_emit(stream, VIV_FE_DRAW_PRIMITIVES_HEADER_OP_DRAW_PRIMITIVES);
    103    etna_cmd_stream_emit(stream, primitive_type);
    104    etna_cmd_stream_emit(stream, start);
    105    etna_cmd_stream_emit(stream, count);
    106 }
    107 
    108 static inline void
    109 etna_draw_indexed_primitives(struct etna_cmd_stream *stream,
    110                              uint32_t primitive_type, uint32_t start,
    111                              uint32_t count, uint32_t offset)
    112 {
    113    etna_cmd_stream_reserve(stream, 5 + 1);
    114 
    115    etna_cmd_stream_emit(stream, VIV_FE_DRAW_INDEXED_PRIMITIVES_HEADER_OP_DRAW_INDEXED_PRIMITIVES);
    116    etna_cmd_stream_emit(stream, primitive_type);
    117    etna_cmd_stream_emit(stream, start);
    118    etna_cmd_stream_emit(stream, count);
    119    etna_cmd_stream_emit(stream, offset);
    120    etna_cmd_stream_emit(stream, 0);
    121 }
    122 
    123 /* important: this takes a vertex count, not a primitive count */
    124 static inline void
    125 etna_draw_instanced(struct etna_cmd_stream *stream,
    126                     uint32_t indexed, uint32_t primitive_type,
    127                     uint32_t instance_count,
    128                     uint32_t vertex_count, uint32_t offset)
    129 {
    130    etna_cmd_stream_reserve(stream, 3 + 1);
    131    etna_cmd_stream_emit(stream,
    132       VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED |
    133       COND(indexed, VIV_FE_DRAW_INSTANCED_HEADER_INDEXED) |
    134       VIV_FE_DRAW_INSTANCED_HEADER_TYPE(primitive_type) |
    135       VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(instance_count & 0xffff));
    136    etna_cmd_stream_emit(stream,
    137       VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(instance_count >> 16) |
    138       VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(vertex_count));
    139    etna_cmd_stream_emit(stream,
    140       VIV_FE_DRAW_INSTANCED_START_INDEX(offset));
    141    etna_cmd_stream_emit(stream, 0);
    142 }
    143 
    144 static inline void
    145 etna_coalesce_start(struct etna_cmd_stream *stream,
    146                     struct etna_coalesce *coalesce)
    147 {
    148    coalesce->start = etna_cmd_stream_offset(stream);
    149    coalesce->last_reg = 0;
    150    coalesce->last_fixp = 0;
    151 }
    152 
    153 static inline void
    154 etna_coalesce_end(struct etna_cmd_stream *stream,
    155                   struct etna_coalesce *coalesce)
    156 {
    157    uint32_t end = etna_cmd_stream_offset(stream);
    158    uint32_t size = end - coalesce->start;
    159 
    160    if (size) {
    161       uint32_t offset = coalesce->start - 1;
    162       uint32_t value = etna_cmd_stream_get(stream, offset);
    163 
    164       value |= VIV_FE_LOAD_STATE_HEADER_COUNT(size);
    165       etna_cmd_stream_set(stream, offset, value);
    166    }
    167 
    168    /* append needed padding */
    169    if (end % 2 == 1)
    170       etna_cmd_stream_emit(stream, 0xdeadbeef);
    171 }
    172 
    173 static inline void
    174 check_coalsence(struct etna_cmd_stream *stream, struct etna_coalesce *coalesce,
    175                 uint32_t reg, uint32_t fixp)
    176 {
    177    if (coalesce->last_reg != 0) {
    178       if (((coalesce->last_reg + 4) != reg) || (coalesce->last_fixp != fixp)) {
    179          etna_coalesce_end(stream, coalesce);
    180          etna_emit_load_state(stream, reg >> 2, 0, fixp);
    181          coalesce->start = etna_cmd_stream_offset(stream);
    182       }
    183    } else {
    184       etna_emit_load_state(stream, reg >> 2, 0, fixp);
    185       coalesce->start = etna_cmd_stream_offset(stream);
    186    }
    187 
    188    coalesce->last_reg = reg;
    189    coalesce->last_fixp = fixp;
    190 }
    191 
    192 static inline void
    193 etna_coalsence_emit(struct etna_cmd_stream *stream,
    194                     struct etna_coalesce *coalesce, uint32_t reg,
    195                     uint32_t value)
    196 {
    197    check_coalsence(stream, coalesce, reg, 0);
    198    etna_cmd_stream_emit(stream, value);
    199 }
    200 
    201 static inline void
    202 etna_coalsence_emit_fixp(struct etna_cmd_stream *stream,
    203                          struct etna_coalesce *coalesce, uint32_t reg,
    204                          uint32_t value)
    205 {
    206    check_coalsence(stream, coalesce, reg, 1);
    207    etna_cmd_stream_emit(stream, value);
    208 }
    209 
    210 static inline void
    211 etna_coalsence_emit_reloc(struct etna_cmd_stream *stream,
    212                           struct etna_coalesce *coalesce, uint32_t reg,
    213                           const struct etna_reloc *r)
    214 {
    215    if (r->bo) {
    216       check_coalsence(stream, coalesce, reg, 0);
    217       etna_cmd_stream_reloc(stream, r);
    218    }
    219 }
    220 
    221 void
    222 etna_emit_state(struct etna_context *ctx);
    223 
    224 #endif
    225