/* * Mesa 3-D graphics library * * Copyright (C) 2014 LunarG, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Chia-I Wu */ #ifndef ILO_IMAGE_H #define ILO_IMAGE_H #include "genhw/genhw.h" #include "ilo_core.h" #include "ilo_dev.h" /* * From the Ivy Bridge PRM, volume 4 part 1, page 75: * * "(MIP Count / LOD) representing [1,15] MIP levels" */ #define ILO_IMAGE_MAX_LEVEL_COUNT 15 enum ilo_image_aux_type { ILO_IMAGE_AUX_NONE, ILO_IMAGE_AUX_HIZ, ILO_IMAGE_AUX_MCS, }; enum ilo_image_walk_type { /* * LODs of each array layer are first packed together in MIPLAYOUT_BELOW. * Array layers are then stacked together vertically. * * This can be used for mipmapped 2D textures. */ ILO_IMAGE_WALK_LAYER, /* * Array layers of each LOD are first stacked together vertically and * tightly. LODs are then packed together in MIPLAYOUT_BELOW with each LOD * starting at page boundaries. * * This is usually used for non-mipmapped 2D textures, as multiple LODs are * not supported natively. */ ILO_IMAGE_WALK_LOD, /* * 3D slices of each LOD are first packed together horizontally and tightly * with wrapping. LODs are then stacked together vertically and tightly. * * This is used for 3D textures. */ ILO_IMAGE_WALK_3D, }; struct ilo_image_info { enum gen_surface_type type; enum gen_surface_format format; bool interleaved_stencil; bool is_integer; /* width, height and size of pixel blocks */ bool compressed; unsigned block_width; unsigned block_height; unsigned block_size; /* image size */ uint16_t width; uint16_t height; uint16_t depth; uint16_t array_size; uint8_t level_count; uint8_t sample_count; /* disable optional aux */ bool aux_disable; /* tilings to consider, if any bit is set */ uint8_t valid_tilings; /* * prefer GEN6_TILING_NONE when the (estimated) image size exceeds the * threshold; ignored when zero */ uint32_t prefer_linear_threshold; /* force a stride when non-zero */ uint32_t force_bo_stride; bool bind_surface_sampler; bool bind_surface_dp_render; bool bind_surface_dp_typed; bool bind_zs; bool bind_scanout; bool bind_cursor; }; /* * When the walk type is ILO_IMAGE_WALK_LAYER, there is only a slice in each * LOD and this is used to describe LODs in the first array layer. Otherwise, * there can be multiple slices in each LOD and this is used to describe the * first slice in each LOD. */ struct ilo_image_lod { /* physical position in pixels */ unsigned x; unsigned y; /* physical size of a slice in pixels */ unsigned slice_width; unsigned slice_height; }; /** * Texture layout. */ struct ilo_image { enum gen_surface_type type; enum gen_surface_format format; bool interleaved_stencil; /* size, format, etc for programming hardware states */ unsigned width0; unsigned height0; unsigned depth0; unsigned array_size; unsigned level_count; unsigned sample_count; /* * width, height, and size of pixel blocks for conversion between pixel * positions and memory offsets */ unsigned block_width; unsigned block_height; unsigned block_size; enum ilo_image_walk_type walk; bool interleaved_samples; enum gen_surface_tiling tiling; /* physical LOD slice alignments */ unsigned align_i; unsigned align_j; struct ilo_image_lod lods[ILO_IMAGE_MAX_LEVEL_COUNT]; /* physical layer height for ILO_IMAGE_WALK_LAYER */ unsigned walk_layer_height; /* distance in bytes between two pixel block rows */ unsigned bo_stride; /* number of pixel block rows */ unsigned bo_height; bool scanout; struct { enum ilo_image_aux_type type; /* bitmask of levels that can use aux */ unsigned enables; /* LOD offsets for ILO_IMAGE_WALK_LOD */ unsigned walk_lod_offsets[ILO_IMAGE_MAX_LEVEL_COUNT]; unsigned walk_layer_height; unsigned bo_stride; unsigned bo_height; } aux; }; bool ilo_image_init(struct ilo_image *img, const struct ilo_dev *dev, const struct ilo_image_info *info); static inline bool ilo_image_can_enable_aux(const struct ilo_image *img, unsigned level) { return (img->aux.enables & (1 << level)); } /** * Convert from pixel position to 2D memory offset. */ static inline void ilo_image_pos_to_mem(const struct ilo_image *img, unsigned pos_x, unsigned pos_y, unsigned *mem_x, unsigned *mem_y) { assert(pos_x % img->block_width == 0); assert(pos_y % img->block_height == 0); *mem_x = pos_x / img->block_width * img->block_size; *mem_y = pos_y / img->block_height; } /** * Convert from 2D memory offset to linear offset. */ static inline unsigned ilo_image_mem_to_linear(const struct ilo_image *img, unsigned mem_x, unsigned mem_y) { return mem_y * img->bo_stride + mem_x; } /** * Convert from 2D memory offset to raw offset. */ static inline unsigned ilo_image_mem_to_raw(const struct ilo_image *img, unsigned mem_x, unsigned mem_y) { unsigned tile_w, tile_h; switch (img->tiling) { case GEN6_TILING_NONE: tile_w = 1; tile_h = 1; break; case GEN6_TILING_X: tile_w = 512; tile_h = 8; break; case GEN6_TILING_Y: tile_w = 128; tile_h = 32; break; case GEN8_TILING_W: tile_w = 64; tile_h = 64; break; default: assert(!"unknown tiling"); tile_w = 1; tile_h = 1; break; } assert(mem_x % tile_w == 0); assert(mem_y % tile_h == 0); return mem_y * img->bo_stride + mem_x * tile_h; } /** * Return the stride, in bytes, between slices within a level. */ static inline unsigned ilo_image_get_slice_stride(const struct ilo_image *img, unsigned level) { unsigned h; switch (img->walk) { case ILO_IMAGE_WALK_LAYER: h = img->walk_layer_height; break; case ILO_IMAGE_WALK_LOD: h = img->lods[level].slice_height; break; case ILO_IMAGE_WALK_3D: if (level == 0) { h = img->lods[0].slice_height; break; } /* fall through */ default: assert(!"no single stride to walk across slices"); h = 0; break; } assert(h % img->block_height == 0); return (h / img->block_height) * img->bo_stride; } /** * Return the physical size, in bytes, of a slice in a level. */ static inline unsigned ilo_image_get_slice_size(const struct ilo_image *img, unsigned level) { const unsigned w = img->lods[level].slice_width; const unsigned h = img->lods[level].slice_height; assert(w % img->block_width == 0); assert(h % img->block_height == 0); return (w / img->block_width * img->block_size) * (h / img->block_height); } /** * Return the pixel position of a slice. */ static inline void ilo_image_get_slice_pos(const struct ilo_image *img, unsigned level, unsigned slice, unsigned *x, unsigned *y) { switch (img->walk) { case ILO_IMAGE_WALK_LAYER: *x = img->lods[level].x; *y = img->lods[level].y + img->walk_layer_height * slice; break; case ILO_IMAGE_WALK_LOD: *x = img->lods[level].x; *y = img->lods[level].y + img->lods[level].slice_height * slice; break; case ILO_IMAGE_WALK_3D: { /* slices are packed horizontally with wrapping */ const unsigned sx = slice & ((1 << level) - 1); const unsigned sy = slice >> level; assert(slice < u_minify(img->depth0, level)); *x = img->lods[level].x + img->lods[level].slice_width * sx; *y = img->lods[level].y + img->lods[level].slice_height * sy; } break; default: assert(!"unknown img walk type"); *x = 0; *y = 0; break; } /* should not exceed the bo size */ assert(*y + img->lods[level].slice_height <= img->bo_height * img->block_height); } #endif /* ILO_IMAGE_H */