[igt-dev] [PATCH i-g-t 3/3] tests: Add new PSR2 selective fetch test
Pankaj Bharadiya
pankaj.laxminarayan.bharadiya at intel.com
Tue Dec 8 17:01:09 UTC 2020
Selective fetch reduces display engine use of memory bandwidth
by only fetching (reading from memory) the updated regions of the frame
buffer and sending those updated regions to a panel with a PSR2 capability.
The FB_DAMAGE_CLIPS plane property provides user-space a way inform
kernel about the updated regions.
Add new test to verify selective fetch by using FB_DAMAGE_CLIPS property
to send updated regions.
changes since v1:
* alloc enough clips for all tests in stack and reuse (Jose)
* set damage clip along with draw, refactor code, rename
variables, etc (Jose)
Signed-off-by: Pankaj Bharadiya <pankaj.laxminarayan.bharadiya at intel.com>
---
tests/Makefile.sources | 1 +
tests/kms_psr2_sf.c | 649 +++++++++++++++++++++++++++++++++++++++++
tests/meson.build | 1 +
3 files changed, 651 insertions(+)
create mode 100644 tests/kms_psr2_sf.c
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 15fb56048..e7e399165 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -80,6 +80,7 @@ TESTS_progs = \
kms_properties \
kms_psr \
kms_psr2_su \
+ kms_psr2_sf \
kms_pwrite_crc \
kms_rmfb \
kms_rotation_crc \
diff --git a/tests/kms_psr2_sf.c b/tests/kms_psr2_sf.c
new file mode 100644
index 000000000..296ed8476
--- /dev/null
+++ b/tests/kms_psr2_sf.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright © 2020 Intel Corporation
+ *
+ * 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 "igt.h"
+#include "igt_sysfs.h"
+#include "igt_psr.h"
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include "intel_bufmgr.h"
+
+IGT_TEST_DESCRIPTION("Tests to varify PSR2 selective fetch by sending multiple"
+ " damaged areas");
+
+#define SQUARE_SIZE 100
+
+#define CUR_SIZE 64
+#define MAX_DAMAGE_AREAS 5
+
+enum operations {
+ PLANE_UPDATE,
+ PLANE_MOVE,
+ OVERLAY_PRIM_UPDATE
+};
+
+enum plane_move_postion {
+ POS_TOP_LEFT,
+ POS_TOP_RIGHT,
+ POS_BOTTOM_LEFT,
+ POS_BOTTOM_RIGHT
+};
+
+typedef struct {
+ int drm_fd;
+ int debugfs_fd;
+ igt_display_t display;
+ drm_intel_bufmgr *bufmgr;
+ drmModeModeInfo *mode;
+ igt_output_t *output;
+ struct igt_fb fb_primary, fb_overlay, fb_cursor;
+ struct igt_fb fb_test;
+ int damage_area_count;
+ struct drm_mode_rect plane_update_clip[MAX_DAMAGE_AREAS];
+ struct drm_mode_rect plane_move_clip;
+ struct drm_mode_rect cursor_clip;
+ enum operations op;
+ enum plane_move_postion pos;
+ int test_plane_id;
+ igt_plane_t *test_plane;
+ cairo_t *cr;
+} data_t;
+
+static const char *op_str(enum operations op)
+{
+ static const char * const name[] = {
+ [PLANE_UPDATE] = "plane-update",
+ [PLANE_MOVE] = "plane-move",
+ [OVERLAY_PRIM_UPDATE] = "overlay-primary-update",
+ };
+
+ return name[op];
+}
+
+static void setup_output(data_t *data)
+{
+ igt_display_t *display = &data->display;
+ igt_output_t *output;
+ enum pipe pipe;
+
+ for_each_pipe_with_valid_output(display, pipe, output) {
+ drmModeConnectorPtr c = output->config.connector;
+
+ if (c->connector_type != DRM_MODE_CONNECTOR_eDP)
+ continue;
+
+ igt_output_set_pipe(output, pipe);
+ data->output = output;
+ data->mode = igt_output_get_mode(output);
+
+ return;
+ }
+}
+
+static void display_init(data_t *data)
+{
+ igt_display_require(&data->display, data->drm_fd);
+ setup_output(data);
+}
+
+static void display_fini(data_t *data)
+{
+ igt_display_fini(&data->display);
+}
+
+static void draw_rect(data_t *data, igt_fb_t *fb, int x, int y, int w, int h,
+ double r, double g, double b, double a)
+{
+ cairo_t *cr;
+
+ cr = igt_get_cairo_ctx(data->drm_fd, fb);
+ igt_paint_color_alpha(cr, x, y, w, h, r, g, b, a);
+ igt_put_cairo_ctx(cr);
+}
+
+static void set_clip(struct drm_mode_rect *clip, int x, int y, int width,
+ int height)
+{
+ clip->x1 = x;
+ clip->y1 = y;
+ clip->x2 = x + width;
+ clip->y2 = y + height;
+}
+
+static void plane_update_setup_squares(data_t *data, igt_fb_t *fb, uint32_t h,
+ uint32_t v)
+{
+ int x, y;
+ int width = SQUARE_SIZE;
+ int height = SQUARE_SIZE;
+
+ switch (data->damage_area_count) {
+ case 5:
+ /*Bottom right corner*/
+ x = h - SQUARE_SIZE;
+ y = v - SQUARE_SIZE;
+
+ draw_rect(data, fb, x, y, width, height, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_update_clip[4], x, y, width, height);
+ case 4:
+ /*Bottom left corner*/
+ x = 0;
+ y = v - SQUARE_SIZE;
+
+ draw_rect(data, fb, x, y, width, height, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_update_clip[3], x, y, width, height);
+ case 3:
+ /*Top right corner*/
+ x = h - SQUARE_SIZE;
+ y = 0;
+
+ draw_rect(data, fb, x, y, width, height, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_update_clip[2], x, y, width, height);
+ case 2:
+ /*Top left corner*/
+ x = 0;
+ y = 0;
+
+ draw_rect(data, fb, x, y, width, height, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_update_clip[1], x, y, width, height);
+ case 1:
+ /*Center*/
+ x = h/2 - SQUARE_SIZE/2;
+ y = v/2 - SQUARE_SIZE/2;
+
+ draw_rect(data, fb, x, y, width, height, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_update_clip[0], x, y, width, height);
+ break;
+ default:
+ igt_assert(false);
+ }
+}
+
+static void plane_move_setup_square(data_t *data, igt_fb_t *fb, uint32_t h,
+ uint32_t v)
+{
+ int x = 0, y = 0;
+
+ switch (data->pos) {
+ case POS_TOP_LEFT:
+ /*Bottom right corner*/
+ x = h - SQUARE_SIZE;
+ y = v - SQUARE_SIZE;
+ break;
+ case POS_TOP_RIGHT:
+ /*Bottom left corner*/
+ x = 0;
+ y = v - SQUARE_SIZE;
+ break;
+ case POS_BOTTOM_LEFT:
+ /*Top right corner*/
+ x = h - SQUARE_SIZE;
+ y = 0;
+ break;
+ case POS_BOTTOM_RIGHT:
+ /*Top left corner*/
+ x = 0;
+ y = 0;
+ break;
+ default:
+ igt_assert(false);
+ }
+
+ draw_rect(data, fb, x, y,
+ SQUARE_SIZE, SQUARE_SIZE, 1.0, 1.0, 1.0, 1.0);
+ set_clip(&data->plane_move_clip, x, y, SQUARE_SIZE, SQUARE_SIZE);
+}
+
+static void prepare(data_t *data)
+{
+ igt_plane_t *primary, *sprite = NULL, *cursor = NULL;
+
+ /* all green frame */
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay, data->mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 1.0, 0.0,
+ &data->fb_primary);
+
+ primary = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_PRIMARY);
+
+ switch (data->test_plane_id) {
+ case DRM_PLANE_TYPE_OVERLAY:
+ sprite = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_OVERLAY);
+ /*All blue plane*/
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay/2,
+ data->mode->vdisplay/2,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 0.0, 1.0,
+ &data->fb_overlay);
+
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay/2,
+ data->mode->vdisplay/2,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 0.0, 1.0,
+ &data->fb_test);
+
+ if (data->op == PLANE_MOVE) {
+ plane_move_setup_square(data, &data->fb_test,
+ data->mode->hdisplay/2,
+ data->mode->vdisplay/2);
+
+ } else {
+ plane_update_setup_squares(data, &data->fb_test,
+ data->mode->hdisplay/2,
+ data->mode->vdisplay/2);
+ }
+
+ igt_plane_set_fb(sprite, &data->fb_overlay);
+ data->test_plane = sprite;
+ break;
+
+ case DRM_PLANE_TYPE_PRIMARY:
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay, data->mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 1.0, 0.0,
+ &data->fb_test);
+
+ plane_update_setup_squares(data, &data->fb_test,
+ data->mode->hdisplay,
+ data->mode->vdisplay);
+ data->test_plane = primary;
+
+ if (data->op == OVERLAY_PRIM_UPDATE) {
+ sprite = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_OVERLAY);
+
+ igt_create_color_fb(data->drm_fd,
+ data->mode->hdisplay,
+ data->mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0, 0.0, 1.0,
+ &data->fb_overlay);
+
+ igt_plane_set_fb(sprite, &data->fb_overlay);
+ igt_plane_set_prop_value(sprite, IGT_PLANE_ALPHA,
+ 0x6060);
+ }
+ break;
+
+ case DRM_PLANE_TYPE_CURSOR:
+ cursor = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_CURSOR);
+ igt_plane_set_position(cursor, 0, 0);
+
+ igt_create_fb(data->drm_fd, CUR_SIZE, CUR_SIZE,
+ DRM_FORMAT_ARGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+ &data->fb_cursor);
+
+ draw_rect(data, &data->fb_cursor, 0, 0, CUR_SIZE, CUR_SIZE,
+ 0.0, 0.0, 1.0, 1.0);
+
+ igt_create_fb(data->drm_fd, CUR_SIZE, CUR_SIZE,
+ DRM_FORMAT_ARGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
+ &data->fb_test);
+
+ draw_rect(data, &data->fb_test, 0, 0, CUR_SIZE, CUR_SIZE,
+ 1.0, 1.0, 1.0, 1.0);
+
+ set_clip(&data->cursor_clip, 0, 0, CUR_SIZE, CUR_SIZE);
+ igt_plane_set_fb(cursor, &data->fb_cursor);
+ data->test_plane = cursor;
+ break;
+ default:
+ igt_assert(false);
+ }
+
+ igt_plane_set_fb(primary, &data->fb_primary);
+
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+}
+
+static inline void manual(const char *expected)
+{
+ igt_debug_manual_check("all", expected);
+}
+
+static void plane_update_expected_output(int plane_type, int box_count)
+{
+ char expected[64] = {};
+
+ switch (plane_type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ sprintf(expected, "screen Green with %d White box(es)",
+ box_count);
+ break;
+ case DRM_PLANE_TYPE_OVERLAY:
+ sprintf(expected,
+ "screen Green with Blue box and %d White box(es)",
+ box_count);
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ sprintf(expected, "screen Green with %d White box(es)",
+ box_count);
+ break;
+ default:
+ igt_assert(false);
+ }
+
+ manual(expected);
+}
+
+static void plane_move_expected_output(enum plane_move_postion pos)
+{
+ char expected[64] = {};
+
+ switch (pos) {
+ case POS_TOP_LEFT:
+ sprintf(expected,
+ "screen Green with Blue box on top left corner and White box");
+ break;
+ case POS_TOP_RIGHT:
+ sprintf(expected,
+ "screen Green with Blue box on top right corner and White box");
+ break;
+ case POS_BOTTOM_LEFT:
+ sprintf(expected,
+ "screen Green with Blue box on bottom left corner and White box");
+ break;
+ case POS_BOTTOM_RIGHT:
+ sprintf(expected,
+ "screen Green with Blue box on bottom right corner and White box");
+ break;
+ default:
+ igt_assert(false);
+ }
+
+ manual(expected);
+}
+
+static void overlay_prim_update_expected_output(int box_count)
+{
+ char expected[64] = {};
+
+ sprintf(expected,
+ "screen Green with Blue overlay, %d light Blue box(es)",
+ box_count);
+
+ manual(expected);
+
+}
+
+static void expected_output(data_t *data)
+{
+ switch (data->op) {
+ case PLANE_MOVE:
+ plane_move_expected_output(data->pos);
+ break;
+ case PLANE_UPDATE:
+ plane_update_expected_output(data->test_plane_id,
+ data->damage_area_count);
+ break;
+ case OVERLAY_PRIM_UPDATE:
+ overlay_prim_update_expected_output(data->damage_area_count);
+ break;
+ default:
+ igt_assert(false);
+ }
+}
+
+static void damaged_plane_move(data_t *data)
+{
+ igt_plane_t *test_plane = data->test_plane;
+ uint32_t h = data->mode->hdisplay;
+ uint32_t v = data->mode->vdisplay;
+
+ igt_plane_set_fb(test_plane, &data->fb_test);
+
+ if (data->test_plane_id == DRM_PLANE_TYPE_OVERLAY) {
+ h = h/2;
+ v = v/2;
+ }
+
+ igt_plane_replace_prop_blob(test_plane, IGT_PLANE_FB_DAMAGE_CLIPS,
+ &data->plane_move_clip,
+ sizeof(struct drm_mode_rect));
+
+ switch (data->pos) {
+ case POS_TOP_LEFT:
+ igt_plane_set_position(data->test_plane, 0, 0);
+ break;
+ case POS_TOP_RIGHT:
+ igt_plane_set_position(data->test_plane,
+ data->mode->hdisplay/2, 0);
+ break;
+ case POS_BOTTOM_LEFT:
+ igt_plane_set_position(data->test_plane, 0,
+ data->mode->vdisplay/2);
+ break;
+ case POS_BOTTOM_RIGHT:
+ igt_plane_set_position(data->test_plane,
+ data->mode->hdisplay/2,
+ data->mode->vdisplay/2);
+ break;
+ default:
+ igt_assert(false);
+ }
+
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+ igt_assert(psr_wait_entry(data->debugfs_fd, PSR_MODE_2));
+
+ expected_output(data);
+}
+
+static void damaged_plane_update(data_t *data)
+{
+ igt_plane_t *test_plane = data->test_plane;
+ uint32_t h = data->mode->hdisplay;
+ uint32_t v = data->mode->vdisplay;
+
+ igt_plane_set_fb(test_plane, &data->fb_test);
+
+ if (data->test_plane_id == DRM_PLANE_TYPE_OVERLAY) {
+ h = h/2;
+ v = v/2;
+ }
+
+ if (data->test_plane_id == DRM_PLANE_TYPE_CURSOR)
+ igt_plane_replace_prop_blob(test_plane,
+ IGT_PLANE_FB_DAMAGE_CLIPS,
+ &data->cursor_clip,
+ sizeof(struct drm_mode_rect));
+ else
+ igt_plane_replace_prop_blob(test_plane,
+ IGT_PLANE_FB_DAMAGE_CLIPS,
+ &data->plane_update_clip,
+ sizeof(struct drm_mode_rect)*
+ data->damage_area_count);
+
+ igt_plane_set_position(data->test_plane, 0, 0);
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+ igt_assert(psr_wait_entry(data->debugfs_fd, PSR_MODE_2));
+
+ expected_output(data);
+}
+
+static void run(data_t *data)
+{
+ igt_assert(psr_wait_entry(data->debugfs_fd, PSR_MODE_2));
+
+ switch (data->op) {
+ case PLANE_UPDATE:
+ case OVERLAY_PRIM_UPDATE:
+ damaged_plane_update(data);
+ break;
+ case PLANE_MOVE:
+ damaged_plane_move(data);
+ break;
+ default:
+ igt_assert(false);
+ }
+}
+
+static void cleanup(data_t *data)
+{
+ igt_plane_t *primary;
+ igt_plane_t *sprite;
+
+ primary = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_PRIMARY);
+
+ igt_plane_set_fb(primary, NULL);
+
+ if (data->test_plane_id != DRM_PLANE_TYPE_PRIMARY) {
+ igt_plane_set_position(data->test_plane, 0, 0);
+ igt_plane_set_fb(data->test_plane, NULL);
+ }
+
+ if (data->op == OVERLAY_PRIM_UPDATE) {
+ sprite = igt_output_get_plane_type(data->output,
+ DRM_PLANE_TYPE_OVERLAY);
+ igt_plane_set_position(sprite, 0, 0);
+ igt_plane_set_fb(sprite, NULL);
+ }
+
+ igt_display_commit2(&data->display, COMMIT_ATOMIC);
+
+ igt_remove_fb(data->drm_fd, &data->fb_primary);
+ igt_remove_fb(data->drm_fd, &data->fb_overlay);
+ igt_remove_fb(data->drm_fd, &data->fb_cursor);
+ igt_remove_fb(data->drm_fd, &data->fb_test);
+}
+
+igt_main
+{
+ data_t data = {};
+ int i;
+
+ igt_fixture {
+ int r;
+
+ data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+ data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
+ kmstest_set_vt_graphics_mode();
+
+ igt_require_f(psr_sink_support(data.drm_fd,
+ data.debugfs_fd, PSR_MODE_2),
+ "Sink does not support PSR2\n");
+
+ igt_require_f(psr2_selective_fetch_check(data.debugfs_fd),
+ "PSR2 selective fetch not enabled\n");
+
+ data.bufmgr = drm_intel_bufmgr_gem_init(data.drm_fd, 4096);
+ igt_assert(data.bufmgr);
+ drm_intel_bufmgr_gem_enable_reuse(data.bufmgr);
+
+ display_init(&data);
+
+ /* Test if PSR2 can be enabled */
+ igt_require_f(psr_enable(data.drm_fd,
+ data.debugfs_fd, PSR_MODE_2),
+ "Error enabling PSR2\n");
+
+ data.damage_area_count = MAX_DAMAGE_AREAS;
+ data.op = PLANE_UPDATE;
+ data.test_plane_id = DRM_PLANE_TYPE_PRIMARY;
+ prepare(&data);
+ r = psr_wait_entry(data.debugfs_fd, PSR_MODE_2);
+ cleanup(&data);
+ if (!r)
+ psr_print_debugfs(data.debugfs_fd);
+ igt_require_f(r, "PSR2 can not be enabled\n");
+ }
+
+ /* Verify primary plane selective fetch */
+ for (i = 1; i <= MAX_DAMAGE_AREAS; i++) {
+ igt_subtest_f("primary-%s-sf-dmg-area-%d", op_str(data.op), i) {
+ data.damage_area_count = i;
+ data.test_plane_id = DRM_PLANE_TYPE_PRIMARY;
+ prepare(&data);
+ run(&data);
+ cleanup(&data);
+ }
+ }
+
+ /* Verify overlay plane selective fetch */
+ for (i = 1; i <= MAX_DAMAGE_AREAS; i++) {
+ igt_subtest_f("overlay-%s-sf-dmg-area-%d", op_str(data.op), i) {
+ data.damage_area_count = i;
+ data.test_plane_id = DRM_PLANE_TYPE_OVERLAY;
+ prepare(&data);
+ run(&data);
+ cleanup(&data);
+ }
+ }
+
+ /* Verify overlay plane selective fetch */
+ igt_subtest_f("cursor-%s-sf", op_str(data.op)) {
+ data.damage_area_count = 1;
+ data.test_plane_id = DRM_PLANE_TYPE_CURSOR;
+ prepare(&data);
+ run(&data);
+ cleanup(&data);
+ }
+
+ /* Only for overlay plane */
+ data.op = PLANE_MOVE;
+ /* Verify overlay plane move selective fetch */
+ for (i = POS_TOP_LEFT; i <= POS_BOTTOM_RIGHT ; i++) {
+ igt_subtest_f("%s-sf-dmg-area-%d", op_str(data.op), i) {
+ data.pos = i;
+ data.test_plane_id = DRM_PLANE_TYPE_OVERLAY;
+ prepare(&data);
+ run(&data);
+ cleanup(&data);
+ }
+ }
+
+ /* Verify primary plane selective fetch with overplay plane blended */
+ data.op = OVERLAY_PRIM_UPDATE;
+ for (i = 1; i <= MAX_DAMAGE_AREAS; i++) {
+ igt_subtest_f("%s-sf-dmg-area-%d", op_str(data.op), i) {
+ data.damage_area_count = i;
+ data.test_plane_id = DRM_PLANE_TYPE_PRIMARY;
+ prepare(&data);
+ run(&data);
+ cleanup(&data);
+ }
+ }
+
+ igt_fixture {
+ close(data.debugfs_fd);
+ drm_intel_bufmgr_destroy(data.bufmgr);
+ display_fini(&data);
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index a2decf4ab..4cab294b8 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -64,6 +64,7 @@ test_progs = [
'kms_properties',
'kms_psr',
'kms_psr2_su',
+ 'kms_psr2_sf',
'kms_pwrite_crc',
'kms_rmfb',
'kms_rotation_crc',
--
2.29.2
More information about the igt-dev
mailing list