Re: [igt-dev] [RESEND,v3 5/5] kms_plane: Add clipping subtests

Mun, Gwan-gyeong
2018-09-07T15:19:09Z

Hi Imre,

Thanks for reviewing patches.

On Fri, 2018-09-07 at 13:48 +0300, Imre Deak wrote:
> Hi G.G.,
>
> Thanks for doing this, looks ok in general. Few comments below.
>
> On Thu, Sep 06, 2018 at 10:24:00AM +0300, Gwan-gyeong Mun wrote:
> > From: Imre Deak <imre.deak@intel.com>
> >
> > Add plane clipping subtests displaying a single clipped plane, with
> > the
> > following test cases:
> > a) plane covering the whole screen, so that clipping is done at all
> > 4
> > screen edges
> > b) plane at either of the 4 corners of the screen clipped, so that
> > a
> > 4x4 pixel part of the plane is visible
> > c) plane at either of the 4 corners of the screen clipped, so that
> > a
> > 2x2 pixel part of the plane is visible
> >
> > Each of the above cases are tested with all supported tiling modes,
> > rotation degrees, differing pixel format sizes (only 16 bpp and 32
> > bpp
> > for now) and certain planes. While the a) and b) cases above are
> > supported on all platforms c) is not fully supported on GLK and CNL
> > (which was the primary motivation for this testcase).
> >
> > v2:
> > - Add missing reset for the output pipe after finishing the test
> > for a
> > given output, fixing the
> > "DP-1 and eDP-1 are both trying to use pipe A" type of errors.
> > - Use -ERANGE instead of -EINVAL to check the return code for
> > unsupported plane X positions, based on the latest kernel code.
> > - Add comment explaining the dependencies when doing a universal
> > commit.
> >
> > v3: (Gwan-gyeong)
> > - Add missing release of framebuffer on
> > create_fb_for_mode__clipping_display()
> > function.
> > - Add using multi planes per single display commit on clipping test
> > of
> > 4 corners. (Daniel)
> > It enables the improving of test speed. If number of planes is
> > over
> > than 4, it uses four planes from first plane to next four planes.
> > (4 planes make testing of 4 corners possible as 1 display
> > commit.)
> > If number of planes is over than 2 and less than 4, it uses two
> > planes
> > from first plane to next two planes. (2 planes make testing of 4
> > corners
> > possible as 2 display commit.) Rest of cases it uses only first
> > plane.
> > (1 plane makes testing of 4 corners possible as 4 display
> > commit.)
> > It changes to using of certain planes from using of all supported
> > planes.
> > And a cursor plane can be one of test planes.
> >
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > Signed-off-by: Gwan-gyeong Mun <gwan-gyeong.mun@intel.com>
> > Cc: Mika Kahola <mika.kahola@intel.com>
> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> > Cc: Juha-Pekka Heikkilä <juha-pekka.heikkila@intel.com>
> > Reviewed-by: Arkadiusz Hiler <arkadiusz.hiler@intel.com> (v1)
> > ---
> > tests/kms_plane.c | 529
> > ++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 529 insertions(+)
> >
> > diff --git a/tests/kms_plane.c b/tests/kms_plane.c
> > index 3d08893f..ea62efed 100644
> > --- a/tests/kms_plane.c
> > +++ b/tests/kms_plane.c
> > @@ -41,11 +41,40 @@ typedef struct {
> > int drm_fd;
> > igt_display_t display;
> > igt_pipe_crc_t *pipe_crc;
> > + uint32_t devid;
> > + uint64_t max_curw;
> > + uint64_t max_curh;
> > } data_t;
> >
> > +typedef struct {
> > + int x;
> > + int y;
> > + int size;
> > +} square_t;
> > +
> > static color_t red = { 1.0f, 0.0f, 0.0f };
> > static color_t green = { 0.0f, 1.0f, 0.0f };
> > +static color_t yellow = { 1.0f, 1.0f, 0.0f };
> > static color_t blue = { 0.0f, 0.0f, 1.0f };
> > +static color_t white = { 1.0f, 1.0f, 1.0f };
> > +static square_t clip_squares[4];
> > +
> > +/*
> > + * Size of a square plane used to test clipping at the 4 courners
> > of the
> > + * display.
> > + */
> > +#define CLIPPED_PLANE_SMALL_SIZE 64
> > +
> > +/*
> > + * Visible plane size after clipping that works on all platforms
> > for all plane
> > + * positions.
> > + * The exceptions are GLK/CNL where there must be at least this
> > many pixels
> > + * visible from the plane after it's clipped to the left/right
> > edge of the
> > + * screen. Not meeting this condition may trigger FIFO underflows
> > and screen
> > + * corruption. The cursor plane is an exception that doesn't have
> > this problem
> > + * even on GLK/CNL.
> > + */
> > +#define CLIPPED_PLANE_MIN_VALID 4
> >
> > /*
> > * Common code across all tests, acting on data_t
> > @@ -151,6 +180,69 @@ create_fb_for_mode__position(data_t *data,
> > drmModeModeInfo *mode,
> > igt_put_cairo_ctx(data->drm_fd, fb, cr);
> > }
> >
> > +/*
> > + * Create a square FB for the plane in the clipping test, divided
> > into 4
> > + * quarters solid filled with different colors. Use the given
> > tiling, format
> > + * and size and rotate the FB clockwise with the given rotation
> > degrees, so
> > + * that the counterclockwise rotation with the same degrees done
> > by the HW
> > + * will always result in the same reference FB image.
> > + */
> > +static void
> > +create_fb_for_mode__clipping_plane(data_t *data, igt_rotation_t
> > rotation,
> > + uint64_t tiling,
> > + uint32_t format,
> > + int size,
> > + struct igt_fb *fb /* out */)
> > +{
> > + color_t corners[] = { red, white, yellow, blue };
> > + color_t color;
> > + unsigned int fb_id;
> > + cairo_t *cr;
> > + const int qsize = size / 2;
> > + int idx;
> > +
> > + fb_id = igt_create_fb(data->drm_fd, size, size, format, tiling,
> > fb);
> > + igt_assert(fb_id);
> > +
> > + cr = igt_get_cairo_ctx(data->drm_fd, fb);
> > +
> > + switch (rotation) {
> > + case IGT_ROTATION_0:
> > + idx = 0;
> > + break;
> > + case IGT_ROTATION_90:
> > + idx = 3;
> > + break;
> > + case IGT_ROTATION_180:
> > + idx = 2;
> > + break;
> > + case IGT_ROTATION_270:
> > + idx = 1;
> > + break;
> > + default:
> > + igt_assert(0);
> > + }
> > +
> > + color = corners[idx];
> > + igt_paint_color(cr, 0, 0, qsize, qsize,
> > + color.red, color.green, color.blue);
> > +
> > + color = corners[(++idx) % 4];
> > + igt_paint_color(cr, qsize, 0, qsize, qsize,
> > + color.red, color.green, color.blue);
> > +
> > + color = corners[(++idx) % 4];
> > + igt_paint_color(cr, qsize, qsize, qsize, qsize,
> > + color.red, color.green, color.blue);
> > +
> > + color = corners[(++idx) % 4];
> > + igt_paint_color(cr, 0, qsize, qsize, qsize,
> > + color.red, color.green, color.blue);
> > +
> > + igt_assert(cairo_status(cr) == 0);
> > + cairo_destroy(cr);
> > +}
> > +
> > enum {
> > TEST_POSITION_FULLY_COVERED = 1 << 0,
> > TEST_DPMS = 1 << 1,
> > @@ -554,6 +646,427 @@ test_pixel_formats(data_t *data, enum pipe
> > pipe)
> > }
> > }
> >
> > +static bool
> > +bogus_plane_conf(uint32_t devid, igt_plane_t *plane_obj,
> > + int hdisplay, int plane_x, int plane_width)
> > +{
> > + if (!(IS_GEMINILAKE(devid) || IS_CANNONLAKE(devid)))
> > + return false;
> > +
> > + if (plane_obj->type == DRM_PLANE_TYPE_CURSOR)
> > + return false;
> > +
> > + if (plane_x + plane_width >= CLIPPED_PLANE_MIN_VALID &&
> > + plane_x <= hdisplay - CLIPPED_PLANE_MIN_VALID)
> > + return false;
> > +
> > + return true;
> > +}
> > +
> > +static bool
> > +supported_plane_conf(data_t *data, int plane_type, uint64_t
> > tiling,
> > + uint32_t format, igt_rotation_t rotation,
> > + drmModeModeInfo *mode,
> > + int plane_x, int plane_y, int plane_size)
> > +{
> > + if (intel_gen(data->devid) < 9 &&
> > + tiling != LOCAL_DRM_FORMAT_MOD_NONE)
> > + return false;
> > +
> > + /* On GEN<9 the primary plane must cover the full screen. */
> > + if (intel_gen(data->devid) < 9 &&
> > + plane_type == DRM_PLANE_TYPE_PRIMARY &&
> > + (plane_x > 0 || plane_y > 0 ||
> > + (plane_x + plane_size < mode->hdisplay) ||
> > + (plane_y + plane_size < mode->vdisplay)))
> > + return false;
> > +
> > + if (plane_type == DRM_PLANE_TYPE_CURSOR) {
> > + /* For cursor planes only linear/alpha format is
> > supported. */
> > + if (tiling != LOCAL_DRM_FORMAT_MOD_NONE ||
> > + format != DRM_FORMAT_ARGB8888)
> > + return false;
> > +
> > + if (plane_size > data->max_curw || plane_size > data-
> > >max_curh)
> > + return false;
> > + } else {
> > + /*
> > + * For non-cursor planes formats with alpha may result
> > in
> > + * undeterministic CRCs, we use the same sized
> > + * non-alpha XRGB8888 format instead.
> > + */
> > + if (format == DRM_FORMAT_ARGB8888)
> > + return false;
> > +
> > + if (format == DRM_FORMAT_RGB565 &&
> > + intel_gen(data->devid) < 9 &&
> > + !IS_VALLEYVIEW(data->devid) && !IS_CHERRYVIEW(data-
> > >devid))
> > + return false;
> > + }
> > +
> > + /* RGB565 with rotation is not supported for now. */
> > + if (format == DRM_FORMAT_RGB565 && rotation != IGT_ROTATION_0)
> > + return false;
> > +
> > + return true;
> > +}
> > +
> > +/*
> > + * Create a square reference FB for the whole screen in the
> > clipping test,
> > + * with the given test plane position and size. See
> > + * create_fb_for_mode__clipping_plane() for the layout of the test
> > plane.
> > + */
> > +static void
> > +create_fb_for_mode__clipping_display(data_t *data, drmModeModeInfo
> > *mode,
> > + square_t *clip_squares,
> > + int clip_squares_cnt,
> > + struct igt_fb *fb /* out */)
> > +{
> > + int plane;
> > + struct igt_fb plane_fbs[4];
> > + unsigned int fb_id;
> > + cairo_t *cr;
> > + cairo_surface_t *srcs[4];
> > +
> > + fb_id = igt_create_fb(data->drm_fd,
> > + mode->hdisplay, mode->vdisplay,
> > + DRM_FORMAT_XRGB8888,
> > + LOCAL_DRM_FORMAT_MOD_NONE,
> > + fb);
> > + igt_assert(fb_id);
> > +
> > + cr = igt_get_cairo_ctx(data->drm_fd, fb);
> > + igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
> > + 0, 0, 0);
> > +
> > + for (plane = 0; plane < clip_squares_cnt; plane++) {
> > + create_fb_for_mode__clipping_plane(data,
> > IGT_ROTATION_0,
> > + LOCAL_DRM_FORMAT_MOD
> > _NONE,
> > + DRM_FORMAT_XRGB8888,
> > + clip_squares[plane].
> > size,
> > + &plane_fbs[plane]);
> > +
> > + srcs[plane] = igt_get_cairo_surface(data->drm_fd,
> > + &plane_fbs[plane]);
> > + cairo_set_source_surface(cr, srcs[plane],
> > + clip_squares[plane].x,
> > + clip_squares[plane].y);
> > + cairo_rectangle(cr,
> > + clip_squares[plane].x,
> > + clip_squares[plane].y,
> > + clip_squares[plane].size,
> > + clip_squares[plane].size);
> > + cairo_fill(cr);
>
> Could remove the FB, cairo surface already here, so we don't need the
> array and a second loop below?
>
if we remove the FB and cairo surface here, we will receive SIGABRT
like this,

kms_plane: cairo-surface.c:955: cairo_surface_destroy: Assertion
`CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)' failed.
Received signal SIGABRT.

And when we call cairo_destroy(), a cairo image surface of igt calls
blit.

> > + }
> > +
> > + igt_assert(cairo_status(cr) == 0);
> > + cairo_destroy(cr);
> > +
> > + for (plane = 0; plane < clip_squares_cnt; plane++) {
> > + cairo_surface_destroy(srcs[plane]);
> > + igt_remove_fb(data->drm_fd, &plane_fbs[plane]);
> > + }
> > +}
> > +
> > +static void
> > +test_plane_clipping_format(data_t *data,
> > + enum pipe pipe,
> > + igt_output_t *output,
> > + drmModeModeInfo *mode,
> > + square_t *clip_squares,
> > + int clip_squares_cnt,
> > + uint64_t tiling,
> > + igt_rotation_t rotation,
> > + uint32_t format,
> > + igt_crc_t *reference_crc)
> > +{
> > + int plane;
> > + igt_plane_t *plane_objs[4];
> > + struct igt_fb plane_fbs[4];
> > + igt_crc_t crc;
> > + int ret;
> > + bool bogus_planes = false;
> > +
> > + memset(plane_objs, 0, sizeof(plane_objs));
> > +
> > + igt_debug("rotation %s tiling %s format %s\n",
> > + igt_rotation_degrees_str(rotation),
> > + igt_tiling_str(tiling),
> > + igt_format_str(format));
> > +
> > + igt_output_set_pipe(output, pipe);
> > +
> > + for (plane = 0; plane < clip_squares_cnt ; plane++) {
> > + igt_plane_t *obj = igt_output_get_plane(output, plane);
> > + struct igt_fb *fb = &plane_fbs[plane];
> > + int x = clip_squares[plane].x;
> > + int y = clip_squares[plane].y;
> > + int size = clip_squares[plane].size;
> > + uint64_t _tiling = tiling;
> > + uint32_t _format = format;
> > +
> > + if (obj->type == DRM_PLANE_TYPE_CURSOR) {
> > + _tiling = LOCAL_DRM_FORMAT_MOD_NONE;
> > + _format = DRM_FORMAT_ARGB8888;
> > + }
> > +
> > + if (!supported_plane_conf(data, obj->type, _tiling,
> > _format,
> > + rotation, mode, x, y, size))
> > + goto out;
> > +
> > + create_fb_for_mode__clipping_plane(data,
> > rotation,_tiling,
> > + _format, size, fb);
> > +
> > + igt_plane_set_fb(obj, fb);
> > + igt_fb_set_position(fb, obj, 0, 0);
> > +
> > + igt_plane_set_size(obj, size, size);
> > + igt_plane_set_rotation(obj, rotation);
> > + igt_plane_set_position(obj, x, y);
> > +
> > + plane_objs[plane] = obj;
> > + }
> > +
> > + /*
> > + * Note that a universal commit doesn't support full modesets,
> > so we
> > + * have to make sure that the following only needs to commit
> > changes
> > + * that are compatible with a fastset. This should be
> > guaranteed,
> > + * since before calling this function we took the reference CRC
> > which
> > + * left the display enabled with the mode we require here and
> > + * afterwards we only change plane parameters (FB, position,
> > rotation
> > + * etc.).
> > + */
> > + ret = igt_display_try_commit2(&data->display,
> > COMMIT_UNIVERSAL);
> > +
> > + for (plane = 0; plane < clip_squares_cnt; plane++) {
> > + if(!bogus_plane_conf(data->devid, plane_objs[plane],
> > + mode->hdisplay, clip_squares[plane].x,
> > + clip_squares[plane].size)) {
>
> Please check formatting (kernel style).
>
Ok, I'll update it

> > + bogus_planes = true;
> > + break;
> > + }
> > + }
> > +
> > + if (bogus_planes) {
> > + igt_assert(ret == 0);
> > + igt_pipe_crc_collect_crc(data->pipe_crc, &crc);
> > + igt_assert_crc_equal(reference_crc, &crc);
> > + } else {
> > + igt_assert(ret == -ERANGE);
> > + }
> > +
> > +out:
> > + for (plane = 0; plane < clip_squares_cnt; plane++) {
> > + if (!plane_objs[plane])
> > + continue;
> > + igt_plane_set_fb(plane_objs[plane], NULL);
> > + igt_plane_set_rotation(plane_objs[plane],
> > IGT_ROTATION_0);
> > + igt_plane_set_position(plane_objs[plane], 0, 0);
> > +
> > + igt_remove_fb(data->drm_fd, &plane_fbs[plane]);
> > + }
> > +
> > + igt_output_set_pipe(output, PIPE_ANY);
> > +}
> > +
> > +static void
> > +test_plane_clipping_square(data_t *data, enum pipe pipe,
> > + igt_output_t *output, drmModeModeInfo *mode,
> > + square_t *clip_squares, int
> > clip_squares_cnt)
> > +{
> > + const struct {
> > + uint64_t tiling;
> > + igt_rotation_t rotation;
> > + } rotations[] = {
> > + { LOCAL_DRM_FORMAT_MOD_NONE, IGT_ROTATIO
> > N_0 },
> > +
> > + { LOCAL_I915_FORMAT_MOD_X_TILED, IGT_ROTATION_0 },
> > +
> > + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_0 },
> > + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_90 },
> > + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_180 },
> > + { LOCAL_I915_FORMAT_MOD_Y_TILED, IGT_ROTATION_270 },
> > +
> > + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_0 },
> > + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_90 },
> > + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_180 },
> > + { LOCAL_I915_FORMAT_MOD_Yf_TILED, IGT_ROTATION_270 },
> > + };
> > + const uint32_t formats[] = {
> > + DRM_FORMAT_RGB565,
> > + DRM_FORMAT_XRGB8888,
> > + DRM_FORMAT_ARGB8888,
> > + };
> > +
> > + igt_fb_t reference_fb;
> > + igt_crc_t reference_crc;
> > +
> > + for (int plane = 0; plane < clip_squares_cnt; plane++) {
> > + igt_info("Testing connector %s mode %dx%d using pipe
> > %s: %dx%d@%d,%d\n",
> > + igt_output_name(output),
> > + mode->hdisplay, mode->vdisplay,
> > + kmstest_pipe_name(pipe),
> > + clip_squares[plane].size,
> > clip_squares[plane].size,
> > + clip_squares[plane].x, clip_squares[plane].y);
> > + }
> > +
> > + test_init(data, pipe);
> > +
> > + create_fb_for_mode__clipping_display(data, mode,
> > + clip_squares,
> > + clip_squares_cnt,
> > + &reference_fb);
> > +
> > + test_grab_crc_for_fb2(data, output, pipe, &reference_fb,
> > + &reference_crc, COMMIT_UNIVERSAL);
>
> Hm not sure why legacy commit wouldn't work here. It will result in a
> modeset with only the primary plane on without rotation. Otoh
> universal
> commit doesn't (or at least used not to) support full modesets, so if
> we'd have to change the mode here then that wouldn't work. Did you
> try
> to run the test with multiple outputs?
>
yes, you are right. If I tried to test with multiple outputs,it didn't work as expected. I'll fix it with other solution which you guided(resetting a first commit state and calling commit with legacy style).

> > +
> > + igt_remove_fb(data->drm_fd, &reference_fb);
> > +
> > + for (int rotation = 0; rotation < ARRAY_SIZE(rotations);
> > rotation++)
> > + for (int format = 0; format < ARRAY_SIZE(formats);
> > format++)
> > + test_plane_clipping_format(data, pipe, output,
> > + mode,
> > + clip_squares,
> > + clip_squares_cnt,
> > + rotations[rotation].
> > tiling,
> > + rotations[rotation].
> > rotation,
> > + formats[format],
> > + &reference_crc);
> > +
> > + test_fini(data);
> > +}
> > +
> > +static void
> > +test_plane_clipping_squares(data_t *data, enum pipe pipe,
> > + igt_output_t *output, drmModeModeInfo
> > *mode,
> > + square_t *clip_squares, int
> > clip_squares_cnt)
>
> Imo s/clip_squares_cnt/plane_cnt/ would be clearer.
>
Ok I'll update it.

> > +{
> > + switch (clip_squares_cnt) {
> > + case 4:
> > + test_plane_clipping_square(data, pipe, output, mode,
> > + clip_squares, clip_squares_cnt);
> > + break;
> > + case 2:
> > + test_plane_clipping_square(data, pipe, output, mode,
> > + clip_squares, clip_squares_cnt);
> > + test_plane_clipping_square(data, pipe, output, mode,
> > + clip_squares + clip_squares_cnt,
> > + clip_squares_cnt);
> > + break;
> > + case 1:
> > + default:
> > + for (int i = 0; i < 4; i++) {
> > + test_plane_clipping_square(data, pipe, output, mode,
> > + clip_squares + i,
> > + clip_squares_cnt);
> > + }
> > + break;
> > + }
>
> Could be just
>
> for (i = 0; i < 4; i += clip_squares_cnt)
> test_plane_clipping_square(data, pipe, output, mode,
> clip_squares + i,
> clip_squares_cnt);
> ?
>

Ok I'll update it.

> > +}
> > +
> > +static void
> > +test_plane_clipping(data_t *data, enum pipe pipe)
> > +{
> > + igt_output_t *output;
> > + int connected_outs = 0;
> > +
> > + for_each_valid_output_on_pipe(&data->display, pipe, output) {
> > + drmModeModeInfo *mode;
> > + int sq_size;
> > + int max_planes = data->display.pipes[pipe].n_planes;
> > + int clip_squares_cnt;
> > +
> > + clip_squares_cnt = max_planes >= 4 ?
> > + 4 : max_planes >= 2 ? 2 : 1;
> > +
> > + igt_output_set_pipe(output, pipe);
> > + mode = igt_output_get_mode(output);
> > +
> > + /*
> > + * Test with a square plane bigger than either the
> > width or
> > + * height of the mode. This should pass on all
> > platforms.
> > + */
> > + sq_size = mode->hdisplay > mode->vdisplay ?
> > + mode->hdisplay : mode->vdisplay;
> > +
> > + clip_squares[0].x = -2;
> > + clip_squares[0].y = -2;
> > + clip_squares[0].size = sq_size + 4;
> > +
> > + test_plane_clipping_square(data, pipe, output, mode,
> > + clip_squares, 1);
> > +
> > + /*
> > + * Test positions in the 4 corners of the screen with a
> > + * CLIPPED_PLANE_MIN_VALID x CLIPPED_PLANE_MIN_VALID
> > square
> > + * visible from the plane. These should pass on all
> > platforms.
> > + */
> > + clip_squares[0].x = -CLIPPED_PLANE_SMALL_SIZE +
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[0].y = -CLIPPED_PLANE_SMALL_SIZE +
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[0].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[1].x = -CLIPPED_PLANE_SMALL_SIZE +
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[1].y = mode->vdisplay -
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[1].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[2].x = mode->hdisplay -
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[2].y = -CLIPPED_PLANE_SMALL_SIZE +
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[2].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[3].x = mode->hdisplay -
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[3].y = mode->vdisplay -
> > + CLIPPED_PLANE_MIN_VALID;
> > + clip_squares[3].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + test_plane_clipping_squares(data, pipe, output, mode,
> > + clip_squares,
> > clip_squares_cnt);
> > +
> > + /*
> > + * Test positions in the 4 corners of the screen with a
> > + * 2 x 2 square visible from the plane. These are valid
> > on all
> > + * platforms except on GLK/CNL where less than
> > + * CLIPPED_PLANE_MIN_VALID pixels visible on the
> > left/right
> > + * edges of the screen may cause FIFO underflow and
> > display
> > + * corruption.
> > + *
> > + * The cursor plane is an exception without this
> > problem.
> > + *
> > + * Use 2 x 2 size as other (odd) sizes may result in an
> > + * incorrect CRC for the cursor plane even though it
> > displays
> > + * correctly and causes no underflow.
> > + */
> > + clip_squares[0].x = -CLIPPED_PLANE_SMALL_SIZE + 2;
> > + clip_squares[0].y = -CLIPPED_PLANE_SMALL_SIZE + 2;
> > + clip_squares[0].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[1].x = -CLIPPED_PLANE_SMALL_SIZE + 2;
> > + clip_squares[1].y = mode->vdisplay - 2;
> > + clip_squares[1].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[2].x = mode->hdisplay - 2;
> > + clip_squares[2].y = -CLIPPED_PLANE_SMALL_SIZE + 2;
> > + clip_squares[2].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + clip_squares[3].x = mode->hdisplay - 2;
> > + clip_squares[3].y = mode->vdisplay - 2;
> > + clip_squares[3].size = CLIPPED_PLANE_SMALL_SIZE;
> > +
> > + test_plane_clipping_squares(data, pipe, output, mode,
> > + clip_squares,
> > clip_squares_cnt);
> > +
> > + connected_outs++;
> > + }
> > +
> > + igt_skip_on(connected_outs == 0);
> > +}
> > +
> > static void
> > run_tests_for_pipe_plane(data_t *data, enum pipe pipe)
> > {
> > @@ -590,6 +1103,9 @@ run_tests_for_pipe_plane(data_t *data, enum
> > pipe pipe)
> > kmstest_pipe_name(pipe))
> > test_plane_panning(data, pipe,
> > TEST_PANNING_BOTTOM_RIGHT |
> > TEST_SUSPEND_RESUME);
> > + igt_subtest_f("plane-clipping-pipe-%s-planes",
> > + kmstest_pipe_name(pipe))
> > + test_plane_clipping(data, pipe);
> > }
> >
> >
> > @@ -602,8 +1118,21 @@ igt_main
> > igt_skip_on_simulation();
> >
> > igt_fixture {
> > + int ret;
> > +
> > data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
> >
> > + data.devid = intel_get_drm_devid(data.drm_fd);
> > +
> > + data.max_curw = 64;
> > + data.max_curh = 64;
> > + ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_WIDTH,
> > + &data.max_curw);
> > + igt_assert(ret == 0 || errno == EINVAL);
> > + ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_HEIGHT,
> > + &data.max_curh);
> > + igt_assert(ret == 0 || errno == EINVAL);
> > +
> > kmstest_set_vt_graphics_mode();
> >
> > igt_require_pipe_crc(data.drm_fd);
> > --
> > 2.18.0
> >