diff options
author | Mika Kahola <mika.kahola@intel.com> | 2016-11-23 11:19:37 +0200 |
---|---|---|
committer | Mika Kahola <mika.kahola@intel.com> | 2017-01-13 14:57:31 +0200 |
commit | 12e34d8c909a6bd203722a92a019693fec779db6 (patch) | |
tree | eab18a89e9f23f9195ed7bc4355372774c1fe87b /lib | |
parent | ef8cff635c8cee75a623753237c5e774a7b0b95f (diff) |
tests/kms_plane_lowres: Plane visibility after atomic modesets
Testcase for plane visibility after atomic modesets. The idea of the test
is the following:
- draw a blue screen with high resolution
- enable a yellow plane, visible, in lower-left corner
- set a new lower resolution mode (1024x768) that makes plane invisible
- check from debugfs 'i915_display_info' that the plane is invisible
- switch back to higher resolution mode
- check from debugfs 'i915_display_info' that the plane is visible again
- repeat number of iterations, default 64
v2: allow test to be run on non-Intel drivers (Daniel)
moved test for plane visibility to as helper function (Daniel)
moved get_vblank() function to be part of helper functions (Daniel)
rename 'tiling' parameter as 'modifier' (Daniel)
select a mode from a list so that the plane should be invisible.
use default 1024x768 mode only as a fallback if decent mode has not
been found (Daniel)
add tiling MODE_NONE (Daniel)
v3: draw as many overlay planes as the platform supports + cursor plane
on top of each other on lower-left corner
skip the test if i915_display_info file is not available
test plane visibility with igt_assert_plane_visibility() function
drop option for multiple test iterations (Daniel Vetter)
v4: switch 'for_each_connected_output()' to
'for_each_valid_output_on_pipe()'
skip Y and Yf tiling for generations older than 9 (Maarten)
Cc: Daniel Stone <daniel@fooishbar.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Mika Kahola <mika.kahola@intel.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/igt_kms.c | 161 | ||||
-rw-r--r-- | lib/igt_kms.h | 23 |
2 files changed, 184 insertions, 0 deletions
diff --git a/lib/igt_kms.c b/lib/igt_kms.c index eefe32f7..2c5a6e89 100644 --- a/lib/igt_kms.c +++ b/lib/igt_kms.c @@ -324,6 +324,24 @@ const char *kmstest_pipe_name(enum pipe pipe) } /** + * kmstest_pipe_to_index: + *@pipe: display pipe in string format + * + * Returns: index to corresponding pipe + */ +int kmstest_pipe_to_index(char pipe) +{ + if (pipe == 'A') + return 0; + else if (pipe == 'B') + return 1; + else if (pipe == 'C') + return 2; + else + return -EINVAL; +} + +/** * kmstest_plane_name: * @plane: display plane * @@ -1181,6 +1199,149 @@ int kmstest_get_crtc_idx(drmModeRes *res, uint32_t crtc_id) igt_assert(false); } +static inline uint32_t pipe_select(int pipe) +{ + if (pipe > 1) + return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT; + else if (pipe > 0) + return DRM_VBLANK_SECONDARY; + else + return 0; +} + +unsigned int kmstest_get_vblank(int fd, int pipe, unsigned int flags) +{ + union drm_wait_vblank vbl; + + memset(&vbl, 0, sizeof(vbl)); + vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe) | flags; + if (drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl)) + return 0; + + return vbl.reply.sequence; +} + +static void get_plane(char *str, int type, struct kmstest_plane *plane) +{ + int ret; + char buf[256]; + + plane->plane = type; + ret = sscanf(str + 12, "%d%*c %*s %[^n]s", + &plane->id, + buf); + igt_assert_eq(ret, 2); + + ret = sscanf(buf + 9, "%4d%*c%4d%*c", &plane->pos_x, &plane->pos_y); + igt_assert_eq(ret, 2); + + ret = sscanf(buf + 30, "%4d%*c%4d%*c", &plane->width, &plane->height); + igt_assert_eq(ret, 2); +} + +static int parse_planes(FILE *fid, struct kmstest_plane *plane) +{ + char tmp[256]; + int nplanes; + int ovl; + + ovl = 0; + nplanes = 0; + while (fgets(tmp, 256, fid) != NULL) { + igt_assert_neq(nplanes, IGT_MAX_PLANES); + if (strstr(tmp, "type=PRI") != NULL) { + get_plane(tmp, IGT_PLANE_PRIMARY, &plane[nplanes]); + nplanes++; + } else if (strstr(tmp, "type=OVL") != NULL) { + get_plane(tmp, IGT_PLANE_2 + ovl, &plane[nplanes]); + ovl++; + nplanes++; + } else if (strstr(tmp, "type=CUR") != NULL) { + get_plane(tmp, IGT_PLANE_CURSOR, &plane[nplanes]); + nplanes++; + break; + } + } + + return nplanes; +} + +static void parse_crtc(char *info, struct kmstest_crtc *crtc) +{ + char buf[256]; + int ret; + char pipe; + + ret = sscanf(info + 4, "%d%*c %*s %c%*c %*s %s%*c", + &crtc->id, &pipe, buf); + igt_assert_eq(ret, 3); + + crtc->pipe = kmstest_pipe_to_index(pipe); + igt_assert(crtc->pipe >= 0); + + ret = sscanf(buf + 6, "%d%*c%d%*c", + &crtc->width, &crtc->height); + igt_assert_eq(ret, 2); +} + +void kmstest_get_crtc(enum pipe pipe, struct kmstest_crtc *crtc) +{ + char tmp[256]; + FILE *fid; + const char *mode = "r"; + int ncrtc; + int line; + + fid = igt_debugfs_fopen("i915_display_info", mode); + + igt_skip_on(fid == NULL); + + ncrtc = 0; + line = 0; + while (fgets(tmp, 256, fid) != NULL) { + if ((strstr(tmp, "CRTC") != NULL) && (line > 0)) { + if (strstr(tmp, "active=yes") != NULL) { + crtc->active = true; + parse_crtc(tmp, crtc); + crtc->nplanes = parse_planes(fid, crtc->plane); + + if (crtc->pipe != pipe) + crtc = NULL; + else + ncrtc++; + } + } + + line++; + } + + fclose(fid); + + igt_skip_on(ncrtc == 0); +} + +void igt_assert_plane_visible(enum pipe pipe, bool visibility) +{ + struct kmstest_crtc crtc; + int i; + bool visible; + + kmstest_get_crtc(pipe, &crtc); + + visible = true; + for (i = IGT_PLANE_2; i < crtc.nplanes; i++) { + if (crtc.plane[i].pos_x > crtc.width) { + visible = false; + break; + } else if (crtc.plane[i].pos_y > crtc.height) { + visible = false; + break; + } + } + + igt_assert_eq(visible, visibility); +} + /* * A small modeset API */ diff --git a/lib/igt_kms.h b/lib/igt_kms.h index b12c67fb..81be77f5 100644 --- a/lib/igt_kms.h +++ b/lib/igt_kms.h @@ -57,6 +57,7 @@ enum pipe { I915_MAX_PIPES }; const char *kmstest_pipe_name(enum pipe pipe); +int kmstest_pipe_to_index(char pipe); /* We namespace this enum to not conflict with the Android i915_drm.h */ enum igt_plane { @@ -132,6 +133,25 @@ struct kmstest_connector_config { unsigned valid_crtc_idx_mask; }; +struct kmstest_plane { + int id; + int plane; + int pos_x; + int pos_y; + int width; + int height; +}; + +struct kmstest_crtc { + int id; + int pipe; + bool active; + int width; + int height; + int nplanes; + struct kmstest_plane plane[IGT_MAX_PLANES]; +}; + /** * kmstest_force_connector_state: * @FORCE_CONNECTOR_UNSPECIFIED: Unspecified @@ -177,6 +197,9 @@ uint32_t kmstest_dumb_create(int fd, int width, int height, int bpp, void *kmstest_dumb_map_buffer(int fd, uint32_t handle, uint64_t size, unsigned prot); +unsigned int kmstest_get_vblank(int fd, int pipe, unsigned int flags); +void kmstest_get_crtc(enum pipe pipe, struct kmstest_crtc *crtc); +void igt_assert_plane_visible(enum pipe pipe, bool visibility); /* * A small modeset API |