diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c index f940557a113..3fd8c5ce28e 100644 --- a/src/gallium/drivers/panfrost/pan_job.c +++ b/src/gallium/drivers/panfrost/pan_job.c @@ -922,93 +922,6 @@ panfrost_batch_adjust_stack_size(struct panfrost_batch *batch) } } -/* Helper to smear a 32-bit color across 128-bit components */ - -static void -pan_pack_color_32(uint32_t *packed, uint32_t v) -{ - for (unsigned i = 0; i < 4; ++i) - packed[i] = v; -} - -static void -pan_pack_color_64(uint32_t *packed, uint32_t lo, uint32_t hi) -{ - for (unsigned i = 0; i < 4; i += 2) { - packed[i + 0] = lo; - packed[i + 1] = hi; - } -} - -static void -pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format) -{ - /* Alpha magicked to 1.0 if there is no alpha */ - - bool has_alpha = util_format_has_alpha(format); - float clear_alpha = has_alpha ? color->f[3] : 1.0f; - - /* Packed color depends on the framebuffer format */ - - const struct util_format_description *desc = - util_format_description(format); - - if (util_format_is_rgba8_variant(desc) && desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB) { - pan_pack_color_32(packed, - ((uint32_t) float_to_ubyte(clear_alpha) << 24) | - ((uint32_t) float_to_ubyte(color->f[2]) << 16) | - ((uint32_t) float_to_ubyte(color->f[1]) << 8) | - ((uint32_t) float_to_ubyte(color->f[0]) << 0)); - } else if (format == PIPE_FORMAT_B5G6R5_UNORM) { - /* First, we convert the components to R5, G6, B5 separately */ - unsigned r5 = _mesa_roundevenf(SATURATE(color->f[0]) * 31.0); - unsigned g6 = _mesa_roundevenf(SATURATE(color->f[1]) * 63.0); - unsigned b5 = _mesa_roundevenf(SATURATE(color->f[2]) * 31.0); - - /* Then we pack into a sparse u32. TODO: Why these shifts? */ - pan_pack_color_32(packed, (b5 << 25) | (g6 << 14) | (r5 << 5)); - } else if (format == PIPE_FORMAT_B4G4R4A4_UNORM) { - /* Convert to 4-bits */ - unsigned r4 = _mesa_roundevenf(SATURATE(color->f[0]) * 15.0); - unsigned g4 = _mesa_roundevenf(SATURATE(color->f[1]) * 15.0); - unsigned b4 = _mesa_roundevenf(SATURATE(color->f[2]) * 15.0); - unsigned a4 = _mesa_roundevenf(SATURATE(clear_alpha) * 15.0); - - /* Pack on *byte* intervals */ - pan_pack_color_32(packed, (a4 << 28) | (b4 << 20) | (g4 << 12) | (r4 << 4)); - } else if (format == PIPE_FORMAT_B5G5R5A1_UNORM) { - /* Scale as expected but shift oddly */ - unsigned r5 = _mesa_roundevenf(SATURATE(color->f[0]) * 31.0); - unsigned g5 = _mesa_roundevenf(SATURATE(color->f[1]) * 31.0); - unsigned b5 = _mesa_roundevenf(SATURATE(color->f[2]) * 31.0); - unsigned a1 = _mesa_roundevenf(SATURATE(clear_alpha) * 1.0); - - pan_pack_color_32(packed, (a1 << 31) | (b5 << 25) | (g5 << 15) | (r5 << 5)); - } else { - /* Otherwise, it's generic subject to replication */ - - union util_color out = { 0 }; - unsigned size = util_format_get_blocksize(format); - - util_pack_color(color->f, format, &out); - - if (size == 1) { - unsigned b = out.ui[0]; - unsigned s = b | (b << 8); - pan_pack_color_32(packed, s | (s << 16)); - } else if (size == 2) - pan_pack_color_32(packed, out.ui[0] | (out.ui[0] << 16)); - else if (size == 3 || size == 4) - pan_pack_color_32(packed, out.ui[0]); - else if (size == 6 || size == 8) - pan_pack_color_64(packed, out.ui[0], out.ui[1]); - else if (size == 12 || size == 16) - memcpy(packed, out.ui, 16); - else - unreachable("Unknown generic format size packing clear colour"); - } -} - void panfrost_batch_clear(struct panfrost_batch *batch, unsigned buffers, diff --git a/src/panfrost/lib/meson.build b/src/panfrost/lib/meson.build index f01cb6c19b2..551e6304677 100644 --- a/src/panfrost/lib/meson.build +++ b/src/panfrost/lib/meson.build @@ -56,6 +56,7 @@ libpanfrost_lib_files = files( 'pan_bo.c', 'pan_blend.c', 'pan_blitter.c', + 'pan_clear.c', 'pan_cs.c', 'pan_indirect_dispatch.c', 'pan_indirect_draw.c', diff --git a/src/panfrost/lib/pan_clear.c b/src/panfrost/lib/pan_clear.c new file mode 100644 index 00000000000..6247348565d --- /dev/null +++ b/src/panfrost/lib/pan_clear.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2019-2021 Collabora, Ltd. + * Copyright (C) 2019 Alyssa Rosenzweig + * + * 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 (including the next + * paragraph) 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. + * + */ + +#include +#include "pan_util.h" +#include "pan_format.h" +#include "gallium/auxiliary/util/u_pack_color.h" +#include "util/rounding.h" +#include "util/format_srgb.h" + +/* Clear colours are packed as the internal format of the tilebuffer, looked up + * in the blendable formats table given the render target format. + * + * Raw formats may emulate arbitrary formats with blend shaders. For these, we + * defer to util_pack_colour to pack in the API format. + * + * Blendable formats, on the other hand, include extra "fractional" bits in the + * tilebuffer for dithering. These have a packed fixed-point representation: + * for a channel with m integer bits and n fractional bits, multiply by ((2^m) + * - 1) * 2^n and round to the nearest even. + */ + +/* Replicate a 32-bit value to fill 128-bit */ + +static void +pan_pack_color_32(uint32_t *packed, uint32_t v) +{ + for (unsigned i = 0; i < 4; ++i) + packed[i] = v; +} + +/* For m integer bits and n fractional bits, calculate the conversion factor, + * multiply the source value, and convert to integer rounding to even */ + +static inline uint32_t +float_to_fixed(float f, unsigned bits_int, unsigned bits_frac) +{ + float factor = ((1 << bits_int) - 1) << bits_frac; + return _mesa_roundevenf(f * factor); +} + +/* These values are shared across hardware versions. Don't include GenXML. */ +enum mali_color_buffer_internal_format { + MALI_COLOR_BUFFER_INTERNAL_FORMAT_RAW = 0, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R8G8B8A8 = 1, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R10G10B10A2 = 2, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R8G8B8A2 = 3, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R4G4B4A4 = 4, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R5G6B5A0 = 5, + MALI_COLOR_BUFFER_INTERNAL_FORMAT_R5G5B5A1 = 6, + MALI_COLOR_BUFFER_NUM_FORMATS, +}; + +struct mali_tib_layout { + unsigned int_r, frac_r; + unsigned int_g, frac_g; + unsigned int_b, frac_b; + unsigned int_a, frac_a; +}; + +static const struct mali_tib_layout tib_layouts[MALI_COLOR_BUFFER_NUM_FORMATS] = { + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R8G8B8A8] = { 8, 0, 8, 0, 8, 0, 8, 0 }, + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R10G10B10A2] = { 10, 0, 10, 0, 10, 0, 2, 0 }, + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R8G8B8A2] = { 8, 2, 8, 2, 8, 2, 2, 0 }, + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R4G4B4A4] = { 4, 4, 4, 4, 4, 4, 4, 4 }, + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R5G6B5A0] = { 5, 5, 6, 4, 5, 5, 0, 2 }, + [MALI_COLOR_BUFFER_INTERNAL_FORMAT_R5G5B5A1] = { 5, 5, 5, 5, 5, 5, 1, 1 }, +}; + +/* Raw values are stored as-is but replicated for multisampling */ + +static void +pan_pack_raw(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format) +{ + union util_color out = { 0 }; + unsigned size = util_format_get_blocksize(format); + assert(size <= 16); + + util_pack_color(color->f, format, &out); + + if (size == 1) { + unsigned s = out.ui[0] | (out.ui[0] << 8); + pan_pack_color_32(packed, s | (s << 16)); + } else if (size == 2) + pan_pack_color_32(packed, out.ui[0] | (out.ui[0] << 16)); + else if (size <= 4) + pan_pack_color_32(packed, out.ui[0]); + else if (size <= 8) { + memcpy(packed + 0, out.ui, 8); + memcpy(packed + 2, out.ui, 8); + } else { + memcpy(packed, out.ui, 16); + } +} + +void +pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format) +{ + /* Set of blendable formats is common across versions. TODO: v9 */ + enum mali_color_buffer_internal_format internal = + panfrost_blendable_formats_v7[format].internal; + + if (internal == MALI_COLOR_BUFFER_INTERNAL_FORMAT_RAW) { + pan_pack_raw(packed, color, format); + return; + } + + /* Saturate to [0, 1] by definition of UNORM. Prevents overflow. */ + float r = SATURATE(color->f[0]); + float g = SATURATE(color->f[1]); + float b = SATURATE(color->f[2]); + float a = SATURATE(color->f[3]); + + /* Fill in alpha = 1.0 by default */ + if (!util_format_has_alpha(format)) + a = 1.0; + + /* Convert colourspace while we still have floats */ + if (util_format_is_srgb(format)) { + r = util_format_linear_to_srgb_float(r); + g = util_format_linear_to_srgb_float(g); + b = util_format_linear_to_srgb_float(b); + } + + /* Look up the layout of the tilebuffer */ + assert(internal < MALI_COLOR_BUFFER_NUM_FORMATS); + struct mali_tib_layout l = tib_layouts[internal]; + + unsigned count_r = l.int_r + l.frac_r; + unsigned count_g = l.int_g + l.frac_g + count_r; + unsigned count_b = l.int_b + l.frac_b + count_g; + ASSERTED unsigned count_a = l.int_a + l.frac_a + count_b; + + /* Must fill the word */ + 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; + + pan_pack_color_32(packed, ur | ug | ub | ua); +} diff --git a/src/panfrost/lib/pan_util.h b/src/panfrost/lib/pan_util.h index 3a13b5e11d5..099f4d75076 100644 --- a/src/panfrost/lib/pan_util.h +++ b/src/panfrost/lib/pan_util.h @@ -28,6 +28,10 @@ #ifndef PAN_UTIL_H #define PAN_UTIL_H +#include +#include +#include "util/format/u_format.h" + #define PAN_DBG_PERF 0x0001 #define PAN_DBG_TRACE 0x0002 #define PAN_DBG_DEQP 0x0004 @@ -43,6 +47,8 @@ #define PAN_DBG_LINEAR 0x1000 #define PAN_DBG_NO_CACHE 0x2000 +struct panfrost_device; + unsigned panfrost_translate_swizzle_4(const unsigned char swizzle[4]); @@ -54,4 +60,7 @@ panfrost_format_to_bifrost_blend(const struct panfrost_device *dev, enum pipe_format format, bool dithered); +void +pan_pack_color(uint32_t *packed, const union pipe_color_union *color, enum pipe_format format); + #endif /* PAN_UTIL_H */