drm/selftest: Add drm damage helper selftest
authorDeepak Rawat <drawat@vmware.com>
Mon, 15 Oct 2018 18:07:08 +0000 (11:07 -0700)
committerThomas Hellstrom <thellstrom@vmware.com>
Wed, 5 Dec 2018 09:00:36 +0000 (10:00 +0100)
Selftest for drm damage helper iterator functions.

v2: Rebase to new test-drm_modeset.

Signed-off-by: Deepak Rawat <drawat@vmware.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
drivers/gpu/drm/selftests/Makefile
drivers/gpu/drm/selftests/drm_modeset_selftests.h
drivers/gpu/drm/selftests/test-drm_damage_helper.c [new file with mode: 0644]
drivers/gpu/drm/selftests/test-drm_modeset_common.h

index 383d8d6c584779f242ba064adb78d8d3dd6330b0..1bb73dc4c88ce06520eee0c44ae20fbbf82b364f 100644 (file)
@@ -1,4 +1,5 @@
 test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
-                      test-drm_format.o test-drm_framebuffer.o
+                      test-drm_format.o test-drm_framebuffer.o \
+                     test-drm_damage_helper.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o
index 92601defd8f625efeb23b5990ce63bc0f13d9eba..46475374601333609c633cc6ef67daf73ae204f7 100644 (file)
@@ -11,3 +11,24 @@ selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
 selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
 selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch)
 selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
+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 (file)
index 0000000..a2f7532
--- /dev/null
@@ -0,0 +1,811 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test case for drm_damage_helper functions
+ */
+
+#define pr_fmt(fmt) "drm_damage_helper: " fmt
+
+#include <drm/drm_damage_helper.h>
+
+#include "test-drm_modeset_common.h"
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
index d5df5bd51b052aa27053625a21f2b150f02744af..8c76f09c12d1108a2d36296ac6ec49761c529697 100644 (file)
@@ -18,5 +18,26 @@ int igt_check_drm_format_block_width(void *ignored);
 int igt_check_drm_format_block_height(void *ignored);
 int igt_check_drm_format_min_pitch(void *ignored);
 int igt_check_drm_framebuffer_create(void *ignored);
+int igt_damage_iter_no_damage(void *ignored);
+int igt_damage_iter_no_damage_fractional_src(void *ignored);
+int igt_damage_iter_no_damage_src_moved(void *ignored);
+int igt_damage_iter_no_damage_fractional_src_moved(void *ignored);
+int igt_damage_iter_no_damage_not_visible(void *ignored);
+int igt_damage_iter_no_damage_no_crtc(void *ignored);
+int igt_damage_iter_no_damage_no_fb(void *ignored);
+int igt_damage_iter_simple_damage(void *ignored);
+int igt_damage_iter_single_damage(void *ignored);
+int igt_damage_iter_single_damage_intersect_src(void *ignored);
+int igt_damage_iter_single_damage_outside_src(void *ignored);
+int igt_damage_iter_single_damage_fractional_src(void *ignored);
+int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored);
+int igt_damage_iter_single_damage_outside_fractional_src(void *ignored);
+int igt_damage_iter_single_damage_src_moved(void *ignored);
+int igt_damage_iter_single_damage_fractional_src_moved(void *ignored);
+int igt_damage_iter_damage(void *ignored);
+int igt_damage_iter_damage_one_intersect(void *ignored);
+int igt_damage_iter_damage_one_outside(void *ignored);
+int igt_damage_iter_damage_src_moved(void *ignored);
+int igt_damage_iter_damage_not_visible(void *ignored);
 
 #endif