xref: /aosp_15_r20/external/mesa3d/src/asahi/layout/layout.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2022 Alyssa Rosenzweig
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "layout.h"
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker static void
ail_initialize_linear(struct ail_layout * layout)9*61046927SAndroid Build Coastguard Worker ail_initialize_linear(struct ail_layout *layout)
10*61046927SAndroid Build Coastguard Worker {
11*61046927SAndroid Build Coastguard Worker    /* Select the optimal stride if none is forced */
12*61046927SAndroid Build Coastguard Worker    if (layout->linear_stride_B == 0) {
13*61046927SAndroid Build Coastguard Worker       uint32_t minimum_stride_B =
14*61046927SAndroid Build Coastguard Worker          util_format_get_stride(layout->format, layout->width_px);
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker       layout->linear_stride_B = ALIGN_POT(minimum_stride_B, AIL_CACHELINE);
17*61046927SAndroid Build Coastguard Worker    }
18*61046927SAndroid Build Coastguard Worker 
19*61046927SAndroid Build Coastguard Worker    assert((layout->linear_stride_B % 16) == 0 && "Strides must be aligned");
20*61046927SAndroid Build Coastguard Worker 
21*61046927SAndroid Build Coastguard Worker    /* Layer stride must be cache line aligned to pack linear 2D arrays */
22*61046927SAndroid Build Coastguard Worker    layout->layer_stride_B = align64(
23*61046927SAndroid Build Coastguard Worker       (uint64_t)layout->linear_stride_B * layout->height_px, AIL_CACHELINE);
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker    layout->size_B = layout->layer_stride_B * layout->depth_px;
26*61046927SAndroid Build Coastguard Worker }
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker /*
29*61046927SAndroid Build Coastguard Worker  * Get the maximum tile size possible for a given block size. This satisfy
30*61046927SAndroid Build Coastguard Worker  * width * height * blocksize = 16384 = page size, so each tile is one page.
31*61046927SAndroid Build Coastguard Worker  */
32*61046927SAndroid Build Coastguard Worker static inline struct ail_tile
ail_get_max_tile_size(unsigned blocksize_B)33*61046927SAndroid Build Coastguard Worker ail_get_max_tile_size(unsigned blocksize_B)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker    /* clang-format off */
36*61046927SAndroid Build Coastguard Worker    switch (blocksize_B) {
37*61046927SAndroid Build Coastguard Worker    case  1: return (struct ail_tile) { 128, 128 };
38*61046927SAndroid Build Coastguard Worker    case  2: return (struct ail_tile) { 128,  64 };
39*61046927SAndroid Build Coastguard Worker    case  4: return (struct ail_tile) {  64,  64 };
40*61046927SAndroid Build Coastguard Worker    case  8: return (struct ail_tile) {  64,  32 };
41*61046927SAndroid Build Coastguard Worker    case 16: return (struct ail_tile) {  32,  32 };
42*61046927SAndroid Build Coastguard Worker    case 32: return (struct ail_tile) {  32,  16 };
43*61046927SAndroid Build Coastguard Worker    case 64: return (struct ail_tile) {  16,  16 };
44*61046927SAndroid Build Coastguard Worker    default: unreachable("Invalid blocksize");
45*61046927SAndroid Build Coastguard Worker    }
46*61046927SAndroid Build Coastguard Worker    /* clang-format on */
47*61046927SAndroid Build Coastguard Worker }
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker /*
50*61046927SAndroid Build Coastguard Worker  * Calculate the number of bytes in a block. This must take both block
51*61046927SAndroid Build Coastguard Worker  * dimensions and multisampling into account.
52*61046927SAndroid Build Coastguard Worker  */
53*61046927SAndroid Build Coastguard Worker static uint32_t
ail_get_block_size_B(struct ail_layout * layout)54*61046927SAndroid Build Coastguard Worker ail_get_block_size_B(struct ail_layout *layout)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker    ASSERTED const struct util_format_description *desc =
57*61046927SAndroid Build Coastguard Worker       util_format_description(layout->format);
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker    assert(((layout->sample_count_sa == 1) ||
60*61046927SAndroid Build Coastguard Worker            (desc->block.width == 1 && desc->block.height == 1)) &&
61*61046927SAndroid Build Coastguard Worker           "multisampling and block-compression are mutually-exclusive");
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    return util_format_get_blocksize(layout->format) * layout->sample_count_sa;
64*61046927SAndroid Build Coastguard Worker }
65*61046927SAndroid Build Coastguard Worker 
66*61046927SAndroid Build Coastguard Worker static void
ail_initialize_twiddled(struct ail_layout * layout)67*61046927SAndroid Build Coastguard Worker ail_initialize_twiddled(struct ail_layout *layout)
68*61046927SAndroid Build Coastguard Worker {
69*61046927SAndroid Build Coastguard Worker    unsigned offset_B = 0;
70*61046927SAndroid Build Coastguard Worker    unsigned blocksize_B = ail_get_block_size_B(layout);
71*61046927SAndroid Build Coastguard Worker    unsigned w_el = util_format_get_nblocksx(layout->format, layout->width_px);
72*61046927SAndroid Build Coastguard Worker    unsigned h_el = util_format_get_nblocksy(layout->format, layout->height_px);
73*61046927SAndroid Build Coastguard Worker    unsigned bw_px = util_format_get_blockwidth(layout->format);
74*61046927SAndroid Build Coastguard Worker    unsigned bh_px = util_format_get_blockheight(layout->format);
75*61046927SAndroid Build Coastguard Worker    bool compressed = util_format_is_compressed(layout->format);
76*61046927SAndroid Build Coastguard Worker 
77*61046927SAndroid Build Coastguard Worker    /* Calculate the tile size used for the large miptree, and the dimensions of
78*61046927SAndroid Build Coastguard Worker     * level 0 given that tile size.
79*61046927SAndroid Build Coastguard Worker     */
80*61046927SAndroid Build Coastguard Worker    struct ail_tile tilesize_el = ail_get_max_tile_size(blocksize_B);
81*61046927SAndroid Build Coastguard Worker    unsigned stx_tiles = DIV_ROUND_UP(w_el, tilesize_el.width_el);
82*61046927SAndroid Build Coastguard Worker    unsigned sty_tiles = DIV_ROUND_UP(h_el, tilesize_el.height_el);
83*61046927SAndroid Build Coastguard Worker    unsigned sarea_tiles = stx_tiles * sty_tiles;
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    /* Calculate which level the small power-of-two miptree begins at. The
86*61046927SAndroid Build Coastguard Worker     * power-of-two miptree is used when either the width or the height is
87*61046927SAndroid Build Coastguard Worker     * smaller than a single large tile.
88*61046927SAndroid Build Coastguard Worker     */
89*61046927SAndroid Build Coastguard Worker    unsigned pot_level = 0;
90*61046927SAndroid Build Coastguard Worker    unsigned pot_w_px = bw_px * w_el;
91*61046927SAndroid Build Coastguard Worker    unsigned pot_h_px = bh_px * h_el;
92*61046927SAndroid Build Coastguard Worker    do {
93*61046927SAndroid Build Coastguard Worker       unsigned pot_w_el = util_format_get_nblocksx(layout->format, pot_w_px);
94*61046927SAndroid Build Coastguard Worker       unsigned pot_h_el = util_format_get_nblocksy(layout->format, pot_h_px);
95*61046927SAndroid Build Coastguard Worker       if (pot_w_el < tilesize_el.width_el || pot_h_el < tilesize_el.height_el)
96*61046927SAndroid Build Coastguard Worker          break;
97*61046927SAndroid Build Coastguard Worker       pot_w_px = u_minify(pot_w_px, 1);
98*61046927SAndroid Build Coastguard Worker       pot_h_px = u_minify(pot_h_px, 1);
99*61046927SAndroid Build Coastguard Worker       pot_level++;
100*61046927SAndroid Build Coastguard Worker    } while (1);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    /* First allocate the large miptree. All tiles in the large miptree are of
103*61046927SAndroid Build Coastguard Worker     * size tilesize_el and have their dimensions given by stx/sty/sarea.
104*61046927SAndroid Build Coastguard Worker     */
105*61046927SAndroid Build Coastguard Worker    for (unsigned l = 0; l < MIN2(pot_level, layout->levels); ++l) {
106*61046927SAndroid Build Coastguard Worker       unsigned tiles = (sarea_tiles >> (2 * l));
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker       bool pad_left = (stx_tiles & BITFIELD_MASK(l));
109*61046927SAndroid Build Coastguard Worker       bool pad_bottom = (sty_tiles & BITFIELD_MASK(l));
110*61046927SAndroid Build Coastguard Worker       bool pad_corner = pad_left && pad_bottom;
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker       if (pad_left)
113*61046927SAndroid Build Coastguard Worker          tiles += (sty_tiles >> l);
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker       if (pad_bottom)
116*61046927SAndroid Build Coastguard Worker          tiles += (stx_tiles >> l);
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker       if (pad_corner)
119*61046927SAndroid Build Coastguard Worker          tiles += 1;
120*61046927SAndroid Build Coastguard Worker 
121*61046927SAndroid Build Coastguard Worker       unsigned size_el = tiles * tilesize_el.width_el * tilesize_el.height_el;
122*61046927SAndroid Build Coastguard Worker       layout->level_offsets_B[l] = offset_B;
123*61046927SAndroid Build Coastguard Worker       offset_B = ALIGN_POT(offset_B + (blocksize_B * size_el), AIL_CACHELINE);
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker       layout->stride_el[l] = util_format_get_nblocksx(
126*61046927SAndroid Build Coastguard Worker          layout->format, u_minify(layout->width_px, l));
127*61046927SAndroid Build Coastguard Worker 
128*61046927SAndroid Build Coastguard Worker       /* Compressed textures pad the stride in this case */
129*61046927SAndroid Build Coastguard Worker       if (compressed && pad_left)
130*61046927SAndroid Build Coastguard Worker          layout->stride_el[l]++;
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker       layout->tilesize_el[l] = tilesize_el;
133*61046927SAndroid Build Coastguard Worker    }
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    /* Then begin the POT miptree. Note that we round up to a power-of-two
136*61046927SAndroid Build Coastguard Worker     * outside the loop. That ensures correct handling of cases like 33x33
137*61046927SAndroid Build Coastguard Worker     * images, where the round-down error of right-shifting could cause incorrect
138*61046927SAndroid Build Coastguard Worker     * tile size calculations.
139*61046927SAndroid Build Coastguard Worker     */
140*61046927SAndroid Build Coastguard Worker    unsigned potw_el, poth_el;
141*61046927SAndroid Build Coastguard Worker    if (compressed) {
142*61046927SAndroid Build Coastguard Worker       /* Compressed formats round then minify instead of minifying then rounding
143*61046927SAndroid Build Coastguard Worker        */
144*61046927SAndroid Build Coastguard Worker       potw_el = u_minify(util_next_power_of_two(w_el), pot_level);
145*61046927SAndroid Build Coastguard Worker       poth_el = u_minify(util_next_power_of_two(h_el), pot_level);
146*61046927SAndroid Build Coastguard Worker    } else {
147*61046927SAndroid Build Coastguard Worker       potw_el = util_next_power_of_two(u_minify(w_el, pot_level));
148*61046927SAndroid Build Coastguard Worker       poth_el = util_next_power_of_two(u_minify(h_el, pot_level));
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    /* Finally we allocate the POT miptree, starting at level pot_level. Each
152*61046927SAndroid Build Coastguard Worker     * level uses the largest power-of-two tile that fits the level.
153*61046927SAndroid Build Coastguard Worker     */
154*61046927SAndroid Build Coastguard Worker    for (unsigned l = pot_level; l < layout->levels; ++l) {
155*61046927SAndroid Build Coastguard Worker       unsigned size_el = potw_el * poth_el;
156*61046927SAndroid Build Coastguard Worker       layout->level_offsets_B[l] = offset_B;
157*61046927SAndroid Build Coastguard Worker       offset_B = ALIGN_POT(offset_B + (blocksize_B * size_el), AIL_CACHELINE);
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker       /* The tilesize is based on the true mipmap level size, not the POT
160*61046927SAndroid Build Coastguard Worker        * rounded size, except for compressed textures */
161*61046927SAndroid Build Coastguard Worker       unsigned tilesize_el;
162*61046927SAndroid Build Coastguard Worker       if (compressed)
163*61046927SAndroid Build Coastguard Worker          tilesize_el = util_next_power_of_two(MIN2(potw_el, poth_el));
164*61046927SAndroid Build Coastguard Worker       else
165*61046927SAndroid Build Coastguard Worker          tilesize_el = util_next_power_of_two(u_minify(MIN2(w_el, h_el), l));
166*61046927SAndroid Build Coastguard Worker       layout->tilesize_el[l] = (struct ail_tile){tilesize_el, tilesize_el};
167*61046927SAndroid Build Coastguard Worker       layout->stride_el[l] = util_format_get_nblocksx(
168*61046927SAndroid Build Coastguard Worker          layout->format, u_minify(layout->width_px, l));
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker       potw_el = u_minify(potw_el, 1);
171*61046927SAndroid Build Coastguard Worker       poth_el = u_minify(poth_el, 1);
172*61046927SAndroid Build Coastguard Worker    }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    /* Add the end offset so we can easily recover the size of a level */
175*61046927SAndroid Build Coastguard Worker    assert(layout->levels < ARRAY_SIZE(layout->level_offsets_B));
176*61046927SAndroid Build Coastguard Worker    layout->level_offsets_B[layout->levels] = offset_B;
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    /* Align layer size if we have mipmaps and one miptree is larger than one
179*61046927SAndroid Build Coastguard Worker     * page */
180*61046927SAndroid Build Coastguard Worker    layout->page_aligned_layers = layout->levels != 1 && offset_B > AIL_PAGESIZE;
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker    /* Single-layer images are not padded unless they are Z/S */
183*61046927SAndroid Build Coastguard Worker    bool zs = util_format_is_depth_or_stencil(layout->format);
184*61046927SAndroid Build Coastguard Worker    if (layout->depth_px == 1 && !zs)
185*61046927SAndroid Build Coastguard Worker       layout->page_aligned_layers = false;
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    /* For writable images, we require page-aligned layers. This appears to be
188*61046927SAndroid Build Coastguard Worker     * required for PBE stores, including block stores for colour rendering.
189*61046927SAndroid Build Coastguard Worker     * Likewise, we specify the ZLS layer stride in pages, so we need
190*61046927SAndroid Build Coastguard Worker     * page-aligned layers for renderable depth/stencil targets.
191*61046927SAndroid Build Coastguard Worker     */
192*61046927SAndroid Build Coastguard Worker    layout->page_aligned_layers |= layout->writeable_image;
193*61046927SAndroid Build Coastguard Worker    layout->page_aligned_layers |= layout->renderable && layout->depth_px > 1;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    if (layout->page_aligned_layers)
196*61046927SAndroid Build Coastguard Worker       layout->layer_stride_B = ALIGN_POT(offset_B, AIL_PAGESIZE);
197*61046927SAndroid Build Coastguard Worker    else
198*61046927SAndroid Build Coastguard Worker       layout->layer_stride_B = offset_B;
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker    layout->size_B = (uint64_t)layout->layer_stride_B * layout->depth_px;
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker static void
ail_initialize_compression(struct ail_layout * layout)204*61046927SAndroid Build Coastguard Worker ail_initialize_compression(struct ail_layout *layout)
205*61046927SAndroid Build Coastguard Worker {
206*61046927SAndroid Build Coastguard Worker    assert(!util_format_is_compressed(layout->format) &&
207*61046927SAndroid Build Coastguard Worker           "Compressed pixel formats not supported");
208*61046927SAndroid Build Coastguard Worker    assert(util_format_get_blockwidth(layout->format) == 1);
209*61046927SAndroid Build Coastguard Worker    assert(util_format_get_blockheight(layout->format) == 1);
210*61046927SAndroid Build Coastguard Worker 
211*61046927SAndroid Build Coastguard Worker    unsigned width_sa =
212*61046927SAndroid Build Coastguard Worker       ail_effective_width_sa(layout->width_px, layout->sample_count_sa);
213*61046927SAndroid Build Coastguard Worker    unsigned height_sa =
214*61046927SAndroid Build Coastguard Worker       ail_effective_height_sa(layout->height_px, layout->sample_count_sa);
215*61046927SAndroid Build Coastguard Worker 
216*61046927SAndroid Build Coastguard Worker    assert(width_sa >= 16 && "Small textures are never compressed");
217*61046927SAndroid Build Coastguard Worker    assert(height_sa >= 16 && "Small textures are never compressed");
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    layout->metadata_offset_B = layout->size_B;
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    width_sa = ALIGN_POT(width_sa, 16);
222*61046927SAndroid Build Coastguard Worker    height_sa = ALIGN_POT(height_sa, 16);
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker    unsigned compbuf_B = 0;
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    for (unsigned l = 0; l < layout->levels; ++l) {
227*61046927SAndroid Build Coastguard Worker       if (!ail_is_level_compressed(layout, l))
228*61046927SAndroid Build Coastguard Worker          break;
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker       layout->level_offsets_compressed_B[l] = compbuf_B;
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker       /* The metadata buffer contains 8 bytes per 16x16 compression tile.
233*61046927SAndroid Build Coastguard Worker        * Addressing is fully twiddled, so both width and height are padded to
234*61046927SAndroid Build Coastguard Worker        * powers-of-two.
235*61046927SAndroid Build Coastguard Worker        */
236*61046927SAndroid Build Coastguard Worker       unsigned w_tl = DIV_ROUND_UP(util_next_power_of_two(width_sa), 16);
237*61046927SAndroid Build Coastguard Worker       unsigned h_tl = DIV_ROUND_UP(util_next_power_of_two(height_sa), 16);
238*61046927SAndroid Build Coastguard Worker       unsigned B_per_tl_2 = 8;
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker       compbuf_B += ALIGN_POT(w_tl * h_tl * B_per_tl_2, AIL_CACHELINE);
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker       width_sa = DIV_ROUND_UP(width_sa, 2);
243*61046927SAndroid Build Coastguard Worker       height_sa = DIV_ROUND_UP(height_sa, 2);
244*61046927SAndroid Build Coastguard Worker    }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker    layout->compression_layer_stride_B = compbuf_B;
247*61046927SAndroid Build Coastguard Worker    layout->size_B +=
248*61046927SAndroid Build Coastguard Worker       (uint64_t)(layout->compression_layer_stride_B * layout->depth_px);
249*61046927SAndroid Build Coastguard Worker }
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker void
ail_make_miptree(struct ail_layout * layout)252*61046927SAndroid Build Coastguard Worker ail_make_miptree(struct ail_layout *layout)
253*61046927SAndroid Build Coastguard Worker {
254*61046927SAndroid Build Coastguard Worker    assert(layout->width_px >= 1 && "Invalid dimensions");
255*61046927SAndroid Build Coastguard Worker    assert(layout->height_px >= 1 && "Invalid dimensions");
256*61046927SAndroid Build Coastguard Worker    assert(layout->depth_px >= 1 && "Invalid dimensions");
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    if (layout->tiling == AIL_TILING_LINEAR) {
259*61046927SAndroid Build Coastguard Worker       assert(layout->levels == 1 && "Invalid linear layout");
260*61046927SAndroid Build Coastguard Worker       assert(layout->sample_count_sa == 1 &&
261*61046927SAndroid Build Coastguard Worker              "Multisampled linear layouts not supported");
262*61046927SAndroid Build Coastguard Worker       assert(util_format_get_blockwidth(layout->format) == 1 &&
263*61046927SAndroid Build Coastguard Worker              "Strided linear block formats unsupported");
264*61046927SAndroid Build Coastguard Worker       assert(util_format_get_blockheight(layout->format) == 1 &&
265*61046927SAndroid Build Coastguard Worker              "Strided linear block formats unsupported");
266*61046927SAndroid Build Coastguard Worker    } else {
267*61046927SAndroid Build Coastguard Worker       assert(layout->linear_stride_B == 0 && "Invalid nonlinear layout");
268*61046927SAndroid Build Coastguard Worker       assert(layout->levels >= 1 && "Invalid dimensions");
269*61046927SAndroid Build Coastguard Worker       assert(layout->sample_count_sa >= 1 && "Invalid sample count");
270*61046927SAndroid Build Coastguard Worker    }
271*61046927SAndroid Build Coastguard Worker 
272*61046927SAndroid Build Coastguard Worker    assert(!(layout->writeable_image &&
273*61046927SAndroid Build Coastguard Worker             layout->tiling == AIL_TILING_TWIDDLED_COMPRESSED) &&
274*61046927SAndroid Build Coastguard Worker           "Writeable images must not be compressed");
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    /* Hardware strides are based on the maximum number of levels, so always
277*61046927SAndroid Build Coastguard Worker     * allocate them all.
278*61046927SAndroid Build Coastguard Worker     */
279*61046927SAndroid Build Coastguard Worker    if (layout->levels > 1) {
280*61046927SAndroid Build Coastguard Worker       unsigned major_axis_px = MAX2(layout->width_px, layout->height_px);
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker       if (layout->mipmapped_z)
283*61046927SAndroid Build Coastguard Worker          major_axis_px = MAX2(major_axis_px, layout->depth_px);
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker       layout->levels = util_logbase2(major_axis_px) + 1;
286*61046927SAndroid Build Coastguard Worker    }
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker    assert(util_format_get_blockdepth(layout->format) == 1 &&
289*61046927SAndroid Build Coastguard Worker           "Deep formats unsupported");
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    switch (layout->tiling) {
292*61046927SAndroid Build Coastguard Worker    case AIL_TILING_LINEAR:
293*61046927SAndroid Build Coastguard Worker       ail_initialize_linear(layout);
294*61046927SAndroid Build Coastguard Worker       break;
295*61046927SAndroid Build Coastguard Worker    case AIL_TILING_TWIDDLED:
296*61046927SAndroid Build Coastguard Worker       ail_initialize_twiddled(layout);
297*61046927SAndroid Build Coastguard Worker       break;
298*61046927SAndroid Build Coastguard Worker    case AIL_TILING_TWIDDLED_COMPRESSED:
299*61046927SAndroid Build Coastguard Worker       ail_initialize_twiddled(layout);
300*61046927SAndroid Build Coastguard Worker       ail_initialize_compression(layout);
301*61046927SAndroid Build Coastguard Worker       break;
302*61046927SAndroid Build Coastguard Worker    default:
303*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported tiling");
304*61046927SAndroid Build Coastguard Worker    }
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker    layout->size_B = ALIGN_POT(layout->size_B, AIL_CACHELINE);
307*61046927SAndroid Build Coastguard Worker    assert(layout->size_B > 0 && "Invalid dimensions");
308*61046927SAndroid Build Coastguard Worker }
309