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_IMAGE_H
     29 #define ILO_IMAGE_H
     30 
     31 #include "genhw/genhw.h"
     32 
     33 #include "ilo_core.h"
     34 #include "ilo_dev.h"
     35 
     36 /*
     37  * From the Ivy Bridge PRM, volume 4 part 1, page 75:
     38  *
     39  *     "(MIP Count / LOD) representing [1,15] MIP levels"
     40  */
     41 #define ILO_IMAGE_MAX_LEVEL_COUNT 15
     42 
     43 enum ilo_image_aux_type {
     44    ILO_IMAGE_AUX_NONE,
     45    ILO_IMAGE_AUX_HIZ,
     46    ILO_IMAGE_AUX_MCS,
     47 };
     48 
     49 enum ilo_image_walk_type {
     50    /*
     51     * LODs of each array layer are first packed together in MIPLAYOUT_BELOW.
     52     * Array layers are then stacked together vertically.
     53     *
     54     * This can be used for mipmapped 2D textures.
     55     */
     56    ILO_IMAGE_WALK_LAYER,
     57 
     58    /*
     59     * Array layers of each LOD are first stacked together vertically and
     60     * tightly.  LODs are then packed together in MIPLAYOUT_BELOW with each LOD
     61     * starting at page boundaries.
     62     *
     63     * This is usually used for non-mipmapped 2D textures, as multiple LODs are
     64     * not supported natively.
     65     */
     66    ILO_IMAGE_WALK_LOD,
     67 
     68    /*
     69     * 3D slices of each LOD are first packed together horizontally and tightly
     70     * with wrapping.  LODs are then stacked together vertically and tightly.
     71     *
     72     * This is used for 3D textures.
     73     */
     74    ILO_IMAGE_WALK_3D,
     75 };
     76 
     77 struct ilo_image_info {
     78    enum gen_surface_type type;
     79 
     80    enum gen_surface_format format;
     81    bool interleaved_stencil;
     82    bool is_integer;
     83    /* width, height and size of pixel blocks */
     84    bool compressed;
     85    unsigned block_width;
     86    unsigned block_height;
     87    unsigned block_size;
     88 
     89    /* image size */
     90    uint16_t width;
     91    uint16_t height;
     92    uint16_t depth;
     93    uint16_t array_size;
     94    uint8_t level_count;
     95    uint8_t sample_count;
     96 
     97    /* disable optional aux */
     98    bool aux_disable;
     99 
    100    /* tilings to consider, if any bit is set */
    101    uint8_t valid_tilings;
    102 
    103    /*
    104     * prefer GEN6_TILING_NONE when the (estimated) image size exceeds the
    105     * threshold; ignored when zero
    106     */
    107    uint32_t prefer_linear_threshold;
    108 
    109    /* force a stride when non-zero */
    110    uint32_t force_bo_stride;
    111 
    112    bool bind_surface_sampler;
    113    bool bind_surface_dp_render;
    114    bool bind_surface_dp_typed;
    115    bool bind_zs;
    116    bool bind_scanout;
    117    bool bind_cursor;
    118 };
    119 
    120 /*
    121  * When the walk type is ILO_IMAGE_WALK_LAYER, there is only a slice in each
    122  * LOD and this is used to describe LODs in the first array layer.  Otherwise,
    123  * there can be multiple slices in each LOD and this is used to describe the
    124  * first slice in each LOD.
    125  */
    126 struct ilo_image_lod {
    127    /* physical position in pixels */
    128    unsigned x;
    129    unsigned y;
    130 
    131    /* physical size of a slice in pixels */
    132    unsigned slice_width;
    133    unsigned slice_height;
    134 };
    135 
    136 /**
    137  * Texture layout.
    138  */
    139 struct ilo_image {
    140    enum gen_surface_type type;
    141 
    142    enum gen_surface_format format;
    143    bool interleaved_stencil;
    144 
    145    /* size, format, etc for programming hardware states */
    146    unsigned width0;
    147    unsigned height0;
    148    unsigned depth0;
    149    unsigned array_size;
    150    unsigned level_count;
    151    unsigned sample_count;
    152 
    153    /*
    154     * width, height, and size of pixel blocks for conversion between pixel
    155     * positions and memory offsets
    156     */
    157    unsigned block_width;
    158    unsigned block_height;
    159    unsigned block_size;
    160 
    161    enum ilo_image_walk_type walk;
    162    bool interleaved_samples;
    163 
    164    enum gen_surface_tiling tiling;
    165 
    166    /* physical LOD slice alignments */
    167    unsigned align_i;
    168    unsigned align_j;
    169 
    170    struct ilo_image_lod lods[ILO_IMAGE_MAX_LEVEL_COUNT];
    171 
    172    /* physical layer height for ILO_IMAGE_WALK_LAYER */
    173    unsigned walk_layer_height;
    174 
    175    /* distance in bytes between two pixel block rows */
    176    unsigned bo_stride;
    177    /* number of pixel block rows */
    178    unsigned bo_height;
    179 
    180    bool scanout;
    181 
    182    struct {
    183       enum ilo_image_aux_type type;
    184 
    185       /* bitmask of levels that can use aux */
    186       unsigned enables;
    187 
    188       /* LOD offsets for ILO_IMAGE_WALK_LOD */
    189       unsigned walk_lod_offsets[ILO_IMAGE_MAX_LEVEL_COUNT];
    190 
    191       unsigned walk_layer_height;
    192       unsigned bo_stride;
    193       unsigned bo_height;
    194    } aux;
    195 };
    196 
    197 bool
    198 ilo_image_init(struct ilo_image *img,
    199                const struct ilo_dev *dev,
    200                const struct ilo_image_info *info);
    201 
    202 static inline bool
    203 ilo_image_can_enable_aux(const struct ilo_image *img, unsigned level)
    204 {
    205    return (img->aux.enables & (1 << level));
    206 }
    207 
    208 /**
    209  * Convert from pixel position to 2D memory offset.
    210  */
    211 static inline void
    212 ilo_image_pos_to_mem(const struct ilo_image *img,
    213                      unsigned pos_x, unsigned pos_y,
    214                      unsigned *mem_x, unsigned *mem_y)
    215 {
    216    assert(pos_x % img->block_width == 0);
    217    assert(pos_y % img->block_height == 0);
    218 
    219    *mem_x = pos_x / img->block_width * img->block_size;
    220    *mem_y = pos_y / img->block_height;
    221 }
    222 
    223 /**
    224  * Convert from 2D memory offset to linear offset.
    225  */
    226 static inline unsigned
    227 ilo_image_mem_to_linear(const struct ilo_image *img,
    228                         unsigned mem_x, unsigned mem_y)
    229 {
    230    return mem_y * img->bo_stride + mem_x;
    231 }
    232 
    233 /**
    234  * Convert from 2D memory offset to raw offset.
    235  */
    236 static inline unsigned
    237 ilo_image_mem_to_raw(const struct ilo_image *img,
    238                      unsigned mem_x, unsigned mem_y)
    239 {
    240    unsigned tile_w, tile_h;
    241 
    242    switch (img->tiling) {
    243    case GEN6_TILING_NONE:
    244       tile_w = 1;
    245       tile_h = 1;
    246       break;
    247    case GEN6_TILING_X:
    248       tile_w = 512;
    249       tile_h = 8;
    250       break;
    251    case GEN6_TILING_Y:
    252       tile_w = 128;
    253       tile_h = 32;
    254       break;
    255    case GEN8_TILING_W:
    256       tile_w = 64;
    257       tile_h = 64;
    258       break;
    259    default:
    260       assert(!"unknown tiling");
    261       tile_w = 1;
    262       tile_h = 1;
    263       break;
    264    }
    265 
    266    assert(mem_x % tile_w == 0);
    267    assert(mem_y % tile_h == 0);
    268 
    269    return mem_y * img->bo_stride + mem_x * tile_h;
    270 }
    271 
    272 /**
    273  * Return the stride, in bytes, between slices within a level.
    274  */
    275 static inline unsigned
    276 ilo_image_get_slice_stride(const struct ilo_image *img, unsigned level)
    277 {
    278    unsigned h;
    279 
    280    switch (img->walk) {
    281    case ILO_IMAGE_WALK_LAYER:
    282       h = img->walk_layer_height;
    283       break;
    284    case ILO_IMAGE_WALK_LOD:
    285       h = img->lods[level].slice_height;
    286       break;
    287    case ILO_IMAGE_WALK_3D:
    288       if (level == 0) {
    289          h = img->lods[0].slice_height;
    290          break;
    291       }
    292       /* fall through */
    293    default:
    294       assert(!"no single stride to walk across slices");
    295       h = 0;
    296       break;
    297    }
    298 
    299    assert(h % img->block_height == 0);
    300 
    301    return (h / img->block_height) * img->bo_stride;
    302 }
    303 
    304 /**
    305  * Return the physical size, in bytes, of a slice in a level.
    306  */
    307 static inline unsigned
    308 ilo_image_get_slice_size(const struct ilo_image *img, unsigned level)
    309 {
    310    const unsigned w = img->lods[level].slice_width;
    311    const unsigned h = img->lods[level].slice_height;
    312 
    313    assert(w % img->block_width == 0);
    314    assert(h % img->block_height == 0);
    315 
    316    return (w / img->block_width * img->block_size) *
    317       (h / img->block_height);
    318 }
    319 
    320 /**
    321  * Return the pixel position of a slice.
    322  */
    323 static inline void
    324 ilo_image_get_slice_pos(const struct ilo_image *img,
    325                         unsigned level, unsigned slice,
    326                         unsigned *x, unsigned *y)
    327 {
    328    switch (img->walk) {
    329    case ILO_IMAGE_WALK_LAYER:
    330       *x = img->lods[level].x;
    331       *y = img->lods[level].y + img->walk_layer_height * slice;
    332       break;
    333    case ILO_IMAGE_WALK_LOD:
    334       *x = img->lods[level].x;
    335       *y = img->lods[level].y + img->lods[level].slice_height * slice;
    336       break;
    337    case ILO_IMAGE_WALK_3D:
    338       {
    339          /* slices are packed horizontally with wrapping */
    340          const unsigned sx = slice & ((1 << level) - 1);
    341          const unsigned sy = slice >> level;
    342 
    343          assert(slice < u_minify(img->depth0, level));
    344 
    345          *x = img->lods[level].x + img->lods[level].slice_width * sx;
    346          *y = img->lods[level].y + img->lods[level].slice_height * sy;
    347       }
    348       break;
    349    default:
    350       assert(!"unknown img walk type");
    351       *x = 0;
    352       *y = 0;
    353       break;
    354    }
    355 
    356    /* should not exceed the bo size */
    357    assert(*y + img->lods[level].slice_height <=
    358          img->bo_height * img->block_height);
    359 }
    360 
    361 #endif /* ILO_IMAGE_H */
    362