diff --git a/src/asahi/layout/layout.c b/src/asahi/layout/layout.c index db813e7fdfc..685867f2033 100644 --- a/src/asahi/layout/layout.c +++ b/src/asahi/layout/layout.c @@ -25,23 +25,6 @@ ail_initialize_linear(struct ail_layout *layout) layout->size_B = layout->layer_stride_B * layout->depth_px; } -/* - * Calculate the minimum integer l such that x 2^-l < y, where x is an integer - * and y is a power-of-two. - */ -static unsigned -ail_min_mip_below(unsigned x, unsigned y) -{ - assert(util_is_power_of_two_nonzero(y)); - - if (x < y) - return 0; - else if (util_is_power_of_two_or_zero(x)) - return util_logbase2(x) - util_logbase2(y) + 1; - else - return util_logbase2_ceil(x) - util_logbase2(y); -} - /* * Get the maximum tile size possible for a given block size. This satisfy * width * height * blocksize = 16384 = page size, so each tile is one page. @@ -87,6 +70,9 @@ ail_initialize_twiddled(struct ail_layout *layout) unsigned blocksize_B = ail_get_block_size_B(layout); unsigned w_el = util_format_get_nblocksx(layout->format, layout->width_px); unsigned h_el = util_format_get_nblocksy(layout->format, layout->height_px); + unsigned bw_px = util_format_get_blockwidth(layout->format); + unsigned bh_px = util_format_get_blockheight(layout->format); + bool compressed = util_format_is_compressed(layout->format); /* Calculate the tile size used for the large miptree, and the dimensions of * level 0 given that tile size. @@ -100,8 +86,18 @@ ail_initialize_twiddled(struct ail_layout *layout) * power-of-two miptree is used when either the width or the height is * smaller than a single large tile. */ - unsigned pot_level = MIN2(ail_min_mip_below(w_el, tilesize_el.width_el), - ail_min_mip_below(h_el, tilesize_el.height_el)); + unsigned pot_level = 0; + unsigned pot_w_px = bw_px * w_el; + unsigned pot_h_px = bh_px * h_el; + do { + unsigned pot_w_el = util_format_get_nblocksx(layout->format, pot_w_px); + unsigned pot_h_el = util_format_get_nblocksy(layout->format, pot_h_px); + if (pot_w_el < tilesize_el.width_el || pot_h_el < tilesize_el.height_el) + break; + pot_w_px = u_minify(pot_w_px, 1); + pot_h_px = u_minify(pot_h_px, 1); + pot_level++; + } while (1); /* First allocate the large miptree. All tiles in the large miptree are of * size tilesize_el and have their dimensions given by stx/sty/sarea. @@ -134,8 +130,16 @@ ail_initialize_twiddled(struct ail_layout *layout) * images, where the round-down error of right-shifting could cause incorrect * tile size calculations. */ - unsigned potw_el = util_next_power_of_two(u_minify(w_el, pot_level)); - unsigned poth_el = util_next_power_of_two(u_minify(h_el, pot_level)); + unsigned potw_el, poth_el; + if (compressed) { + /* Compressed formats round then minify instead of minifying then rounding + */ + potw_el = u_minify(util_next_power_of_two(w_el), pot_level); + poth_el = u_minify(util_next_power_of_two(h_el), pot_level); + } else { + potw_el = util_next_power_of_two(u_minify(w_el, pot_level)); + poth_el = util_next_power_of_two(u_minify(h_el, pot_level)); + } /* Finally we allocate the POT miptree, starting at level pot_level. Each * level uses the largest power-of-two tile that fits the level.