[igt-dev] [PATCH i-g-t 3/3] tests/kms_dirtyfb: Add new test for dirtyfb ioctl
Hogander, Jouni
jouni.hogander at intel.com
Wed Apr 12 09:46:49 UTC 2023
On Thu, 2023-04-06 at 09:20 +0200, Kamil Konieczny wrote:
> Hi,
>
> On 2023-04-05 at 08:34:51 +0300, Jouni Högander wrote:
> > Add new test to validate dirtyfb ioctl is working properly with GPU
> > frontbuffer rendering.
> >
> > Create big framebuffer and use only lower right corner for the
> > plane. Initiate GPU drawing for a rectangle over the whole
> > framebuffer and perform dirtyfb ioctl. Then wait for the drawing to
> > complete and collect crc and check that it matches with expected.
> >
> > Signed-off-by: Jouni Högander <jouni.hogander at intel.com>
> > ---
> > tests/i915/kms_dirtyfb.c | 309
> > +++++++++++++++++++++++++++++++++++++++
> > tests/meson.build | 8 +
> > 2 files changed, 317 insertions(+)
> > create mode 100644 tests/i915/kms_dirtyfb.c
> >
> > diff --git a/tests/i915/kms_dirtyfb.c b/tests/i915/kms_dirtyfb.c
> > new file mode 100644
> > index 00000000..99d4231d
> > --- /dev/null
> > +++ b/tests/i915/kms_dirtyfb.c
> > @@ -0,0 +1,309 @@
> > +/*
>
> Please add SPDX licence here.
>
> > + * Copyright © 2023 Intel Corporation
> > + *
>
> Delete below text as we should use SPDX instead.
Thank you Kamil for checking my patch. Please check new version where I
have addressed you comment.
>
> Regards,
> Kamil
>
> > + * 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 <sys/types.h>
> > +
> > +#include "igt.h"
> > +#include "igt_psr.h"
> > +
> > +#include "kms_fbc_helper.h"
> > +#include "kms_drrs_helper.h"
> > +
> > +IGT_TEST_DESCRIPTION("Test the DIRTYFB ioctl is working properly
> > with "
> > + "its related features: FBC, PSR and DRRS");
> > +
> > +#ifndef PAGE_ALIGN
> > +#ifndef PAGE_SIZE
> > +#define PAGE_SIZE 4096
> > +#endif
> > +#define PAGE_ALIGN(x) ALIGN(x, PAGE_SIZE)
> > +#endif
> > +
> > +typedef struct {
> > + int drm_fd;
> > + int debugfs_fd;
> > + igt_display_t display;
> > + drmModeModeInfo *mode;
> > + igt_output_t *output;
> > + igt_pipe_crc_t *pipe_crc;
> > + enum pipe pipe;
> > +
> > + struct igt_fb fbs[3];
> > +
> > + igt_crc_t ref_crc;
> > +
> > + struct buf_ops *bops;
> > + enum {
> > + FEATURE_NONE = 0,
> > + FEATURE_PSR = 1,
> > + FEATURE_FBC = 2,
> > + FEATURE_DRRS = 4,
> > + FEATURE_COUNT = 8,
> > + FEATURE_DEFAULT = 8,
> > + } feature;
> > +} data_t;
> > +
> > +static const char *feature_str(int feature)
> > +{
> > + switch (feature) {
> > + case FEATURE_NONE:
> > + return "nop";
> > + case FEATURE_FBC:
> > + return "fbc";
> > + case FEATURE_PSR:
> > + return "psr";
> > + case FEATURE_DRRS:
> > + return "drrs";
> > + case FEATURE_DEFAULT:
> > + return "default";
> > + default:
> > + igt_assert(false);
> > + }
> > +}
> > +
> > +static bool check_support(data_t *data)
> > +{
> > + switch (data->feature) {
> > + case FEATURE_NONE:
> > + return true;
> > + case FEATURE_FBC:
> > + return fbc_supported_on_chipset(data->drm_fd, data-
> > >pipe);
> > + case FEATURE_PSR:
> > + return psr_sink_support(data->drm_fd, data-
> > >debugfs_fd,
> > + PSR_MODE_1);
> > + case FEATURE_DRRS:
> > + return is_drrs_supported(data->drm_fd, data->pipe)
> > &&
> > + output_has_drrs(data->drm_fd, data-
> > >output);
> > + case FEATURE_DEFAULT:
> > + return true;
> > + default:
> > + igt_assert(false);
> > + }
> > +}
> > +
> > +static void enable_feature(data_t *data)
> > +{
> > + switch (data->feature) {
> > + case FEATURE_NONE:
> > + break;
> > + case FEATURE_FBC:
> > + fbc_enable(data->drm_fd);
> > + break;
> > + case FEATURE_PSR:
> > + psr_enable(data->drm_fd, data->debugfs_fd,
> > PSR_MODE_1);
> > + break;
> > + case FEATURE_DRRS:
> > + drrs_enable(data->drm_fd, data->pipe);
> > + break;
> > + case FEATURE_DEFAULT:
> > + break;
> > + default:
> > + igt_assert(false);
> > + }
> > +}
> > +
> > +static void check_feature(data_t *data)
> > +{
> > + switch (data->feature) {
> > + case FEATURE_NONE:
> > + break;
> > + case FEATURE_FBC:
> > + igt_assert_f(fbc_wait_until_enabled(data->drm_fd,
> > data->pipe),
> > + "FBC still disabled");
> > + break;
> > + case FEATURE_PSR:
> > + igt_assert_f(psr_wait_entry(data->debugfs_fd,
> > PSR_MODE_1),
> > + "PSR still disabled\n");
> > + break;
> > + case FEATURE_DRRS:
> > + igt_assert_f(is_drrs_inactive(data->drm_fd, data-
> > >pipe),
> > + "DRRS INACTIVE\n");
> > + break;
> > + case FEATURE_DEFAULT:
> > + break;
> > + default:
> > + igt_assert(false);
> > + }
> > +}
> > +
> > +static void disable_features(data_t *data)
> > +{
> > + fbc_disable(data->drm_fd);
> > + psr_disable(data->drm_fd, data->debugfs_fd);
> > + drrs_disable(data->drm_fd, data->pipe);
> > +}
> > +
> > +static void prepare(data_t *data)
> > +{
> > + igt_plane_t *primary;
> > + drmModeResPtr res;
> > +
> > + igt_skip_on(!check_support(data));
> > +
> > + data->mode = igt_output_get_mode(data->output);
> > +
> > + igt_output_set_pipe(data->output, data->pipe);
> > +
> > + data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe,
> > + IGT_PIPE_CRC_SOURCE_AUTO);
> > +
> > + igt_create_color_fb(data->drm_fd, data->mode->hdisplay,
> > + data->mode->hdisplay,
> > DRM_FORMAT_XRGB8888,
> > + DRM_FORMAT_MOD_LINEAR, 0.0, 1.0, 0.0,
> > + &data->fbs[0]);
> > + igt_draw_rect_fb(data->drm_fd, data->bops, 0, &data-
> > >fbs[0],
> > + IGT_DRAW_RENDER, 0, 0, data->fbs[0].width,
> > + data->fbs[0].height, 0xFF);
> > +
> > + primary = igt_output_get_plane_type(data->output,
> > +
> > DRM_PLANE_TYPE_PRIMARY);
> > +
> > + igt_plane_set_fb(primary, &data->fbs[0]);
> > +
> > + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> > +
> > + igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
> > +
> > + res = drmModeGetResources(data->drm_fd);
> > +
> > + igt_create_color_fb(data->drm_fd, res->max_width,
> > + res->max_height, DRM_FORMAT_XRGB8888,
> > + DRM_FORMAT_MOD_LINEAR, 0.0, 1.0, 0.0,
> > + &data->fbs[1]);
> > + igt_draw_rect_fb(data->drm_fd, data->bops, 0, &data-
> > >fbs[1],
> > + IGT_DRAW_MMAP_CPU, 0, 0, data-
> > >fbs[1].width,
> > + data->fbs[1].height, 0xFF);
> > +
> > + igt_create_color_fb(data->drm_fd, res->max_width,
> > + res->max_height, DRM_FORMAT_XRGB8888,
> > + DRM_FORMAT_MOD_LINEAR, 0.0, 1.0, 0.0,
> > + &data->fbs[2]);
> > +
> > + igt_plane_set_fb(primary, &data->fbs[2]);
> > + igt_fb_set_position(&data->fbs[2], primary,
> > + data->fbs[2].width - data-
> > >fbs[0].width,
> > + data->fbs[2].height - data-
> > >fbs[0].height);
> > + igt_fb_set_size(&data->fbs[2], primary, data->fbs[0].width,
> > + data->fbs[0].height);
> > +
> > + enable_feature(data);
> > +
> > + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> > +
> > + check_feature(data);
> > +}
> > +
> > +static void cleanup(data_t *data)
> > +{
> > + igt_remove_fb(data->drm_fd, &data->fbs[0]);
> > + igt_remove_fb(data->drm_fd, &data->fbs[1]);
> > +
> > + igt_pipe_crc_free(data->pipe_crc);
> > +
> > + disable_features(data);
> > +
> > + igt_output_set_pipe(data->output, PIPE_NONE);
> > +
> > + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> > +}
> > +
> > +static void run_test(data_t *data)
> > +{
> > + igt_crc_t crc;
> > + struct intel_buf *src, *dst;
> > + struct intel_bb *ibb;
> > + uint32_t devid = intel_get_drm_devid(data->drm_fd);
> > + igt_render_copyfunc_t rendercopy =
> > igt_get_render_copyfunc(devid);
> > + int r;
> > +
> > + igt_skip_on(!rendercopy);
> > +
> > + src = intel_buf_create_using_handle(data->bops, data-
> > >fbs[1].gem_handle,
> > + data->fbs[1].width,
> > + data->fbs[1].height,
> > +
> > igt_drm_format_to_bpp(data->fbs[1].drm_format),
> > + 0,
> > igt_fb_mod_to_tiling(data->fbs[1].modifier), 0);
> > + dst = intel_buf_create_using_handle(data->bops, data-
> > >fbs[2].gem_handle,
> > + data->fbs[2].width,
> > + data->fbs[2].height,
> > +
> > igt_drm_format_to_bpp(data->fbs[2].drm_format),
> > + 0,
> > igt_fb_mod_to_tiling(data->fbs[2].modifier), 0);
> > + ibb = intel_bb_create_with_context(data->drm_fd, 0, NULL,
> > PAGE_SIZE);
> > +
> > + rendercopy(ibb, src, 0, 0, data->fbs[2].width, data-
> > >fbs[2].height, dst, 0, 0);
> > +
> > + /* Perfom dirtyfb right after initiating rendercopy */
> > + r = drmModeDirtyFB(data->drm_fd, data->fbs[2].fb_id, NULL,
> > 0);
> > + igt_assert(r == 0 || r == -ENOSYS);
> > +
> > + /* Ensure rendercopy is complete */
> > + intel_bb_sync(ibb);
> > +
> > + intel_bb_destroy(ibb);
> > + intel_buf_destroy(src);
> > + intel_buf_destroy(dst);
> > +
> > + igt_pipe_crc_collect_crc(data->pipe_crc, &crc);
> > + igt_assert_crc_equal(&crc, &data->ref_crc);
> > +}
> > +
> > +igt_main
> > +{
> > + data_t data = {};
> > +
> > + igt_fixture {
> > + data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
> > + data.debugfs_fd = igt_debugfs_dir(data.drm_fd);
> > + kmstest_set_vt_graphics_mode();
> > +
> > + igt_display_require(&data.display, data.drm_fd);
> > +
> > + data.bops = buf_ops_create(data.drm_fd);
> > +
> > + igt_display_reset(&data.display);
> > + }
> > +
> > + igt_describe("Test dirtyFB ioctl");
> > + igt_subtest_with_dynamic("dirtyfb-ioctl") {
> > + data.pipe = PIPE_A;
> > + for_each_valid_output_on_pipe(&data.display,
> > data.pipe,
> > + data.output) {
> > + for (data.feature = FEATURE_DEFAULT;
> > data.feature > 0;
> > + data.feature = data.feature >> 1) {
> > + igt_dynamic_f("%s-%s",
> > feature_str(data.feature),
> > +
> > igt_output_name(data.output)) {
> > + prepare(&data);
> > + run_test(&data);
> > + cleanup(&data);
> > + }
> > + }
> > + }
> > + }
> > +
> > + igt_fixture {
> > + buf_ops_destroy(data.bops);
> > + igt_display_fini(&data.display);
> > + close(data.drm_fd);
> > + }
> > +}
> > diff --git a/tests/meson.build b/tests/meson.build
> > index 8fa69af3..a286a9b8 100644
> > --- a/tests/meson.build
> > +++ b/tests/meson.build
> > @@ -494,6 +494,14 @@ test_executables +=
> > executable('kms_frontbuffer_tracking',
> > install : true)
> > test_list += 'kms_frontbuffer_tracking'
> >
> > +test_executables += executable('kms_dirtyfb',
> > + [ join_paths('i915', 'kms_dirtyfb.c'), join_paths
> > ('i915', 'kms_fbc_helper.c'), join_paths ('i915',
> > 'kms_drrs_helper.c')],
> > + dependencies : test_deps,
> > + install_dir : libexecdir,
> > + install_rpath : libexecdir_rpathdir,
> > + install : true)
> > +test_list += 'kms_frontbuffer_tracking'
> > +
> > if chamelium.found()
> > test_executables += executable('kms_chamelium_color',
> > [ 'chamelium/kms_chamelium_color.c',
> > 'kms_color_helper.c' ],
> > --
> > 2.34.1
> >
BR,
Jouni Högander
More information about the igt-dev
mailing list