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