Message ID | 20181011001657.1715-4-drawat@vmware.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v3,01/18] drm: Add a new plane property to send damage during plane update | expand |
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 > 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 >
> 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? > > > 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&data=02%7C01%7Cdrawat%40vmware.com%7C64e7deb3dc264c > 6f11a008d62f95d96e%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7 > C636748717979714197&sdata=vCz71L%2BoMpFSGFZifg%2F0bR1CxzReLa > 7Dy3ss3UKeLrU%3D&reserved=0
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&data=02%7C01%7Cdrawat%40vmware.com%7C64e7deb3dc264c > > 6f11a008d62f95d96e%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7 > > C636748717979714197&sdata=vCz71L%2BoMpFSGFZifg%2F0bR1CxzReLa > > 7Dy3ss3UKeLrU%3D&reserved=0
On Tue, Oct 16, 2018 at 02:21:17PM +0200, Daniel Vetter wrote: > 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? I was trying to add some selftests, as well here [1], with that in mind, I think it makes sense to have just one module, call it "test-drm_modeset" or whatever and separate the tests source code base on whatever core functionality they are testing. Besides compiling everything together, probably some stuff will have to move out of test-drm-helper.c into some common header. For example this "FAIL/FAIL_ON" macros [1] https://lists.freedesktop.org/archives/dri-devel/2018-October/192973.html > > 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&data=02%7C01%7Cdrawat%40vmware.com%7C64e7deb3dc264c > > > 6f11a008d62f95d96e%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7 > > > C636748717979714197&sdata=vCz71L%2BoMpFSGFZifg%2F0bR1CxzReLa > > > 7Dy3ss3UKeLrU%3D&reserved=0 > > -- > Daniel Vetter > Software Engineer, Intel Corporation > http://blog.ffwll.ch > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> > > 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? > Yes it makes sense to me and in fact I had similar changes in mind. And, since existing plane selftest are not invoked from igt it's safe to rename kernel module.
> > On Tue, Oct 16, 2018 at 02:21:17PM +0200, Daniel Vetter wrote: > > 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? > > I was trying to add some selftests, as well here [1], with that in > mind, I think it makes sense to have just one module, call it > "test-drm_modeset" or whatever and separate the tests source code base > on whatever core functionality they are testing. > > Besides compiling everything together, probably some stuff will have > to move out of test-drm-helper.c into some common header. For example > this "FAIL/FAIL_ON" macros > Hi, Thanks for your input. I have similar change in mind after suggestion from Daniel. Below is initial draft I did yesterday, will move common code to a common header. I hope this aligns with what you are doing. --- drivers/gpu/drm/selftests/Makefile | 4 ++- .../gpu/drm/selftests/drm_helper_selftests.c | 27 +++++++++++++++++++ .../gpu/drm/selftests/drm_helper_selftests.h | 15 +++++------ ...-helper.c => drm_plane_helper_selftests.c} | 16 ++++------- .../selftests/drm_plane_helper_selftests.h | 9 +++++++ 5 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 drivers/gpu/drm/selftests/drm_helper_selftests.c rename drivers/gpu/drm/selftests/{test-drm-helper.c => drm_plane_helper_selftests.c} (96%) create mode 100644 drivers/gpu/drm/selftests/drm_plane_helper_selftests.h diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile index 9fc349fa18e9..560117d64658 100644 --- a/drivers/gpu/drm/selftests/Makefile +++ b/drivers/gpu/drm/selftests/Makefile @@ -1 +1,3 @@ -obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm-helper.o +test-drm_helper-y := drm_helper_selftests.o drm_plane_helper_selftests.o + +obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_helper.o diff --git a/drivers/gpu/drm/selftests/drm_helper_selftests.c b/drivers/gpu/drm/selftests/drm_helper_selftests.c new file mode 100644 index 000000000000..873db462fa35 --- /dev/null +++ b/drivers/gpu/drm/selftests/drm_helper_selftests.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Test cases for the drm_kms_helper functions + */ + +#include <linux/module.h> + +#include "drm_helper_selftests.h" + +static int __init test_drm_helper_init(void) +{ + int err; + + err = drm_run_plane_helper_selftests(); + + return err; +} + +static void __exit test_drm_helper_exit(void) +{ +} + +module_init(test_drm_helper_init); +module_exit(test_drm_helper_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/selftests/drm_helper_selftests.h b/drivers/gpu/drm/selftests/drm_helper_selftests.h index 9771290ed228..82d076a20bb3 100644 --- a/drivers/gpu/drm/selftests/drm_helper_selftests.h +++ b/drivers/gpu/drm/selftests/drm_helper_selftests.h @@ -1,9 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* List each unit test as selftest(name, function) - * - * The name is used as both an enum and expanded as igt__name to create - * a module parameter. It must be unique and legal for a C identifier. - * - * Tests are executed in order by igt/drm_selftests_helper - */ -selftest(check_plane_state, igt_check_plane_state) + +#ifndef __TEST_DRM_HELPER_H__ +#define __TEST_DRM_HELPER_H__ + +int drm_run_plane_helper_selftests(void); + +#endif diff --git a/drivers/gpu/drm/selftests/test-drm-helper.c b/drivers/gpu/drm/selftests/drm_plane_helper_selftests.c similarity index 96% rename from drivers/gpu/drm/selftests/test-drm-helper.c rename to drivers/gpu/drm/selftests/drm_plane_helper_selftests.c index a015712b43e8..11941c14a791 100644 --- a/drivers/gpu/drm/selftests/test-drm-helper.c +++ b/drivers/gpu/drm/selftests/drm_plane_helper_selftests.c @@ -1,16 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Test cases for the drm_kms_helper functions + * Test cases for the drm_plane_helper functions */ -#define pr_fmt(fmt) "drm_kms_helper: " fmt - -#include <linux/module.h> +#define pr_fmt(fmt) "drm_plane_helper: " fmt #include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_modes.h> -#define TESTS "drm_helper_selftests.h" +#define TESTS "drm_plane_helper_selftests.h" #include "drm_selftest.h" #define FAIL(test, msg, ...) \ @@ -232,7 +231,7 @@ static int igt_check_plane_state(void *ignored) #include "drm_selftest.c" -static int __init test_drm_helper_init(void) +int drm_run_plane_helper_selftests(void) { int err; @@ -240,8 +239,3 @@ static int __init test_drm_helper_init(void) return err > 0 ? 0 : err; } - -module_init(test_drm_helper_init); - -MODULE_AUTHOR("Intel Corporation"); -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/selftests/drm_plane_helper_selftests.h b/drivers/gpu/drm/selftests/drm_plane_helper_selftests.h new file mode 100644 index 000000000000..9771290ed228 --- /dev/null +++ b/drivers/gpu/drm/selftests/drm_plane_helper_selftests.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* List each unit test as selftest(name, function) + * + * The name is used as both an enum and expanded as igt__name to create + * a module parameter. It must be unique and legal for a C identifier. + * + * Tests are executed in order by igt/drm_selftests_helper + */ +selftest(check_plane_state, igt_check_plane_state)
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 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");
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