• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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
ilo_image_can_enable_aux(const struct ilo_image * img,unsigned level)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
ilo_image_pos_to_mem(const struct ilo_image * img,unsigned pos_x,unsigned pos_y,unsigned * mem_x,unsigned * mem_y)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
ilo_image_mem_to_linear(const struct ilo_image * img,unsigned mem_x,unsigned mem_y)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
ilo_image_mem_to_raw(const struct ilo_image * img,unsigned mem_x,unsigned mem_y)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
ilo_image_get_slice_stride(const struct ilo_image * img,unsigned level)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
ilo_image_get_slice_size(const struct ilo_image * img,unsigned level)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
ilo_image_get_slice_pos(const struct ilo_image * img,unsigned level,unsigned slice,unsigned * x,unsigned * y)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