summaryrefslogtreecommitdiff
path: root/lib/igt_fb.c
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2021-10-26 20:45:56 +0300
committerImre Deak <imre.deak@intel.com>2021-11-02 18:00:37 +0200
commit14a20fb2bbf51c40e178e4435a739c99b48529f3 (patch)
tree3f9e4b39ddb110469e351c910e79962ae95944e6 /lib/igt_fb.c
parentac780ef58da420fdbc765fff993aed4dde242dae (diff)
lib/igt_fb/tgl+: Prevent CCS FB UV surface offset overalignment
The offset of semiplanar UV surfaces in CCS FBs must be 64 kbyte aligned as required by the Vebox engine which IGT uses to convert between tiling formats. At the same time the display engine requires the offset to be tile-row aligned. So far we ensured both of these alignment requirements by aligning all color surface widths/heights to 4x4 tiles. This however wastes memory in case the number of tiles in one tile-row modulo 16 is 0 or 8 where 1 or 2 tile-row alignment correspondingly would be enough. The next patch removes the 4x4 tile alignment, here prepare for that by aligning TGL+ UV surface offsets to LCM(tile-row size, 64 kbyte) ensuring the minimum tile-row size and 64 kbyte alignment. v2: Calculate GCD without recursion. (Ville) Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Diffstat (limited to 'lib/igt_fb.c')
-rw-r--r--lib/igt_fb.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/igt_fb.c b/lib/igt_fb.c
index b8b2396d..4d961270 100644
--- a/lib/igt_fb.c
+++ b/lib/igt_fb.c
@@ -392,6 +392,12 @@ bool igt_format_is_yuv_semiplanar(uint32_t format)
return igt_format_is_yuv(format) && f->num_planes == 2;
}
+static bool is_yuv_semiplanar_plane(const struct igt_fb *fb, int color_plane)
+{
+ return igt_format_is_yuv_semiplanar(fb->drm_format) &&
+ color_plane == 1;
+}
+
/**
* igt_get_fb_tile_size:
* @fd: the DRM file descriptor
@@ -843,16 +849,65 @@ static uint64_t calc_plane_size(struct igt_fb *fb, int plane)
}
}
+static unsigned int gcd(unsigned int a, unsigned int b)
+{
+ while (b) {
+ unsigned int m = a % b;
+
+ a = b;
+ b = m;
+ }
+
+ return a;
+}
+
+static unsigned int lcm(unsigned int a, unsigned int b)
+{
+ unsigned int g = gcd(a, b);
+
+ if (g == 0 || b == 0)
+ return 0;
+
+ return a / g * b;
+}
+
+static unsigned int get_plane_alignment(struct igt_fb *fb, int color_plane)
+{
+ unsigned int tile_width, tile_height;
+ unsigned int tile_row_size;
+ unsigned int alignment;
+
+ if (!(is_i915_device(fb->fd) &&
+ is_gen12_ccs_modifier(fb->modifier) &&
+ is_yuv_semiplanar_plane(fb, color_plane)))
+ return 0;
+
+ igt_get_fb_tile_size(fb->fd, fb->modifier, fb->plane_bpp[color_plane],
+ &tile_width, &tile_height);
+
+ tile_row_size = fb->strides[color_plane] * tile_height;
+
+ alignment = lcm(tile_row_size, 64 * 1024);
+
+ return alignment;
+}
+
static uint64_t calc_fb_size(struct igt_fb *fb)
{
uint64_t size = 0;
int plane;
for (plane = 0; plane < fb->num_planes; plane++) {
+ unsigned int align;
+
/* respect the stride requested by the caller */
if (!fb->strides[plane])
fb->strides[plane] = calc_plane_stride(fb, plane);
+ align = get_plane_alignment(fb, plane);
+ if (align)
+ size += align - (size % align);
+
fb->offsets[plane] = size;
size += calc_plane_size(fb, plane);