Home | History | Annotate | Download | only in core
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2014 LunarG, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     22  * DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Chia-I Wu <olv (at) lunarg.com>
     26  */
     27 
     28 #ifndef ILO_BUILDER_BLT_H
     29 #define ILO_BUILDER_BLT_H
     30 
     31 #include "genhw/genhw.h"
     32 #include "intel_winsys.h"
     33 
     34 #include "ilo_core.h"
     35 #include "ilo_dev.h"
     36 #include "ilo_builder.h"
     37 
     38 enum gen6_blt_mask {
     39    GEN6_BLT_MASK_8,
     40    GEN6_BLT_MASK_16,
     41    GEN6_BLT_MASK_32,
     42    GEN6_BLT_MASK_32_LO,
     43    GEN6_BLT_MASK_32_HI,
     44 };
     45 
     46 struct gen6_blt_bo {
     47    struct intel_bo *bo;
     48    uint32_t offset;
     49    int16_t pitch;
     50 };
     51 
     52 struct gen6_blt_xy_bo {
     53    struct intel_bo *bo;
     54    uint32_t offset;
     55    int16_t pitch;
     56 
     57    enum gen_surface_tiling tiling;
     58    int16_t x, y;
     59 };
     60 
     61 /*
     62  * From the Sandy Bridge PRM, volume 1 part 5, page 7:
     63  *
     64  *     "The BLT engine is capable of transferring very large quantities of
     65  *      graphics data. Any graphics data read from and written to the
     66  *      destination is permitted to represent a number of pixels that occupies
     67  *      up to 65,536 scan lines and up to 32,768 bytes per scan line at the
     68  *      destination. The maximum number of pixels that may be represented per
     69  *      scan line's worth of graphics data depends on the color depth."
     70  */
     71 static const int gen6_blt_max_bytes_per_scanline = 32768;
     72 static const int gen6_blt_max_scanlines = 65536;
     73 
     74 static inline uint32_t
     75 gen6_blt_translate_value_mask(enum gen6_blt_mask value_mask)
     76 {
     77    switch (value_mask) {
     78    case GEN6_BLT_MASK_8:  return GEN6_BLITTER_BR13_FORMAT_8;
     79    case GEN6_BLT_MASK_16: return GEN6_BLITTER_BR13_FORMAT_565;
     80    default:               return GEN6_BLITTER_BR13_FORMAT_8888;
     81    }
     82 }
     83 
     84 static inline uint32_t
     85 gen6_blt_translate_value_cpp(enum gen6_blt_mask value_mask)
     86 {
     87    switch (value_mask) {
     88    case GEN6_BLT_MASK_8:  return 1;
     89    case GEN6_BLT_MASK_16: return 2;
     90    default:               return 4;
     91    }
     92 }
     93 
     94 static inline uint32_t
     95 gen6_blt_translate_write_mask(enum gen6_blt_mask write_mask)
     96 {
     97    switch (write_mask) {
     98    case GEN6_BLT_MASK_32:    return GEN6_BLITTER_BR00_WRITE_RGB |
     99                                     GEN6_BLITTER_BR00_WRITE_A;
    100    case GEN6_BLT_MASK_32_LO: return GEN6_BLITTER_BR00_WRITE_RGB;
    101    case GEN6_BLT_MASK_32_HI: return GEN6_BLITTER_BR00_WRITE_A;
    102    default:                  return 0;
    103    }
    104 }
    105 
    106 static inline void
    107 gen6_COLOR_BLT(struct ilo_builder *builder,
    108                const struct gen6_blt_bo *dst, uint32_t pattern,
    109                uint16_t width, uint16_t height, uint8_t rop,
    110                enum gen6_blt_mask value_mask,
    111                enum gen6_blt_mask write_mask)
    112 {
    113    const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 6 : 5;
    114    const int cpp = gen6_blt_translate_value_cpp(value_mask);
    115    uint32_t *dw;
    116    unsigned pos;
    117 
    118    ILO_DEV_ASSERT(builder->dev, 6, 8);
    119 
    120    assert(width < gen6_blt_max_bytes_per_scanline);
    121    assert(height < gen6_blt_max_scanlines);
    122    /* offsets are naturally aligned and pitches are dword-aligned */
    123    assert(dst->offset % cpp == 0 && dst->pitch % 4 == 0);
    124 
    125    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
    126 
    127    dw[0] = GEN6_BLITTER_CMD(COLOR_BLT) |
    128            gen6_blt_translate_write_mask(write_mask) |
    129            (cmd_len - 2);
    130    dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
    131            gen6_blt_translate_value_mask(value_mask) |
    132            dst->pitch;
    133    dw[2] = height << 16 | width;
    134 
    135    if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
    136       dw[5] = pattern;
    137 
    138       ilo_builder_batch_reloc64(builder, pos + 3,
    139             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    140    } else {
    141       dw[4] = pattern;
    142 
    143       ilo_builder_batch_reloc(builder, pos + 3,
    144             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    145    }
    146 }
    147 
    148 static inline void
    149 gen6_XY_COLOR_BLT(struct ilo_builder *builder,
    150                   const struct gen6_blt_xy_bo *dst, uint32_t pattern,
    151                   uint16_t width, uint16_t height, uint8_t rop,
    152                   enum gen6_blt_mask value_mask,
    153                   enum gen6_blt_mask write_mask)
    154 {
    155    const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 7 : 6;
    156    const int cpp = gen6_blt_translate_value_cpp(value_mask);
    157    int dst_align = 4, dst_pitch_shift = 0;
    158    uint32_t *dw;
    159    unsigned pos;
    160 
    161    ILO_DEV_ASSERT(builder->dev, 6, 8);
    162 
    163    assert(width * cpp < gen6_blt_max_bytes_per_scanline);
    164    assert(height < gen6_blt_max_scanlines);
    165    /* INT16_MAX */
    166    assert(dst->x + width <= 32767 && dst->y + height <= 32767);
    167 
    168    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
    169 
    170    dw[0] = GEN6_BLITTER_CMD(XY_COLOR_BLT) |
    171            gen6_blt_translate_write_mask(write_mask) |
    172            (cmd_len - 2);
    173 
    174    if (dst->tiling != GEN6_TILING_NONE) {
    175       dw[0] |= GEN6_BLITTER_BR00_DST_TILED;
    176 
    177       assert(dst->tiling == GEN6_TILING_X || dst->tiling == GEN6_TILING_Y);
    178       dst_align = (dst->tiling == GEN6_TILING_Y) ? 128 : 512;
    179       /* in dwords when tiled */
    180       dst_pitch_shift = 2;
    181    }
    182 
    183    assert(dst->offset % dst_align == 0 && dst->pitch % dst_align == 0);
    184 
    185    dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
    186            gen6_blt_translate_value_mask(value_mask) |
    187            dst->pitch >> dst_pitch_shift;
    188    dw[2] = dst->y << 16 | dst->x;
    189    dw[3] = (dst->y + height) << 16 | (dst->x + width);
    190 
    191    if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
    192       dw[6] = pattern;
    193 
    194       ilo_builder_batch_reloc64(builder, pos + 4,
    195             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    196    } else {
    197       dw[5] = pattern;
    198 
    199       ilo_builder_batch_reloc(builder, pos + 4,
    200             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    201    }
    202 }
    203 
    204 static inline void
    205 gen6_SRC_COPY_BLT(struct ilo_builder *builder,
    206                   const struct gen6_blt_bo *dst,
    207                   const struct gen6_blt_bo *src,
    208                   uint16_t width, uint16_t height, uint8_t rop,
    209                   enum gen6_blt_mask value_mask,
    210                   enum gen6_blt_mask write_mask)
    211 {
    212    const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 8 : 6;
    213    const int cpp = gen6_blt_translate_value_cpp(value_mask);
    214    uint32_t *dw;
    215    unsigned pos;
    216 
    217    ILO_DEV_ASSERT(builder->dev, 6, 8);
    218 
    219    assert(width < gen6_blt_max_bytes_per_scanline);
    220    assert(height < gen6_blt_max_scanlines);
    221    /* offsets are naturally aligned and pitches are dword-aligned */
    222    assert(dst->offset % cpp == 0 && dst->pitch % 4 == 0);
    223    assert(src->offset % cpp == 0 && src->pitch % 4 == 0);
    224 
    225    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
    226 
    227    dw[0] = GEN6_BLITTER_CMD(SRC_COPY_BLT) |
    228            gen6_blt_translate_write_mask(write_mask) |
    229            (cmd_len - 2);
    230    dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
    231            gen6_blt_translate_value_mask(value_mask) |
    232            dst->pitch;
    233    dw[2] = height << 16 | width;
    234 
    235    if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
    236       dw[5] = src->pitch;
    237 
    238       ilo_builder_batch_reloc64(builder, pos + 3,
    239             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    240       ilo_builder_batch_reloc64(builder, pos + 6, src->bo, src->offset, 0);
    241    } else {
    242       dw[4] = src->pitch;
    243 
    244       ilo_builder_batch_reloc(builder, pos + 3,
    245             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    246       ilo_builder_batch_reloc(builder, pos + 5, src->bo, src->offset, 0);
    247    }
    248 }
    249 
    250 static inline void
    251 gen6_XY_SRC_COPY_BLT(struct ilo_builder *builder,
    252                      const struct gen6_blt_xy_bo *dst,
    253                      const struct gen6_blt_xy_bo *src,
    254                      uint16_t width, uint16_t height, uint8_t rop,
    255                      enum gen6_blt_mask value_mask,
    256                      enum gen6_blt_mask write_mask)
    257 {
    258    const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 10 : 8;
    259    const int cpp = gen6_blt_translate_value_cpp(value_mask);
    260    int dst_align = 4, dst_pitch_shift = 0;
    261    int src_align = 4, src_pitch_shift = 0;
    262    uint32_t *dw;
    263    unsigned pos;
    264 
    265    ILO_DEV_ASSERT(builder->dev, 6, 8);
    266 
    267    assert(width * cpp < gen6_blt_max_bytes_per_scanline);
    268    assert(height < gen6_blt_max_scanlines);
    269    /* INT16_MAX */
    270    assert(dst->x + width <= 32767 && dst->y + height <= 32767);
    271 
    272    pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
    273 
    274    dw[0] = GEN6_BLITTER_CMD(XY_SRC_COPY_BLT) |
    275            gen6_blt_translate_write_mask(write_mask) |
    276            (cmd_len - 2);
    277 
    278    if (dst->tiling != GEN6_TILING_NONE) {
    279       dw[0] |= GEN6_BLITTER_BR00_DST_TILED;
    280 
    281       assert(dst->tiling == GEN6_TILING_X || dst->tiling == GEN6_TILING_Y);
    282       dst_align = (dst->tiling == GEN6_TILING_Y) ? 128 : 512;
    283       /* in dwords when tiled */
    284       dst_pitch_shift = 2;
    285    }
    286 
    287    if (src->tiling != GEN6_TILING_NONE) {
    288       dw[0] |= GEN6_BLITTER_BR00_SRC_TILED;
    289 
    290       assert(src->tiling == GEN6_TILING_X || src->tiling == GEN6_TILING_Y);
    291       src_align = (src->tiling == GEN6_TILING_Y) ? 128 : 512;
    292       /* in dwords when tiled */
    293       src_pitch_shift = 2;
    294    }
    295 
    296    assert(dst->offset % dst_align == 0 && dst->pitch % dst_align == 0);
    297    assert(src->offset % src_align == 0 && src->pitch % src_align == 0);
    298 
    299    dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
    300            gen6_blt_translate_value_mask(value_mask) |
    301            dst->pitch >> dst_pitch_shift;
    302    dw[2] = dst->y << 16 | dst->x;
    303    dw[3] = (dst->y + height) << 16 | (dst->x + width);
    304 
    305    if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
    306       dw[6] = src->y << 16 | src->x;
    307       dw[7] = src->pitch >> src_pitch_shift;
    308 
    309       ilo_builder_batch_reloc64(builder, pos + 4,
    310             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    311       ilo_builder_batch_reloc64(builder, pos + 8, src->bo, src->offset, 0);
    312    } else {
    313       dw[5] = src->y << 16 | src->x;
    314       dw[6] = src->pitch >> src_pitch_shift;
    315 
    316       ilo_builder_batch_reloc(builder, pos + 4,
    317             dst->bo, dst->offset, INTEL_RELOC_WRITE);
    318       ilo_builder_batch_reloc(builder, pos + 7, src->bo, src->offset, 0);
    319    }
    320 }
    321 
    322 #endif /* ILO_BUILDER_BLT_H */
    323