diff options
author | Matt Roper <matthew.d.roper@intel.com> | 2015-02-26 19:00:19 -0800 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-27 16:11:31 +0100 |
commit | 59d8d663cdac2d1f8e876d53f328e414a993c610 (patch) | |
tree | 262601e77ee1170826d69b17cf0e00c54d849c2a /tests/kms_universal_plane.c | |
parent | d73c5eb97747c899eda2648e238711f6d516b4c9 (diff) |
kms_universal_plane: Check for cursor fb leaks
We've been leaking the framebuffers that get created inside the
legacy -> universal cursor compatibility layer and nobody noticed. Add
an i-g-t test to check debugfs and ensure we end up the same number of
framebuffers we started with after performing cursor operations.
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'tests/kms_universal_plane.c')
-rw-r--r-- | tests/kms_universal_plane.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/tests/kms_universal_plane.c b/tests/kms_universal_plane.c index 6a05584f..78987447 100644 --- a/tests/kms_universal_plane.c +++ b/tests/kms_universal_plane.c @@ -532,6 +532,120 @@ pageflip_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) } static void +cursor_leak_test_fini(data_t *data, + igt_output_t *output, + struct igt_fb *bg, + struct igt_fb *curs) +{ + int i; + + igt_remove_fb(data->drm_fd, bg); + for (i = 0; i < 10; i++) + igt_remove_fb(data->drm_fd, &curs[i]); + + igt_output_set_pipe(output, PIPE_ANY); +} + +static int +i915_gem_fb_count(void) +{ + char buf[1024]; + FILE *fp; + int count = 0; + + fp = igt_debugfs_fopen("i915_gem_framebuffer", "r"); + igt_require(fp); + while (fgets(buf, sizeof(buf), fp) != NULL) + count++; + fclose(fp); + + return count; +} + +static void +cursor_leak_test_pipe(data_t *data, enum pipe pipe, igt_output_t *output) +{ + igt_display_t *display = &data->display; + igt_plane_t *primary, *cursor; + drmModeModeInfo *mode; + struct igt_fb background_fb; + struct igt_fb cursor_fb[10]; + int i; + int r, g, b; + int count1, count2; + + igt_assert(data->display.has_universal_planes); + igt_skip_on(pipe >= display->n_pipes); + + igt_output_set_pipe(output, pipe); + mode = igt_output_get_mode(output); + + /* Count GEM framebuffers before creating our cursor FB's */ + count1 = i915_gem_fb_count(); + + /* Black background FB */ + igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay, + DRM_FORMAT_XRGB8888, + false, + 0.0, 0.0, 0.0, + &background_fb); + + /* Random color cursors */ + for (i = 0; i < 10; i++) { + r = rand() % 0xFF; + g = rand() % 0xFF; + b = rand() % 0xFF; + igt_create_color_fb(data->drm_fd, 64, 64, + DRM_FORMAT_ARGB8888, + false, + (double)r / 0xFF, + (double)g / 0xFF, + (double)b / 0xFF, + &cursor_fb[i]); + } + + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY); + cursor = igt_output_get_plane(output, IGT_PLANE_CURSOR); + if (!primary || !cursor) { + cursor_leak_test_fini(data, output, &background_fb, cursor_fb); + igt_skip("Primary and/or cursor are unavailable\n"); + } + + + igt_plane_set_fb(primary, &background_fb); + igt_display_commit2(display, COMMIT_LEGACY); + + igt_plane_set_position(cursor, 100, 100); + + /* + * Exercise both legacy and universal code paths. Note that legacy + * handling in the kernel redirects through universal codepaths + * internally, so that redirection is where we're most worried about + * leaking. + */ + for (i = 0; i < 10; i++) { + igt_plane_set_fb(cursor, &cursor_fb[i]); + igt_display_commit2(display, COMMIT_UNIVERSAL); + } + for (i = 0; i < 10; i++) { + igt_plane_set_fb(cursor, &cursor_fb[i]); + igt_display_commit2(display, COMMIT_LEGACY); + } + + /* Release our framebuffer handles before we take a second count */ + igt_plane_set_fb(primary, NULL); + igt_plane_set_fb(cursor, NULL); + igt_display_commit2(display, COMMIT_LEGACY); + cursor_leak_test_fini(data, output, &background_fb, cursor_fb); + + /* We should be back to the same framebuffer count as when we started */ + count2 = i915_gem_fb_count(); + + igt_assert_f(count1 == count2, "Cursor framebuffer leak detected. " + "Initial fb count=%d, final count=%d\n", count1, count2); +} + +static void run_tests_for_pipe(data_t *data, enum pipe pipe) { igt_output_t *output; @@ -550,6 +664,11 @@ run_tests_for_pipe(data_t *data, enum pipe pipe) kmstest_pipe_name(pipe)) for_each_connected_output(&data->display, output) pageflip_test_pipe(data, pipe, output); + + igt_subtest_f("cursor-fb-leak-pipe-%s", + kmstest_pipe_name(pipe)) + for_each_connected_output(&data->display, output) + cursor_leak_test_pipe(data, pipe, output); } static data_t data; |