Commit 2ac29047 authored by Alyssa Rosenzweig's avatar Alyssa Rosenzweig 💜
Browse files

panfrost: Handle non-dithered clear colours

In b9c095cc ("panfrost: Rewrite the clear colour packing code"),
packing of clear colours was corrected to use the tilebuffer's
fractional bits, fixing dithering of the clear colour with formats like
RGB565. Unfortunately, that commit did so unconditionally. If the
framebuffer is dithered, but dithering is disabled at the time of
the clear, we would incorrectly dither the clear.

This is a regression, as the old (broken) code passed the relevant CTS
test. What's the catch? Depending on dither state, there are two
formulas to pack tilebuffer colours. We need to handle both. Fixes
KHR-GLES31.core.draw_buffers_indexed.color_masks.

Fixes: b9c095cc

 ("panfrost: Rewrite the clear colour packing code")
Signed-off-by: Alyssa Rosenzweig's avatarAlyssa Rosenzweig <alyssa@collabora.com>
parent 7fef42a3
......@@ -936,7 +936,7 @@ panfrost_batch_clear(struct panfrost_batch *batch,
continue;
enum pipe_format format = ctx->pipe_framebuffer.cbufs[i]->format;
pan_pack_color(batch->clear_color[i], color, format);
pan_pack_color(batch->clear_color[i], color, format, false);
}
}
......
......@@ -52,13 +52,22 @@ pan_pack_color_32(uint32_t *packed, uint32_t v)
}
/* For m integer bits and n fractional bits, calculate the conversion factor,
* multiply the source value, and convert to integer rounding to even */
* multiply the source value, and convert to integer rounding to even. When
* dithering, the fractional bits are used. When not dithered, only the integer
* bits are used and the fractional bits must remain zero. */
static inline uint32_t
float_to_fixed(float f, unsigned bits_int, unsigned bits_frac)
float_to_fixed(float f, unsigned bits_int, unsigned bits_frac, bool dither)
{
float factor = ((1 << bits_int) - 1) << bits_frac;
return _mesa_roundevenf(f * factor);
uint32_t m = (1 << bits_int) - 1;
if (dither) {
float factor = m << bits_frac;
return _mesa_roundevenf(f * factor);
} else {
uint32_t v = _mesa_roundevenf(f * (float) m);
return v << bits_frac;
}
}
/* These values are shared across hardware versions. Don't include GenXML. */
......@@ -116,7 +125,8 @@ pan_pack_raw(uint32_t *packed, const union pipe_color_union *color, enum pipe_fo
}
void
pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format)
pan_pack_color(uint32_t *packed, const union pipe_color_union *color,
enum pipe_format format, bool dithered)
{
/* Set of blendable formats is common across versions. TODO: v9 */
enum mali_color_buffer_internal_format internal =
......@@ -157,10 +167,10 @@ pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_
assert(count_a == 32);
/* Convert the transformed float colour to the given layout */
uint32_t ur = float_to_fixed(r, l.int_r, l.frac_r) << 0;
uint32_t ug = float_to_fixed(g, l.int_g, l.frac_g) << count_r;
uint32_t ub = float_to_fixed(b, l.int_b, l.frac_b) << count_g;
uint32_t ua = float_to_fixed(a, l.int_a, l.frac_a) << count_b;
uint32_t ur = float_to_fixed(r, l.int_r, l.frac_r, dithered) << 0;
uint32_t ug = float_to_fixed(g, l.int_g, l.frac_g, dithered) << count_r;
uint32_t ub = float_to_fixed(b, l.int_b, l.frac_b, dithered) << count_g;
uint32_t ua = float_to_fixed(a, l.int_a, l.frac_a, dithered) << count_b;
pan_pack_color_32(packed, ur | ug | ub | ua);
}
......@@ -61,6 +61,7 @@ panfrost_format_to_bifrost_blend(const struct panfrost_device *dev,
bool dithered);
void
pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format);
pan_pack_color(uint32_t *packed, const union pipe_color_union *color,
enum pipe_format format, bool dithered);
#endif /* PAN_UTIL_H */
......@@ -110,7 +110,7 @@ int main(int argc, const char **argv)
for (unsigned i = 0; i < ARRAY_SIZE(clear_tests); ++i) {
struct test T = clear_tests[i];
uint32_t packed[4];
pan_pack_color(&packed[0], &T.colour, T.format);
pan_pack_color(&packed[0], &T.colour, T.format, T.dithered);
ASSERT_EQ(T.packed, packed);
}
......
......@@ -593,7 +593,7 @@ panvk_cmd_prepare_clear_values(struct panvk_cmd_buffer *cmdbuf,
}
} else if (attachment->load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
union pipe_color_union *col = (union pipe_color_union *) &in[i].color;
pan_pack_color(cmdbuf->state.clear[i].color, col, fmt);
pan_pack_color(cmdbuf->state.clear[i].color, col, fmt, false);
}
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment