diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index ba0e5b2361b..3d17d08c757 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -212,6 +212,25 @@ panfrost_create_sampler_state( struct panfrost_sampler_state *so = CALLOC_STRUCT(panfrost_sampler_state); so->base = *cso; +#if PAN_ARCH == 7 + /* On v7, pan_texture.c composes the API swizzle with a bijective + * swizzle derived from the format, to allow more formats than the + * hardware otherwise supports. When packing border colours, we need to + * undo this bijection, by swizzling with its inverse. + */ + unsigned mali_format = panfrost_pipe_format_v7[cso->border_color_format].hw; + enum mali_rgb_component_order order = mali_format & BITFIELD_MASK(12); + + unsigned char inverted_swizzle[4]; + panfrost_invert_swizzle(GENX(pan_decompose_swizzle)(order).post, + inverted_swizzle); + + util_format_apply_color_swizzle(&so->base.border_color, + &cso->border_color, + inverted_swizzle, + false /* is_integer (irrelevant) */); +#endif + bool using_nearest = cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST; pan_pack(&so->hw, SAMPLER, cfg) { @@ -231,10 +250,10 @@ panfrost_create_sampler_state( cfg.compare_function = panfrost_sampler_compare_func(cso); cfg.seamless_cube_map = cso->seamless_cube_map; - cfg.border_color_r = cso->border_color.ui[0]; - cfg.border_color_g = cso->border_color.ui[1]; - cfg.border_color_b = cso->border_color.ui[2]; - cfg.border_color_a = cso->border_color.ui[3]; + cfg.border_color_r = so->base.border_color.ui[0]; + cfg.border_color_g = so->base.border_color.ui[1]; + cfg.border_color_b = so->base.border_color.ui[2]; + cfg.border_color_a = so->base.border_color.ui[3]; #if PAN_ARCH >= 6 if (cso->max_anisotropy > 1) { diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index 29ba7016b98..5c8072fc3e0 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -202,6 +202,16 @@ panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 16; + /* v7 (only) restricts component orders with AFBC. To workaround, we + * compose format swizzles with texture swizzles. pan_texture.c motsly + * handles this but we need to fix up the border colour. + */ + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + if (dev->arch == 7) + return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO; + else + return 0; + case PIPE_CAP_MAX_TEXEL_BUFFER_ELEMENTS_UINT: return 65536; diff --git a/src/panfrost/lib/pan_afbc.c b/src/panfrost/lib/pan_afbc.c index 83225d98d52..7ad89c517e5 100644 --- a/src/panfrost/lib/pan_afbc.c +++ b/src/panfrost/lib/pan_afbc.c @@ -139,11 +139,7 @@ panfrost_afbc_format(unsigned arch, enum pipe_format format) */ format = util_format_linear(format); - /* Don't allow swizzled formats on v7 */ - if (arch == 7 && format != unswizzled_format(format)) - return PAN_AFBC_MODE_INVALID; - - /* Otherwise swizzling doesn't affect AFBC */ + /* We handle swizzling orthogonally to AFBC */ format = unswizzled_format(format); switch (format) { diff --git a/src/panfrost/lib/pan_format.c b/src/panfrost/lib/pan_format.c index e27f207b8cf..b1d1185bde9 100644 --- a/src/panfrost/lib/pan_format.c +++ b/src/panfrost/lib/pan_format.c @@ -593,3 +593,55 @@ const struct panfrost_format GENX(panfrost_pipe_format)[PIPE_FORMAT_COUNT] = { #endif }; + +#if PAN_ARCH == 7 +/* + * Decompose a component ordering swizzle into a component ordering (applied + * first) and a swizzle (applied second). The output ordering "pre" is allowed + * with compression and the swizzle "post" is a bijection. + * + * These properties allow any component ordering to be used with compression, by + * using the output "pre" ordering, composing the API swizzle with the "post" + * ordering, and applying the inverse of the "post" ordering to the border + * colour to undo what we compose into the API swizzle. + * + * Note that "post" is a swizzle, not a component ordering, which means it is + * inverted from the ordering. E.g. ARGB ordering uses a GBAR (YZWX) swizzle. + */ +struct pan_decomposed_swizzle +GENX(pan_decompose_swizzle)(enum mali_rgb_component_order order) +{ +#define CASE(case_, pre_, R_, G_, B_, A_) \ + case MALI_RGB_COMPONENT_ORDER_##case_: \ + return (struct pan_decomposed_swizzle) { \ + MALI_RGB_COMPONENT_ORDER_##pre_, { \ + PIPE_SWIZZLE_##R_, PIPE_SWIZZLE_##G_, \ + PIPE_SWIZZLE_##B_, PIPE_SWIZZLE_##A_ \ + } \ + }; + + switch (order) { + CASE(RGBA, RGBA, X, Y, Z, W); + CASE(GRBA, RGBA, Y, X, Z, W); + CASE(BGRA, RGBA, Z, Y, X, W); + CASE(ARGB, RGBA, Y, Z, W, X); + CASE(AGRB, RGBA, Z, Y, W, X); + CASE(ABGR, RGBA, W, Z, Y, X); + CASE(RGB1, RGB1, X, Y, Z, W); + CASE(GRB1, RGB1, Y, X, Z, W); + CASE(BGR1, RGB1, Z, Y, X, W); + CASE(1RGB, RGB1, Y, Z, W, X); + CASE(1GRB, RGB1, Z, Y, W, X); + CASE(1BGR, RGB1, W, Z, Y, X); + CASE(RRRR, RRRR, X, Y, Z, W); + CASE(RRR1, RRR1, X, Y, Z, W); + CASE(RRRA, RRRA, X, Y, Z, W); + CASE(000A, 000A, X, Y, Z, W); + CASE(0001, 0001, X, Y, Z, W); + CASE(0000, 0000, X, Y, Z, W); + default: unreachable("Invalid case for texturing"); + } + +#undef CASE +} +#endif diff --git a/src/panfrost/lib/pan_format.h b/src/panfrost/lib/pan_format.h index 547e009bb2b..a723a31b4d3 100644 --- a/src/panfrost/lib/pan_format.h +++ b/src/panfrost/lib/pan_format.h @@ -81,4 +81,17 @@ panfrost_get_default_swizzle(unsigned components) } } +#if PAN_ARCH == 7 +struct pan_decomposed_swizzle { + /* Component ordering to apply first */ + enum mali_rgb_component_order pre; + + /* Bijective swizzle applied after */ + unsigned char post[4]; +}; + +struct pan_decomposed_swizzle +GENX(pan_decompose_swizzle)(enum mali_rgb_component_order order); +#endif + #endif diff --git a/src/panfrost/lib/pan_texture.c b/src/panfrost/lib/pan_texture.c index 446fffe234c..3f6676bc10d 100644 --- a/src/panfrost/lib/pan_texture.c +++ b/src/panfrost/lib/pan_texture.c @@ -535,7 +535,8 @@ GENX(panfrost_new_texture)(const struct panfrost_device *dev, { const struct pan_image_layout *layout = &iview->image->layout; enum pipe_format format = iview->format; - unsigned swizzle; + uint32_t mali_format = dev->formats[format].hw; + unsigned char swizzle[4]; if (PAN_ARCH >= 7 && util_format_is_depth_or_stencil(format)) { /* v7+ doesn't have an _RRRR component order, combine the @@ -545,14 +546,31 @@ GENX(panfrost_new_texture)(const struct panfrost_device *dev, PIPE_SWIZZLE_X, PIPE_SWIZZLE_X, PIPE_SWIZZLE_X, PIPE_SWIZZLE_X, }; - unsigned char patched_swizzle[4]; util_format_compose_swizzles(replicate_x, iview->swizzle, - patched_swizzle); - swizzle = panfrost_translate_swizzle_4(patched_swizzle); + swizzle); + } else if (PAN_ARCH == 7) { +#if PAN_ARCH == 7 + /* v7 (only) restricts component orders when AFBC is in use. + * Rather than restrict AFBC, we use an allowed component order + * with an invertible swizzle composed. + */ + enum mali_rgb_component_order orig = + mali_format & BITFIELD_MASK(12); + struct pan_decomposed_swizzle decomposed = + GENX(pan_decompose_swizzle)(orig); + + /* Apply the new component order */ + mali_format = (mali_format & ~orig) | decomposed.pre; + + /* Compose the new swizzle */ + util_format_compose_swizzles(decomposed.post, iview->swizzle, + swizzle); +#endif } else { - swizzle = panfrost_translate_swizzle_4(iview->swizzle); + STATIC_ASSERT(sizeof(swizzle) == sizeof(iview->swizzle)); + memcpy(swizzle, iview->swizzle, sizeof(swizzle)); } panfrost_emit_texture_payload(iview, format, payload->cpu); @@ -581,14 +599,14 @@ GENX(panfrost_new_texture)(const struct panfrost_device *dev, pan_pack(out, TEXTURE, cfg) { cfg.dimension = iview->dim; - cfg.format = dev->formats[format].hw; + cfg.format = mali_format; cfg.width = width; cfg.height = u_minify(layout->height, iview->first_level); if (iview->dim == MALI_TEXTURE_DIMENSION_3D) cfg.depth = u_minify(layout->depth, iview->first_level); else cfg.sample_count = layout->nr_samples; - cfg.swizzle = swizzle; + cfg.swizzle = panfrost_translate_swizzle_4(swizzle); #if PAN_ARCH >= 9 cfg.texel_interleave = (layout->modifier != DRM_FORMAT_MOD_LINEAR) ||