Re: [Intel-gfx] [PATCH v3 04/18] drm/selftest: Add drm damage helper selftest

Daniel Vetter
2018-10-16T12:21:17Z

On Mon, Oct 15, 2018 at 04:11:41PM +0000, Deepak Singh Rawat wrote:
> > On Wed, Oct 10, 2018 at 05:16:43PM -0700, Deepak Rawat wrote:
> > > Selftest for drm damage helper iterator functions.
> > >
> > > Cc: ville.syrjala@linux.intel.com
> > > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > Cc: Pekka Paalanen <ppaalanen@gmail.com>
> > > Cc: Daniel Stone <daniel@fooishbar.org>
> > > Cc: intel-gfx@lists.freedesktop.org
> > > Cc: igt-dev@lists.freedesktop.org
> > > Cc: petri.latvala@intel.com
> > > Cc: chris@chris-wilson.co.uk
> > > Signed-off-by: Deepak Rawat <drawat@vmware.com>
> > > ---
> > > drivers/gpu/drm/selftests/Makefile | 3 +-
> > > .../selftests/drm_damage_helper_selftests.h | 22 +
> > > .../drm/selftests/test-drm_damage_helper.c | 844
> > ++++++++++++++++++
> > > 3 files changed, 868 insertions(+), 1 deletion(-)
> > > create mode 100644
> > drivers/gpu/drm/selftests/drm_damage_helper_selftests.h
> > > create mode 100644 drivers/gpu/drm/selftests/test-
> > drm_damage_helper.c
> > >
> > > diff --git a/drivers/gpu/drm/selftests/Makefile
> > b/drivers/gpu/drm/selftests/Makefile
> > > index 9fc349fa18e9..88ac216f5962 100644
> > > --- a/drivers/gpu/drm/selftests/Makefile
> > > +++ b/drivers/gpu/drm/selftests/Makefile
> > > @@ -1 +1,2 @@
> > > -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm-
> > helper.o
> > > +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm-
> > helper.o \
> > > + test-drm_damage_helper.o
> >
> > With the testcase intagrated into the test-drm-helper.ko module, for
> > patches 1-4 in this series:
> >
> > Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> >
> > Obviously needs some adjusting on the igt side too, since we seem to be
> > missing the igt scaffolding for tests-drm-helper.ko.
> > -Daniel
>
> Hi Daniel,
>
> Thanks for the review. I am a little confused here. Should we have single
> kernel module for drm plane helper selftest and damage helper selftest?
> Also shall I rename the kernel selfttest to kms_*?
>
> For user-space igt test it should be it makes sense to rename to kms_selftets?

Since I went back&forth on this way too many times:
- igt should be called kms_selftest. Please work together with igt
maintainers (Arek and Petri), since we also need to update the CI
building infrastructure to make sure it updates the list of subtests
implemented by the kernel.

- Kernel module I'd call test-drm_modeset.ko. That kernel module can then
include the existing test-drm-helper.c (could probably rename to
test-drm_plane_helper.c for clarity) and your new damage helper (named
test-drm_damage_helper.c for consistency).

Does that make sense to everyone?

Thanks, Daniel

>
> >
> > > diff --git a/drivers/gpu/drm/selftests/drm_damage_helper_selftests.h
> > b/drivers/gpu/drm/selftests/drm_damage_helper_selftests.h
> > > new file mode 100644
> > > index 000000000000..3a1cbe05bef0
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/selftests/drm_damage_helper_selftests.h
> > > @@ -0,0 +1,22 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +selftest(damage_iter_no_damage, igt_damage_iter_no_damage)
> > > +selftest(damage_iter_no_damage_fractional_src,
> > igt_damage_iter_no_damage_fractional_src)
> > > +selftest(damage_iter_no_damage_src_moved,
> > igt_damage_iter_no_damage_src_moved)
> > > +selftest(damage_iter_no_damage_fractional_src_moved,
> > igt_damage_iter_no_damage_fractional_src_moved)
> > > +selftest(damage_iter_no_damage_not_visible,
> > igt_damage_iter_no_damage_not_visible)
> > > +selftest(damage_iter_no_damage_no_crtc,
> > igt_damage_iter_no_damage_no_crtc)
> > > +selftest(damage_iter_no_damage_no_fb,
> > igt_damage_iter_no_damage_no_fb)
> > > +selftest(damage_iter_simple_damage,
> > igt_damage_iter_simple_damage)
> > > +selftest(damage_iter_single_damage, igt_damage_iter_single_damage)
> > > +selftest(damage_iter_single_damage_intersect_src,
> > igt_damage_iter_single_damage_intersect_src)
> > > +selftest(damage_iter_single_damage_outside_src,
> > igt_damage_iter_single_damage_outside_src)
> > > +selftest(damage_iter_single_damage_fractional_src,
> > igt_damage_iter_single_damage_fractional_src)
> > > +selftest(damage_iter_single_damage_intersect_fractional_src,
> > igt_damage_iter_single_damage_intersect_fractional_src)
> > > +selftest(damage_iter_single_damage_outside_fractional_src,
> > igt_damage_iter_single_damage_outside_fractional_src)
> > > +selftest(damage_iter_single_damage_src_moved,
> > igt_damage_iter_single_damage_src_moved)
> > > +selftest(damage_iter_single_damage_fractional_src_moved,
> > igt_damage_iter_single_damage_fractional_src_moved)
> > > +selftest(damage_iter_damage, igt_damage_iter_damage)
> > > +selftest(damage_iter_damage_one_intersect,
> > igt_damage_iter_damage_one_intersect)
> > > +selftest(damage_iter_damage_one_outside,
> > igt_damage_iter_damage_one_outside)
> > > +selftest(damage_iter_damage_src_moved,
> > igt_damage_iter_damage_src_moved)
> > > +selftest(damage_iter_damage_not_visible,
> > igt_damage_iter_damage_not_visible)
> > > diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c
> > b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
> > > new file mode 100644
> > > index 000000000000..17754734c47a
> > > --- /dev/null
> > > +++ b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
> > > @@ -0,0 +1,844 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/*
> > > + * Test case for drm_damage_helper functions
> > > + */
> > > +
> > > +#define pr_fmt(fmt) "drm_damage_helper: " fmt
> > > +
> > > +#include <linux/module.h>
> > > +#include <drm/drm_damage_helper.h>
> > > +
> > > +#define TESTS "drm_damage_helper_selftests.h"
> > > +#include "drm_selftest.h"
> > > +
> > > +#define FAIL(test, msg, ...) \
> > > + do { \
> > > + if (test) { \
> > > + pr_err("%s/%u: " msg, __FUNCTION__, __LINE__,
> > ##__VA_ARGS__); \
> > > + return -EINVAL; \
> > > + } \
> > > + } while (0)
> > > +
> > > +#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
> > > +
> > > +static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int
> > x2,
> > > + int y2)
> > > +{
> > > + state->src.x1 = x1;
> > > + state->src.y1 = y1;
> > > + state->src.x2 = x2;
> > > + state->src.y2 = y2;
> > > +}
> > > +
> > > +static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int
> > x2,
> > > + int y2)
> > > +{
> > > + r->x1 = x1;
> > > + r->y1 = y1;
> > > + r->x2 = x2;
> > > + r->y2 = y2;
> > > +}
> > > +
> > > +static void set_damage_blob(struct drm_property_blob *damage_blob,
> > > + struct drm_mode_rect *r, uint32_t size)
> > > +{
> > > + damage_blob->length = size;
> > > + damage_blob->data = r;
> > > +}
> > > +
> > > +static void set_plane_damage(struct drm_plane_state *state,
> > > + struct drm_property_blob *damage_blob)
> > > +{
> > > + state->fb_damage_clips = damage_blob;
> > > +}
> > > +
> > > +static bool check_damage_clip(struct drm_plane_state *state, struct
> > drm_rect *r,
> > > + int x1, int y1, int x2, int y2)
> > > +{
> > > + /*
> > > + * Round down x1/y1 and round up x2/y2. This is because damage is
> > not in
> > > + * 16.16 fixed point so to catch all pixels.
> > > + */
> > > + int src_x1 = state->src.x1 >> 16;
> > > + int src_y1 = state->src.y1 >> 16;
> > > + int src_x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF);
> > > + int src_y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
> > > +
> > > + if (x1 >= x2 || y1 >= y2) {
> > > + pr_err("Cannot have damage clip with no dimention.\n");
> > > + return false;
> > > + }
> > > +
> > > + if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2) {
> > > + pr_err("Damage cannot be outside rounded plane src.\n");
> > > + return false;
> > > + }
> > > +
> > > + if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2) {
> > > + pr_err("Damage = %d %d %d %d\n", r->x1, r->y1, r->x2, r-
> > >y2);
> > > + return false;
> > > + }
> > > +
> > > + return true;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src same as fb size. */
> > > + set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16);
> > > + set_plane_src(&state, 0, 0, fb.width << 16, fb.height << 16);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return plane src as damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 2048, 2048));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_fractional_src(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src has fractional part. */
> > > + set_plane_src(&old_state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + set_plane_src(&state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return rounded off plane src as
> > damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_src_moved(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src moved since old plane state. */
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 10 << 16, 10 << 16,
> > > + (10 + 1024) << 16, (10 + 768) << 16);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return plane src as damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_fractional_src_moved(void
> > *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src has fractional part and it moved since old plane state. */
> > > + set_plane_src(&old_state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return plane src as damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_not_visible(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = false,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should have no damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_no_crtc(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = 0,
> > > + .fb = &fb,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should have no damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_no_damage_no_fb(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = 0,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should have no damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_simple_damage(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + /* Damage set to plane src */
> > > + set_damage_clip(&damage, 0, 0, 1024, 768);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage when set.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 1024, 768));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_damage_clip(&damage, 256, 192, 768, 576);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage when set.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 768, 576));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_intersect_src(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + /* Damage intersect with plane src. */
> > > + set_damage_clip(&damage, 256, 192, 1360, 768);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage clipped to src.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 1024, 768));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_outside_src(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + /* Damage clip outside plane src */
> > > + set_damage_clip(&damage, 1360, 1360, 1380, 1380);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should have no damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_fractional_src(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src has fractional part. */
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_damage_clip(&damage, 10, 10, 256, 330);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage when set.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 256, 330));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_intersect_fractional_src(void
> > *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src has fractional part. */
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + /* Damage intersect with plane src. */
> > > + set_damage_clip(&damage, 10, 1, 1360, 330);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage clipped to rounded off
> > src.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 10, 4, 1029, 330));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_outside_fractional_src(void
> > *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src has fractional part. */
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + /* Damage clip outside plane src */
> > > + set_damage_clip(&damage, 1360, 1360, 1380, 1380);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should have no damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_src_moved(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src moved since old plane state. */
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 10 << 16, 10 << 16,
> > > + (10 + 1024) << 16, (10 + 768) << 16);
> > > + set_damage_clip(&damage, 20, 30, 256, 256);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return plane src as damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_single_damage_fractional_src_moved(void
> > *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage;
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + /* Plane src with fractional part moved since old plane state. */
> > > + set_plane_src(&old_state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + /* Damage intersect with plane src. */
> > > + set_damage_clip(&damage, 20, 30, 1360, 256);
> > > + set_damage_blob(&damage_blob, &damage, sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return rounded off plane src as
> > damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_damage(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage[2];
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + /* 2 damage clips. */
> > > + set_damage_clip(&damage[0], 20, 30, 200, 180);
> > > + set_damage_clip(&damage[1], 240, 200, 280, 250);
> > > + set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip) {
> > > + if (num_hits == 0)
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 20, 30,
> > 200, 180));
> > > + if (num_hits == 1)
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 240,
> > 200, 280, 250));
> > > + num_hits++;
> > > + }
> > > +
> > > + FAIL(num_hits != 2, "Should return damage when set.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_damage_one_intersect(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage[2];
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + /* 2 damage clips, one intersect plane src. */
> > > + set_damage_clip(&damage[0], 20, 30, 200, 180);
> > > + set_damage_clip(&damage[1], 2, 2, 1360, 1360);
> > > + set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip) {
> > > + if (num_hits == 0)
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 20, 30,
> > 200, 180));
> > > + if (num_hits == 1)
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 4, 4,
> > 1029, 773));
> > > + num_hits++;
> > > + }
> > > +
> > > + FAIL(num_hits != 2, "Should return damage when set.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_damage_one_outside(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage[2];
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
> > > + set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
> > > + /* 2 damage clips, one outside plane src. */
> > > + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
> > > + set_damage_clip(&damage[1], 240, 200, 280, 250);
> > > + set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return damage when set.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_damage_src_moved(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage[2];
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = true,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + /* 2 damage clips, one outside plane src. */
> > > + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
> > > + set_damage_clip(&damage[1], 240, 200, 280, 250);
> > > + set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 1, "Should return round off plane src as damage.");
> > > + FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int igt_damage_iter_damage_not_visible(void *ignored)
> > > +{
> > > + struct drm_atomic_helper_damage_iter iter;
> > > + struct drm_plane_state old_state;
> > > + struct drm_property_blob damage_blob;
> > > + struct drm_mode_rect damage[2];
> > > + struct drm_rect clip;
> > > + uint32_t num_hits = 0;
> > > +
> > > + struct drm_framebuffer fb = {
> > > + .width = 2048,
> > > + .height = 2048
> > > + };
> > > +
> > > + struct drm_plane_state state = {
> > > + .crtc = ZERO_SIZE_PTR,
> > > + .fb = &fb,
> > > + .visible = false,
> > > + };
> > > +
> > > + set_plane_src(&old_state, 0x40002, 0x40002,
> > > + 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
> > > + set_plane_src(&state, 0x3fffe, 0x3fffe,
> > > + 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
> > > + /* 2 damage clips, one outside plane src. */
> > > + set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
> > > + set_damage_clip(&damage[1], 240, 200, 280, 250);
> > > + set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
> > > + set_plane_damage(&state, &damage_blob);
> > > + drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
> > > + drm_atomic_for_each_plane_damage(&iter, &clip)
> > > + num_hits++;
> > > +
> > > + FAIL(num_hits != 0, "Should not return any damage.");
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +#include "drm_selftest.c"
> > > +
> > > +static int __init test_drm_damage_helper_init(void)
> > > +{
> > > + int err;
> > > +
> > > + err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
> > > +
> > > + return err > 0 ? 0 : err;
> > > +}
> > > +
> > > +static void __exit test_drm_damage_helper_exit(void)
> > > +{
> > > +}
> > > +
> > > +module_init(test_drm_damage_helper_init);
> > > +module_exit(test_drm_damage_helper_exit);
> > > +
> > > +MODULE_AUTHOR("VMware Inc.");
> > > +MODULE_LICENSE("GPL");
> > > --
> > > 2.17.1
> > >
> >
> > --
> > Daniel Vetter
> > Software Engineer, Intel Corporation
> > https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fblog.ff
> > wll.ch&amp;data=02%7C01%7Cdrawat%40vmware.com%7C64e7deb3dc264c
> > 6f11a008d62f95d96e%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7
> > C636748717979714197&amp;sdata=vCz71L%2BoMpFSGFZifg%2F0bR1CxzReLa
> > 7Dy3ss3UKeLrU%3D&amp;reserved=0

--
Daniel Vetter
Software Engineer, Intel Corporation