[igt-dev] [v3 2/2] tests/kms_scaling_filters: New IGT to validate scaling filters

Swati Sharma swati2.sharma at intel.com
Tue Jun 14 09:20:25 UTC 2022


SCALING_FILTER can be used either as plane scaler property
or CRTC scaler property.
The value of this property can be one of the following:
    Default:
             Driver's default scaling filter
    Nearest Neighbor:
             Nearest Neighbor scaling filter
If NN is used for scaling, sharpness is preserved
whereas if we use default scaling we can see blurriness
at edges.

Four subtests are written upscale/downscale with NN and default
scaling filters.

v2: no need to set pipe scaler filter property
v3: -addition of new lines to improve readability
    -use of SPDX licence placeholder
    -close(data.drm_fd)

Signed-off-by: Swati Sharma <swati2.sharma at intel.com>
---
 lib/igt_kms.c               |  16 ++++
 lib/igt_kms.h               |   1 +
 tests/kms_scaling_filters.c | 163 ++++++++++++++++++++++++++++++++++++
 tests/meson.build           |   1 +
 4 files changed, 181 insertions(+)
 create mode 100644 tests/kms_scaling_filters.c

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index 2a9376ae..6dca1724 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -912,6 +912,22 @@ const char *kmstest_connector_status_str(int status)
 	return find_type_name(connector_status_names, status);
 }
 
+enum drm_scaling_filter {
+	DRM_SCALING_FILTER_DEFAULT,
+	DRM_SCALING_FILTER_NEAREST_NEIGHBOR,
+};
+
+static const struct type_name drm_scaling_filter[] = {
+	{ DRM_SCALING_FILTER_DEFAULT, "Default" },
+	{ DRM_SCALING_FILTER_NEAREST_NEIGHBOR, "Nearest Neighbor" },
+	{}
+};
+
+const char *kmstest_scaling_filter_str(int filter)
+{
+	return find_type_name(drm_scaling_filter, filter);
+}
+
 static const struct type_name connector_type_names[] = {
 	{ DRM_MODE_CONNECTOR_Unknown, "Unknown" },
 	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 46754b67..7f17a1af 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -107,6 +107,7 @@ enum igt_custom_edid_type {
 const char *kmstest_encoder_type_str(int type);
 const char *kmstest_connector_status_str(int status);
 const char *kmstest_connector_type_str(int type);
+const char *kmstest_scaling_filter_str(int filter);
 
 void kmstest_dump_mode(drmModeModeInfo *mode);
 
diff --git a/tests/kms_scaling_filters.c b/tests/kms_scaling_filters.c
new file mode 100644
index 00000000..e9f9d089
--- /dev/null
+++ b/tests/kms_scaling_filters.c
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include "igt.h"
+#include "igt_kms.h"
+
+IGT_TEST_DESCRIPTION("Test display scaling filters");
+
+enum {
+	DRM_SCALING_FILTER_DEFAULT,
+	DRM_SCALING_FILTER_NEAREST_NEIGHBOR,
+};
+
+typedef struct data {
+	igt_display_t display;
+	int drm_fd;
+} data_t;
+
+typedef struct {
+	float r;
+	float g;
+	float b;
+} rgb_color_t;
+
+static void set_color(rgb_color_t *color, float r, float g, float b)
+{
+	color->r = r;
+	color->g = g;
+	color->b = b;
+}
+
+#define RGB_COLOR(color) \
+	color.r, color.g, color.b
+
+static void
+paint_squares(data_t *data, struct igt_fb *fb, float o)
+{
+	cairo_t *cr;
+	unsigned int w = fb->width;
+	unsigned int h = fb->height;
+	rgb_color_t tl, tr, bl, br;
+
+	cr = igt_get_cairo_ctx(data->drm_fd, fb);
+
+	set_color(&tl, o, 0.0f, 0.0f);
+	set_color(&tr, 0.0f, o, 0.0f);
+	set_color(&br, o, o, o);
+	set_color(&bl, 0.0f, 0.0f, o);
+
+	igt_paint_color(cr, 0, 0, w / 2, h / 2, RGB_COLOR(tl));
+	igt_paint_color(cr, w / 2, 0, w / 2, h / 2, RGB_COLOR(tr));
+	igt_paint_color(cr, 0, h / 2, w / 2, h / 2, RGB_COLOR(bl));
+	igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, RGB_COLOR(br));
+
+	igt_put_cairo_ctx(cr);
+}
+
+#define IS_FACTOR 2
+static void test_scaling_filter_on_output(data_t *data, const enum pipe pipe,
+					  igt_output_t *output, igt_plane_t *plane, int flags,
+					  bool is_upscale)
+{
+	igt_display_t *display = &data->display;
+	const float flip_opacity = 1;
+	drmModeModeInfo *mode;
+	struct igt_fb fb;
+	int w, h, ret;
+
+	igt_output_set_pipe(output, pipe);
+	mode = igt_output_get_mode(output);
+
+	if (is_upscale) {
+		w = mode->hdisplay / IS_FACTOR;
+		h = mode->vdisplay / IS_FACTOR;
+	} else {
+		w = mode->hdisplay;
+		h = mode->vdisplay;
+	}
+
+	igt_create_fb(display->drm_fd, w, h,
+		      DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, &fb);
+	paint_squares(data, &fb, flip_opacity);
+
+	igt_plane_set_prop_enum(plane, IGT_PLANE_SCALING_FILTER, kmstest_scaling_filter_str(flags));
+
+	igt_plane_set_fb(plane, &fb);
+	igt_plane_set_position(plane, 0, 0);
+
+	if (is_upscale)
+		igt_plane_set_size(plane, mode->hdisplay, mode->vdisplay);
+	else
+		igt_plane_set_size(plane, mode->hdisplay * 0.75, mode->vdisplay * 0.75);
+
+	ret = igt_display_try_commit2(display, COMMIT_ATOMIC);
+
+	igt_plane_set_fb(plane, NULL);
+	igt_plane_set_position(plane, 0, 0);
+	igt_remove_fb(display->drm_fd, &fb);
+
+	igt_skip_on_f(ret == -ERANGE || ret == -EINVAL,
+		      "Unsupported scaling factor with fb size %dx%d\n", w, h);
+	igt_assert_eq(ret, 0);
+}
+
+static void test_scaling_filter(data_t *data, int flags, bool is_upscale)
+{
+	igt_display_t *display = &data->display;
+	igt_output_t *output;
+	igt_plane_t *plane;
+	enum pipe pipe;
+
+	for_each_pipe_with_valid_output(display, pipe, output) {
+		for_each_plane_on_pipe(display, pipe, plane) {
+			if (!igt_plane_has_prop(plane, IGT_PLANE_SCALING_FILTER))
+				continue;
+
+			igt_dynamic_f("pipe-%s-%s-plane-%u", kmstest_pipe_name(pipe), output->name, plane->index)
+				test_scaling_filter_on_output(data, pipe, output, plane, flags, is_upscale);
+
+			igt_display_reset(display);
+		}
+	}
+}
+
+igt_main
+{
+	data_t data = {};
+
+	igt_fixture {
+		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
+		igt_require(data.drm_fd >= 0);
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_require(&data.display, data.drm_fd);
+		igt_require(data.display.is_atomic);
+
+		igt_display_require_output(&data.display);
+	}
+
+	igt_describe("Tests default scaling filter, upscale");
+	igt_subtest_with_dynamic("scaling-filter-default-upscale")
+		test_scaling_filter(&data, DRM_SCALING_FILTER_DEFAULT, true);
+
+	igt_describe("Tests default scaling filter, downscale");
+	igt_subtest_with_dynamic("scaling-filter-default-downscale")
+		test_scaling_filter(&data, DRM_SCALING_FILTER_DEFAULT, false);
+
+	igt_describe("Tests nearest neighbor scaling filter, upscale");
+	igt_subtest_with_dynamic("scaling-filter-nn-upscale")
+		test_scaling_filter(&data, DRM_SCALING_FILTER_NEAREST_NEIGHBOR, true);
+
+	igt_describe("Tests nearest neighbor scaling filter, downscale");
+	igt_subtest_with_dynamic("scaling-filter-nn-downscale")
+		test_scaling_filter(&data, DRM_SCALING_FILTER_NEAREST_NEIGHBOR, false);
+
+	igt_fixture {
+		igt_display_fini(&data.display);
+		close(data.drm_fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index b548dc3b..e5d605fa 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -53,6 +53,7 @@ test_progs = [
 	'kms_properties',
 	'kms_rmfb',
 	'kms_rotation_crc',
+	'kms_scaling_filters',
 	'kms_scaling_modes',
 	'kms_selftest',
 	'kms_sequence',
-- 
2.25.1



More information about the igt-dev mailing list