[Intel-gfx] [PATCH i-g-t 1/2] kms_plane: Add panning test for primary plane

Daniel Vetter daniel at ffwll.ch
Mon Jul 7 23:10:10 CEST 2014


On Mon, Jul 07, 2014 at 06:04:45PM +0100, Damien Lespiau wrote:
> From: Yi Sun <yi.sun at intel.com>
> 
> Get CRCs of a full red and a full blue surface as reference.
> 
> Create a big framebuffer that is twice width and twice height as the
> current display mode.

The interesting stuff happens for framebuffers with offset > 4k (in
pixels iirc). Care to add such a subtest too on platforms that support
large enough strides (i.e. gen4+)?
-Daniel

> 
> Fill the top left quarter with red, bottom right quarter with blue
> Check the scanned out image with the CRTC at position (0, 0) of the
> framebuffer and it should be the same CRC as the full red fb
> Check the scanned out image with the CRTC at position (hdisplay,
> vdisplay) and it should be the same CRC as the full blue fb
> 
> v2: Fix a few things here and there (Damien)
> 
> Cc: Lei Liu <lei.a.liu at intel.com>
> Cc: Yi Sun <yi.sun at intel.com>
> Signed-off-by: Lei Liu <lei.a.liu at intel.com>
> Signed-off-by: Yi Sun <yi.sun at intel.com>
> Signed-off-by: Damien Lespiau <damien.lespiau at intel.com>
> ---
>  lib/igt_kms.c     |  21 +++++++--
>  lib/igt_kms.h     |   4 ++
>  tests/kms_plane.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 152 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> index 82bdec5..34311c8 100644
> --- a/lib/igt_kms.c
> +++ b/lib/igt_kms.c
> @@ -979,7 +979,8 @@ static int igt_primary_plane_commit_legacy(igt_plane_t *primary,
>  	/* Primary planes can't be windowed when using a legacy commit */
>  	igt_assert((primary->crtc_x == 0 && primary->crtc_y == 0));
>  
> -	if (!primary->fb_changed && !primary->position_changed)
> +	if (!primary->fb_changed && !primary->position_changed &&
> +	    !primary->panning_changed)
>  		return 0;
>  
>  	crtc_id = output->config.crtc->crtc_id;
> @@ -996,13 +997,13 @@ static int igt_primary_plane_commit_legacy(igt_plane_t *primary,
>  		    igt_output_name(output),
>  		    pipe_name(output->config.pipe),
>  		    fb_id,
> -		    0, 0,
> +		    primary->pan_x, primary->pan_y,
>  		    mode->hdisplay, mode->vdisplay);
>  
>  		ret = drmModeSetCrtc(display->drm_fd,
>  				     crtc_id,
>  				     fb_id,
> -				     0, 0, /* x, y */
> +				     primary->pan_x, primary->pan_y,
>  				     &output->id,
>  				     1,
>  				     mode);
> @@ -1254,6 +1255,20 @@ void igt_plane_set_position(igt_plane_t *plane, int x, int y)
>  	plane->position_changed = true;
>  }
>  
> +void igt_plane_set_panning(igt_plane_t *plane, int x, int y)
> +{
> +	igt_pipe_t *pipe = plane->pipe;
> +	igt_display_t *display = pipe->display;
> +
> +	LOG(display, "%c.%d: plane_set_panning(%d,%d)\n", pipe_name(pipe->pipe),
> +	    plane->index, x, y);
> +
> +	plane->pan_x = x;
> +	plane->pan_y = y;
> +
> +	plane->panning_changed = true;
> +}
> +
>  void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
>  {
>  	drmVBlank wait_vbl;
> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> index 95ba112..a079fc2 100644
> --- a/lib/igt_kms.h
> +++ b/lib/igt_kms.h
> @@ -113,6 +113,7 @@ typedef struct {
>  	unsigned int is_cursor        : 1;
>  	unsigned int fb_changed       : 1;
>  	unsigned int position_changed : 1;
> +	unsigned int panning_changed  : 1;
>  	/*
>  	 * drm_plane can be NULL for primary and cursor planes (when not
>  	 * using the atomic modeset API)
> @@ -121,6 +122,8 @@ typedef struct {
>  	struct igt_fb *fb;
>  	/* position within pipe_src_w x pipe_src_h */
>  	int crtc_x, crtc_y;
> +	/* panning offset within the fb */
> +	unsigned int pan_x, pan_y;
>  } igt_plane_t;
>  
>  struct igt_pipe {
> @@ -170,6 +173,7 @@ igt_plane_t *igt_output_get_plane(igt_output_t *output, enum igt_plane plane);
>  
>  void igt_plane_set_fb(igt_plane_t *plane, struct igt_fb *fb);
>  void igt_plane_set_position(igt_plane_t *plane, int x, int y);
> +void igt_plane_set_panning(igt_plane_t *plane, int x, int y);
>  
>  void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
>  
> diff --git a/tests/kms_plane.c b/tests/kms_plane.c
> index 45c4a77..7437641 100644
> --- a/tests/kms_plane.c
> +++ b/tests/kms_plane.c
> @@ -45,7 +45,9 @@ typedef struct {
>  	igt_pipe_crc_t *pipe_crc;
>  } data_t;
>  
> +static color_t red   = { 1.0f, 0.0f, 0.0f };
>  static color_t green = { 0.0f, 1.0f, 0.0f };
> +static color_t blue  = { 0.0f, 0.0f, 1.0f };
>  
>  /*
>   * Common code across all tests, acting on data_t
> @@ -211,6 +213,124 @@ test_plane_position(data_t *data, enum pipe pipe, enum igt_plane plane,
>  						flags);
>  }
>  
> +/*
> + * Plane panning test.
> + *   - We start by grabbing reference CRCs of a full red and a full blue fb
> + *     being scanned out on the primary plane
> + *   - Then we create a big fb, sized (2 * hdisplay, 2 * vdisplay) and:
> + *      - fill the top left quarter with red
> + *      - fill the bottom right quarter with blue
> + *   - The TEST_PANNING_TOP_LEFT test makes sure that with panning at (0, 0)
> + *     we do get the same CRC than the full red fb.
> + *   - The TEST_PANNING_BOTTOM_RIGHT test makes sure that with panning at
> + *     (vdisplay, hdisplay) we do get the same CRC than the full blue fb.
> + */
> +typedef struct {
> +	data_t *data;
> +	igt_crc_t red_crc, blue_crc;
> +} test_panning_t;
> +
> +static void
> +create_fb_for_mode__panning(data_t *data, drmModeModeInfo *mode,
> +			    struct igt_fb *fb /* out */)
> +{
> +	unsigned int fb_id;
> +	cairo_t *cr;
> +
> +	fb_id = igt_create_fb(data->drm_fd,
> +			      mode->hdisplay * 2, mode->vdisplay * 2,
> +			      DRM_FORMAT_XRGB8888,
> +			      false /* tiling */,
> +			      fb);
> +	igt_assert(fb_id);
> +
> +	cr = igt_get_cairo_ctx(data->drm_fd, fb);
> +
> +	igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
> +			1.0, 0.0, 0.0);
> +
> +	igt_paint_color(cr,
> +			mode->hdisplay, mode->vdisplay,
> +			mode->hdisplay, mode->vdisplay,
> +			0.0, 0.0, 1.0);
> +
> +	igt_assert(cairo_status(cr) == 0);
> +	cairo_destroy(cr);
> +}
> +
> +enum {
> +	TEST_PANNING_TOP_LEFT	  = 1 << 0,
> +	TEST_PANNING_BOTTOM_RIGHT = 1 << 1,
> +};
> +
> +static void
> +test_plane_panning_with_output(data_t *data,
> +			       enum pipe pipe,
> +			       enum igt_plane plane,
> +			       igt_output_t *output,
> +			       unsigned int flags)
> +{
> +	test_panning_t test = { .data = data };
> +	igt_plane_t *primary;
> +	struct igt_fb primary_fb;
> +	drmModeModeInfo *mode;
> +	igt_crc_t crc;
> +
> +	fprintf(stdout, "Testing connector %s using pipe %c plane %d\n",
> +		igt_output_name(output), pipe_name(pipe), plane);
> +
> +	test_init(data, pipe);
> +
> +	test_grab_crc(data, output, &red, &test.red_crc);
> +	test_grab_crc(data, output, &blue, &test.blue_crc);
> +
> +	igt_output_set_pipe(output, pipe);
> +
> +	mode = igt_output_get_mode(output);
> +	primary = igt_output_get_plane(output, 0);
> +
> +	create_fb_for_mode__panning(data, mode, &primary_fb);
> +	igt_plane_set_fb(primary, &primary_fb);
> +
> +	if (flags & TEST_PANNING_TOP_LEFT)
> +		igt_plane_set_panning(primary, 0, 0);
> +	else
> +		igt_plane_set_panning(primary, mode->hdisplay, mode->vdisplay);
> +
> +	igt_plane_set_position(primary, 0, 0);
> +
> +	igt_display_commit(&data->display);
> +
> +	igt_pipe_crc_collect_crc(data->pipe_crc, &crc);
> +
> +	if (flags & TEST_PANNING_TOP_LEFT)
> +		igt_assert(igt_crc_equal(&test.red_crc, &crc));
> +	else
> +		igt_assert(igt_crc_equal(&test.blue_crc, &crc));
> +
> +	igt_plane_set_fb(primary, NULL);
> +
> +	/* reset states to neutral values, assumed by other tests */
> +	igt_output_set_pipe(output, PIPE_ANY);
> +	igt_plane_set_panning(primary, 0, 0);
> +
> +	test_fini(data);
> +}
> +
> +static void
> +test_plane_panning(data_t *data, enum pipe pipe, enum igt_plane plane,
> +            unsigned int flags)
> +{
> +	igt_output_t *output;
> +
> +	igt_skip_on(pipe >= data->display.n_pipes);
> +	igt_skip_on(plane >= data->display.pipes[pipe].n_planes);
> +
> +	for_each_connected_output(&data->display, output)
> +		test_plane_panning_with_output(data, pipe, plane, output,
> +						flags);
> +}
> +
>  static void
>  run_tests_for_pipe_plane(data_t *data, enum pipe pipe, enum igt_plane plane)
>  {
> @@ -222,6 +342,16 @@ run_tests_for_pipe_plane(data_t *data, enum pipe pipe, enum igt_plane plane)
>  	igt_subtest_f("plane-position-hole-pipe-%c-plane-%d",
>  		      pipe_name(pipe), plane)
>  		test_plane_position(data, pipe, plane, 0);
> +
> +	igt_subtest_f("plane-panning-top-left-pipe-%c-plane-%d",
> +		      pipe_name(pipe), plane)
> +		test_plane_panning(data, pipe, plane, TEST_PANNING_TOP_LEFT);
> +
> +	igt_subtest_f("plane-panning-bottom-right-pipe-%c-plane-%d",
> +		      pipe_name(pipe), plane)
> +		test_plane_panning(data, pipe, plane,
> +				   TEST_PANNING_BOTTOM_RIGHT);
> +
>  }
>  
>  static void
> -- 
> 1.8.3.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch



More information about the Intel-gfx mailing list