diff mbox

demos/intel_sprite_on : Sprite Stress Testing

Message ID 1425372773-29138-1-git-send-email-megha.i.nelogal@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

meghanelogal March 3, 2015, 8:52 a.m. UTC
From: meghanelogal <megha.i.nelogal@intel.com>

Adding the Sprite Stress Test Feature

Signed-off-by: meghanelogal <megha.i.nelogal@intel.com>
---
 demos/intel_sprite_on.c |  653 +++++++++++++++++++++++++----------------------
 1 file changed, 347 insertions(+), 306 deletions(-)

Comments

Daniel Vetter March 4, 2015, 2:48 p.m. UTC | #1
On Tue, Mar 03, 2015 at 02:22:53PM +0530, meghanelogal wrote:
> From: meghanelogal <megha.i.nelogal@intel.com>
> 
> Adding the Sprite Stress Test Feature
> 
> Signed-off-by: meghanelogal <megha.i.nelogal@intel.com>

I really, really prefer if all automated and stress tests would be a part
of igt testsuite and that we'd abandon intel_sprite_on as a demo.

The igt library has a lot of support for combining automated modes with
manual testing and additional options, see e.g. the pm_rpm or
kms_psr_sink_crc testcases for what's possible.

If you're using intel_sprite_on for development testing or validation
please evaluate what's missing in proper igt testcoverage and work towards
converting over as soon as possible.

Thanks, Daniel

> ---
>  demos/intel_sprite_on.c |  653 +++++++++++++++++++++++++----------------------
>  1 file changed, 347 insertions(+), 306 deletions(-)
> 
> diff --git a/demos/intel_sprite_on.c b/demos/intel_sprite_on.c
> index 23fc56c..ad6b163 100644
> --- a/demos/intel_sprite_on.c
> +++ b/demos/intel_sprite_on.c
> @@ -49,6 +49,8 @@
>  
>  #include "ioctl_wrappers.h"
>  
> +
> +static int sprite_iteration_count = 1;
>  /*
>   * Mode setting with the kernel interfaces is a bit of a chore.
>   * First you have to find the connector in question and make sure the
> @@ -476,7 +478,7 @@ static int prepare_sprite_surfaces(int fd, int sprite_width, int sprite_height,
>  }
>  
>  static void ricochet(int tiled, int sprite_w, int sprite_h,
> -		     int out_w, int out_h, int dump_info)
> +		     int out_w, int out_h, int dump_info, int delay_time)
>  {
>  	int                                 ret;
>  	int                                 gfx_fd;
> @@ -499,7 +501,7 @@ static void ricochet(int tiled, int sprite_w, int sprite_h,
>  					    prim_fb_id;
>  	struct drm_intel_sprite_colorkey    set;
>  	struct connector                    curr_connector;
> -	drmModeRes                          *gfx_resources;
> +	drmModeRes                          *gfx_resources = NULL;
>  	struct termios                      orig_term,
>  					    curr_term;
>  	int                                 c_index;
> @@ -518,259 +520,264 @@ static void ricochet(int tiled, int sprite_w, int sprite_h,
>  	char                                key;
>  	int				    sprite_plane_count = 0;
>  	int 				    i;
> +	int sprite_loop = 0;
> +	int disable_timer = 0;
> +	drmModePlaneRes *plane_resources;
> +	drmModePlane *ovr;
>  	// Open up I915 graphics device
>  	gfx_fd = drmOpen("i915", NULL);
>  	if (gfx_fd < 0) {
>  		printf("Failed to load i915 driver: %s\n", strerror(errno));
>  		return;
>  	}
> -
> -	// Obtain pointer to struct containing graphics resources
> -	gfx_resources = drmModeGetResources(gfx_fd);
> -	if (!gfx_resources) {
> -		printf("drmModeGetResources failed: %s\n", strerror(errno));
> -		return;
> -	}
> -
> -	if (dump_info != 0) {
> -		dump_connectors(gfx_fd, gfx_resources);
> -		dump_crtcs(gfx_fd, gfx_resources);
> -		dump_planes(gfx_fd, gfx_resources);
> -	}
> -
> -	// Save previous terminal settings
> -	if (tcgetattr( 0, &orig_term) != 0) {
> -		printf("tcgetattr failure: %s\n",
> -				strerror(errno));
> -		return;
> -	}
> -
> -	// Set up input to return characters immediately
> -	curr_term = orig_term;
> -	curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
> -	curr_term.c_cc[VMIN] = 0;       // No minimum number of characters
> -	curr_term.c_cc[VTIME] = 0 ;     // Return immediately, even if
> -	// nothing has been entered.
> -	if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
> -		printf("tcgetattr failure: %s\n", strerror(errno));
> -		return;
> -	}
> -
> -	// Cycle through all connectors and display the flying sprite
> -	// where there are displays attached and the hardware will support it.
> -	for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++)  {
> -		curr_connector.id = gfx_resources->connectors[c_index];
> -
> -		// Find the native (preferred) display mode
> -		connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
> -		if (curr_connector.mode_valid == 0) {
> -			printf("No valid preferred mode detected\n");
> -			goto out;
> -		}
> -
> -		// Determine if sprite hardware is available on pipe
> -		// associated with this connector.
> -		sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector,
> -							  &sprite_plane_id);
> -		if (!sprite_plane_count) {
> -			printf("Failed to find sprite plane on crtc\n");
> -			goto out;
> +	/* Stress Cycle iteration */
> +	for (sprite_loop = 0; sprite_loop < sprite_iteration_count; sprite_loop++) {
> +		// Obtain pointer to struct containing graphics resources
> +		disable_timer = 0;
> +		gfx_resources = drmModeGetResources(gfx_fd);
> +		if (!gfx_resources) {
> +			printf("drmModeGetResources failed: %s\n", strerror(errno));
> +			return;
>  		}
>  
> -		// Width and height of preferred mode
> -		prim_width = curr_connector.mode.hdisplay;
> -		prim_height = curr_connector.mode.vdisplay;
> -
> -		// Allocate and fill memory for primary surface
> -		ret = prepare_primary_surface(
> -				gfx_fd,
> -				prim_width,
> -				prim_height,
> -				&prim_handle,
> -				&prim_stride,
> -				&prim_size,
> -				tiled);
> -		if (ret != 0) {
> -			printf("Failed to add primary fb (%dx%d): %s\n",
> -				prim_width, prim_height, strerror(errno));
> -			goto out;
> +		if (dump_info != 0) {
> +			dump_connectors(gfx_fd, gfx_resources);
> +			dump_crtcs(gfx_fd, gfx_resources);
> +			dump_planes(gfx_fd, gfx_resources);
>  		}
>  
> -		// Add the primary surface framebuffer
> -		ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32,
> -				   prim_stride, prim_handle, &prim_fb_id);
> -		gem_close(gfx_fd, prim_handle);
> -
> -		if (ret != 0) {
> -			printf("Failed to add primary fb (%dx%d): %s\n",
> -					prim_width, prim_height, strerror(errno));
> -			goto out;
> +		// Save previous terminal settings
> +		if (tcgetattr( 0, &orig_term) != 0) {
> +			printf("tcgetattr failure: %s\n",
> +				strerror(errno));
> +			return;
>  		}
>  
> -		// Allocate and fill sprite surfaces
> -		ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces,
> -					      &sprite_handles[0],
> -					      &sprite_stride, &sprite_size,
> -					      tiled);
> -		if (ret != 0) {
> -			printf("Preparation of sprite surfaces failed %dx%d\n",
> -				sprite_w, sprite_h);
> -			goto out;
> +		// Set up input to return characters immediately
> +		curr_term = orig_term;
> +		curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
> +		curr_term.c_cc[VMIN] = 0;       // No minimum number of characters
> +		curr_term.c_cc[VTIME] = 0 ;     // Return immediately, even if
> +		// nothing has been entered.
> +		if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
> +			printf("tcgetattr failure: %s\n", strerror(errno));
> +			return;
>  		}
>  
> -		// Add the sprite framebuffers
> -		for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
> -			handles[0] = sprite_handles[sprite_index];
> -			handles[1] = handles[0];
> -			handles[2] = handles[0];
> -			handles[3] = handles[0];
> -			pitches[0] = sprite_stride;
> -			pitches[1] = sprite_stride;
> -			pitches[2] = sprite_stride;
> -			pitches[3] = sprite_stride;
> -			memset(offsets, 0, sizeof(offsets));
> -
> -			ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h,
> -					    DRM_FORMAT_XRGB8888,
> -					    handles, pitches, offsets,
> -					    &sprite_fb_id[sprite_index], plane_flags);
> -			gem_close(gfx_fd, sprite_handles[sprite_index]);
> -
> -			if (ret) {
> -				printf("Failed to add sprite fb (%dx%d): %s\n",
> -				       sprite_w, sprite_h, strerror(errno));
> -
> -				sprite_index--;
> -				while (sprite_index >= 0) {
> -					drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
> -					sprite_index--;
> -				}
> +		// Cycle through all connectors and display the flying sprite
> +		// where there are displays attached and the hardware will support it.
> +		for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++)  {
> +			curr_connector.id = gfx_resources->connectors[c_index];
> +			// Find the native (preferred) display mode
> +			connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
> +			if (curr_connector.mode_valid == 0) {
> +				printf("No valid preferred mode detected\n");
>  				goto out;
>  			}
> -		}
>  
> -		if (dump_info != 0) {
> -			printf("Displayed Mode Connector struct:\n"
> -				"    .id = %d\n"
> -				"    .mode_valid = %d\n"
> -				"    .crtc = %d\n"
> -				"    .pipe = %d\n"
> -				"    drmModeModeInfo ...\n"
> -				"        .name = %s\n"
> -				"        .type = %d\n"
> -				"        .flags = %08x\n"
> -				"    drmModeEncoder ...\n"
> -				"        .encoder_id = %d\n"
> -				"        .encoder_type = %d (%s)\n"
> -				"        .crtc_id = %d\n"
> -				"        .possible_crtcs = %d\n"
> -				"        .possible_clones = %d\n"
> -				"    drmModeConnector ...\n"
> -				"        .connector_id = %d\n"
> -				"        .encoder_id = %d\n"
> -				"        .connector_type = %d (%s)\n"
> -				"        .connector_type_id = %d\n\n",
> -				curr_connector.id,
> -				curr_connector.mode_valid,
> -				curr_connector.crtc,
> -				curr_connector.pipe,
> -				curr_connector.mode.name,
> -				curr_connector.mode.type,
> -				curr_connector.mode.flags,
> -				curr_connector.encoder->encoder_id,
> -				curr_connector.encoder->encoder_type,
> -				kmstest_encoder_type_str(curr_connector.encoder->encoder_type),
> -				curr_connector.encoder->crtc_id,
> -				curr_connector.encoder->possible_crtcs,
> -				curr_connector.encoder->possible_clones,
> -				curr_connector.connector->connector_id,
> -				curr_connector.connector->encoder_id,
> -				curr_connector.connector->connector_type,
> -				kmstest_connector_type_str(curr_connector.connector->connector_type),
> -				curr_connector.connector->connector_type_id);
> -
> -			printf("Sprite surface dimensions = %dx%d\n"
> -				"Sprite output dimensions = %dx%d\n"
> -				"Press any key to continue >\n",
> -				sprite_w, sprite_h, out_w, out_h);
> -
> -			// Wait for a key-press
> -			while( read(0, &key, 1) == 0);
> -			// Purge unread characters
> -			tcflush(0, TCIFLUSH);
> -		}
> +			// Determine if sprite hardware is available on pipe
> +			// associated with this connector.
> +			sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector,
> +								  &sprite_plane_id);
> +			if (!sprite_plane_count) {
> +				printf("Failed to find sprite plane on crtc\n");
> +				goto out;
> +			}
>  
> -		// Set up the primary display mode
> -		ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id,
> -				     0, 0, &curr_connector.id, 1, &curr_connector.mode);
> -		if (ret != 0) {
> -			printf("Failed to set mode (%dx%d@%dHz): %s\n",
> -				prim_width, prim_height, curr_connector.mode.vrefresh,
> -				strerror(errno));
> -			continue;
> -		}
> +			// Width and height of preferred mode
> +			prim_width = curr_connector.mode.hdisplay;
> +			prim_height = curr_connector.mode.vdisplay;
> +
> +			// Allocate and fill memory for primary surface
> +			ret = prepare_primary_surface(
> +					gfx_fd,
> +					prim_width,
> +					prim_height,
> +					&prim_handle,
> +					&prim_stride,
> +					&prim_size,
> +					tiled);
> +			if (ret != 0) {
> +				printf("Failed to add primary fb (%dx%d): %s\n",
> +					prim_width, prim_height, strerror(errno));
> +				goto out;
> +			}
>  
> -		// Set the sprite colorkey state
> -		for(i = 0; i < sprite_plane_count; i++) {
> -			set.plane_id = sprite_plane_id[i];
> -			set.min_value = 0;
> -			set.max_value = 0;
> -			set.flags = I915_SET_COLORKEY_NONE;
> -			ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
> -					      sizeof(set));
> -			assert(ret == 0);
> -		}
> +			// Add the primary surface framebuffer
> +			ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32,
> +					   prim_stride, prim_handle, &prim_fb_id);
> +			gem_close(gfx_fd, prim_handle);
>  
> -		// Set up sprite output dimensions, initial position, etc.
> -		if (out_w > prim_width / 2)
> -			out_w = prim_width / 2;
> -		if (out_h > prim_height / 2)
> -			out_h = prim_height / 2;
> +			if (ret != 0) {
> +				printf("Failed to add primary fb (%dx%d): %s\n",
> +						prim_width, prim_height, strerror(errno));
> +				goto out;
> +			}
>  
> -		delta_x = (int *) malloc(sprite_plane_count * sizeof(int));
> -		delta_y = (int *) malloc(sprite_plane_count * sizeof(int));
> -		sprite_x = (int *) malloc(sprite_plane_count * sizeof(int));
> -		sprite_y = (int *) malloc(sprite_plane_count * sizeof(int));
> +			// Allocate and fill sprite surfaces
> +			ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces,
> +						      &sprite_handles[0],
> +						      &sprite_stride, &sprite_size,
> +						      tiled);
> +			if (ret != 0) {
> +				printf("Preparation of sprite surfaces failed %dx%d\n",
> +					sprite_w, sprite_h);
> +				goto out;
> +			}
>  
> -		/* Initializing the coordinates (x,y) of the available sprites on the
> -		 * connector, equally spaced along the diagonal of the rectangle
> -		 * {(0,0),(prim_width/2, prim_height/2)}.
> -		 */
> -		for(i = 0; i < sprite_plane_count; i++) {
> -			delta_x[i] = 3;
> -			delta_y[i] = 4;
> -			sprite_x[i] = i * (prim_width / (2 * sprite_plane_count));
> -			sprite_y[i] = i * (prim_height / (2 * sprite_plane_count));
> -		}
> +			// Add the sprite framebuffers
> +			for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
> +				handles[0] = sprite_handles[sprite_index];
> +				handles[1] = handles[0];
> +				handles[2] = handles[0];
> +				handles[3] = handles[0];
> +				pitches[0] = sprite_stride;
> +				pitches[1] = sprite_stride;
> +				pitches[2] = sprite_stride;
> +				pitches[3] = sprite_stride;
> +				memset(offsets, 0, sizeof(offsets));
> +
> +				ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h,
> +						    DRM_FORMAT_XRGB8888,
> +						    handles, pitches, offsets,
> +						    &sprite_fb_id[sprite_index], plane_flags);
> +				gem_close(gfx_fd, sprite_handles[sprite_index]);
> +
> +				if (ret) {
> +					printf("Failed to add sprite fb (%dx%d): %s\n",
> +					       sprite_w, sprite_h, strerror(errno));
>  
> -		currTime = 0;
> -		prevFlipTime = 0;       // Will force immediate sprite flip
> -		prevMoveTime = 0;       // Will force immediate sprite move
> -		deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
> -		deltaMoveTime = 100000; // Move sprite every 100 ms
> -		sprite_index = num_surfaces - 1;
> -		keep_moving = 1;
> +					sprite_index--;
> +					while (sprite_index >= 0) {
> +						drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
> +						sprite_index--;
> +					}
> +					goto out;
> +				}
> +			}
>  
> -		// Bounce sprite off the walls
> -		while (keep_moving) {
> -			// Obtain system time in usec.
> -			if (gettimeofday( &stTimeVal, NULL ) != 0)
> -				printf("gettimeofday error: %s\n", strerror(errno));
> -			else
> -				currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;
> +			if (dump_info != 0) {
> +				printf("Displayed Mode Connector struct:\n"
> +					"    .id = %d\n"
> +					"    .mode_valid = %d\n"
> +					"    .crtc = %d\n"
> +					"    .pipe = %d\n"
> +					"    drmModeModeInfo ...\n"
> +					"        .name = %s\n"
> +					"        .type = %d\n"
> +					"        .flags = %08x\n"
> +					"    drmModeEncoder ...\n"
> +					"        .encoder_id = %d\n"
> +					"        .encoder_type = %d (%s)\n"
> +					"        .crtc_id = %d\n"
> +					"        .possible_crtcs = %d\n"
> +					"        .possible_clones = %d\n"
> +					"    drmModeConnector ...\n"
> +					"        .connector_id = %d\n"
> +					"        .encoder_id = %d\n"
> +					"        .connector_type = %d (%s)\n"
> +					"        .connector_type_id = %d\n\n",
> +					curr_connector.id,
> +					curr_connector.mode_valid,
> +					curr_connector.crtc,
> +					curr_connector.pipe,
> +					curr_connector.mode.name,
> +					curr_connector.mode.type,
> +					curr_connector.mode.flags,
> +					curr_connector.encoder->encoder_id,
> +					curr_connector.encoder->encoder_type,
> +					kmstest_encoder_type_str(curr_connector.encoder->encoder_type),
> +					curr_connector.encoder->crtc_id,
> +					curr_connector.encoder->possible_crtcs,
> +					curr_connector.encoder->possible_clones,
> +					curr_connector.connector->connector_id,
> +					curr_connector.connector->encoder_id,
> +					curr_connector.connector->connector_type,
> +					kmstest_connector_type_str(curr_connector.connector->connector_type),
> +					curr_connector.connector->connector_type_id);
> +
> +				printf("Sprite surface dimensions = %dx%d\n"
> +					"Sprite output dimensions = %dx%d\n"
> +					"Press any key to continue >\n",
> +					sprite_w, sprite_h, out_w, out_h);
> +
> +				// Wait for a key-press
> +				while( read(0, &key, 1) == 0);
> +				// Purge unread characters
> +				tcflush(0, TCIFLUSH);
> +			}
>  
> -			// Check if it's time to flip the sprite surface
> -			if (currTime - prevFlipTime > deltaFlipTime) {
> -				sprite_index = (sprite_index + 1) % num_surfaces;
> +			// Set up the primary display mode
> +			ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id,
> +					     0, 0, &curr_connector.id, 1, &curr_connector.mode);
> +			if (ret != 0) {
> +				printf("Failed to set mode (%dx%d@%dHz): %s\n",
> +					prim_width, prim_height, curr_connector.mode.vrefresh,
> +					strerror(errno));
> +				continue;
> +			}
>  
> -				prevFlipTime = currTime;
> +			// Set the sprite colorkey state
> +			for(i = 0; i < sprite_plane_count; i++) {
> +				set.plane_id = sprite_plane_id[i];
> +				set.min_value = 0;
> +				set.max_value = 0;
> +				set.flags = I915_SET_COLORKEY_NONE;
> +				ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
> +					      sizeof(set));
> +				assert(ret == 0);
>  			}
>  
> -			// Move the sprite on the screen and flip
> -			// the surface if the index has changed
> -			// NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16
> +			// Set up sprite output dimensions, initial position, etc.
> +			if (out_w > prim_width / 2)
> +				out_w = prim_width / 2;
> +			if (out_h > prim_height / 2)
> +				out_h = prim_height / 2;
> +
> +			delta_x = (int *) malloc(sprite_plane_count * sizeof(int));
> +			delta_y = (int *) malloc(sprite_plane_count * sizeof(int));
> +			sprite_x = (int *) malloc(sprite_plane_count * sizeof(int));
> +			sprite_y = (int *) malloc(sprite_plane_count * sizeof(int));
> +
> +			/* Initializing the coordinates (x,y) of the available sprites on the
> +			 * connector, equally spaced along the diagonal of the rectangle
> +			 * {(0,0),(prim_width/2, prim_height/2)}.
> +		 	*/
>  			for(i = 0; i < sprite_plane_count; i++) {
> -				if (drmModeSetPlane(gfx_fd, sprite_plane_id[i],
> +				delta_x[i] = 3;
> +				delta_y[i] = 4;
> +				sprite_x[i] = i * (prim_width / (2 * sprite_plane_count));
> +				sprite_y[i] = i * (prim_height / (2 * sprite_plane_count));
> +			}
> +
> +			currTime = 0;
> +			prevFlipTime = 0;       // Will force immediate sprite flip
> +			prevMoveTime = 0;       // Will force immediate sprite move
> +			deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
> +			deltaMoveTime = 100000; // Move sprite every 100 ms
> +			sprite_index = num_surfaces - 1;
> +			keep_moving = 1;
> +
> +			// Bounce sprite off the walls
> +			while (keep_moving) {
> +				// Obtain system time in usec.
> +				if (gettimeofday( &stTimeVal, NULL ) != 0)
> +					printf("gettimeofday error: %s\n", strerror(errno));
> +				else
> +					currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;
> +
> +				// Check if it's time to flip the sprite surface
> +				if (currTime - prevFlipTime > deltaFlipTime) {
> +					sprite_index = (sprite_index + 1) % num_surfaces;
> +
> +					prevFlipTime = currTime;
> +				}
> +
> +				// Move the sprite on the screen and flip
> +				// the surface if the index has changed
> +				// NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16
> +				for(i = 0; i < sprite_plane_count; i++) {
> +					if (drmModeSetPlane(gfx_fd, sprite_plane_id[i],
>  						    curr_connector.crtc,
>  						    sprite_fb_id[sprite_index],
>  						    plane_flags,
> @@ -778,95 +785,118 @@ static void ricochet(int tiled, int sprite_w, int sprite_h,
>  						    out_w, out_h,
>  						    0, 0,
>  						    sprite_w << 16, sprite_h << 16))
> -					printf("Failed to enable sprite plane: %s\n",
> -						strerror(errno));
> -			}
> -
> -			// Check if it's time to move the sprite surface
> -			if (currTime - prevMoveTime > deltaMoveTime)  {
> +						printf("Failed to enable sprite plane: %s\n",
> +							strerror(errno));
> +				}
>  
> -				// Compute the next position for sprite
> -				for(i = 0; i < sprite_plane_count; i++) {
> -					sprite_x[i] += delta_x[i];
> -					sprite_y[i] += delta_y[i];
> -					if (sprite_x[i] < 0) {
> -						sprite_x[i] = 0;
> -						delta_x[i] = -delta_x[i];
> -					}
> -					else if (sprite_x[i] > prim_width - out_w) {
> -						sprite_x[i] = prim_width - out_w;
> -						delta_x[i] = -delta_x[i];
> +				// Check if it's time to move the sprite surface
> +				if (currTime - prevMoveTime > deltaMoveTime)  {
> +
> +					// Compute the next position for sprite
> +					for(i = 0; i < sprite_plane_count; i++) {
> +						sprite_x[i] += delta_x[i];
> +						sprite_y[i] += delta_y[i];
> +						if (sprite_x[i] < 0) {
> +							sprite_x[i] = 0;
> +							delta_x[i] = -delta_x[i];
> +						}
> +						else if (sprite_x[i] > prim_width - out_w) {
> +							sprite_x[i] = prim_width - out_w;
> +							delta_x[i] = -delta_x[i];
> +						}
> +
> +						if (sprite_y[i] < 0) {
> +							sprite_y[i] = 0;
> +							delta_y[i] = -delta_y[i];
> +						}
> +						else if (sprite_y[i] > prim_height - out_h) {
> +							sprite_y[i] = prim_height - out_h;
> +							delta_y[i] = -delta_y[i];
> +						}
>  					}
> -
> -					if (sprite_y[i] < 0) {
> -						sprite_y[i] = 0;
> -						delta_y[i] = -delta_y[i];
> +					prevMoveTime = currTime;
> +				}
> +				if (delay_time != 0) {
> +					if (disable_timer == delay_time) {
> +						plane_resources = drmModeGetPlaneResources(gfx_fd);
> +						if (!plane_resources) {
> +							printf("drmModeGetPlaneResources failed:%s\n", strerror(errno));
> +							return;
> +						}
> +					for (i = 0; i < plane_resources->count_planes; i++) {
> +						ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
> +						if (!ovr) {
> +							printf("drmModeGetPlane failed:%s\n", strerror(errno));
> +							continue;
> +						}
> +						drmModeFreePlane(ovr);
>  					}
> -					else if (sprite_y[i] > prim_height - out_h) {
> -						sprite_y[i] = prim_height - out_h;
> -						delta_y[i] = -delta_y[i];
> +					while (sprite_index >= 0) {
> +						drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
> +						sprite_index--;
>  					}
> +					keep_moving = 0;
> +					} else
> +						disable_timer++;
>  				}
> -				prevMoveTime = currTime;
> -			}
>  
> -			// Fetch a key from input (non-blocking)
> -			if (read(0, &key, 1) == 1) {
> -				switch (key) {
> -				case 'q':       // Kill the program
> -				case 'Q':
> -					goto out;
> -					break;
> -				case 's':       // Slow down sprite movement;
> -					deltaMoveTime = (deltaMoveTime * 100) / 90;
> -					if (deltaMoveTime > 800000) {
> -						deltaMoveTime = 800000;
> -					}
> -					break;
> -				case 'S':       // Speed up sprite movement;
> -					deltaMoveTime = (deltaMoveTime * 100) / 110;
> -					if (deltaMoveTime < 2000) {
> -						deltaMoveTime = 2000;
> +				// Fetch a key from input (non-blocking)
> +				if (read(0, &key, 1) == 1) {
> +					switch (key) {
> +					case 'q':       // Kill the program
> +					case 'Q':
> +						goto out;
> +						break;
> +					case 's':       // Slow down sprite movement;
> +						deltaMoveTime = (deltaMoveTime * 100) / 90;
> +						if (deltaMoveTime > 800000) {
> +							deltaMoveTime = 800000;
> +						}
> +						break;
> +					case 'S':       // Speed up sprite movement;
> +						deltaMoveTime = (deltaMoveTime * 100) / 110;
> +						if (deltaMoveTime < 2000) {
> +							deltaMoveTime = 2000;
> +						}
> +						break;
> +					case 'f':       // Slow down sprite flipping;
> +						deltaFlipTime = (deltaFlipTime * 100) / 90;
> +						if (deltaFlipTime > 1000000)
> +							deltaFlipTime = 1000000;
> +						break;
> +					case 'F':       // Speed up sprite flipping;
> +						deltaFlipTime = (deltaFlipTime * 100) / 110;
> +						if (deltaFlipTime < 20000)
> +							deltaFlipTime = 20000;
> +						break;
> +					case 'n':       // Next connector
> +					case 'N':
> +						keep_moving = 0;
> +						break;
> +					default:
> +						break;
>  					}
> -					break;
> -				case 'f':       // Slow down sprite flipping;
> -					deltaFlipTime = (deltaFlipTime * 100) / 90;
> -					if (deltaFlipTime > 1000000)
> -						deltaFlipTime = 1000000;
> -					break;
> -				case 'F':       // Speed up sprite flipping;
> -					deltaFlipTime = (deltaFlipTime * 100) / 110;
> -					if (deltaFlipTime < 20000)
> -						deltaFlipTime = 20000;
> -					break;
> -				case 'n':       // Next connector
> -				case 'N':
> -					keep_moving = 0;
> -					break;
> -				default:
> -					break;
> +	
> +					// Purge unread characters
> +					tcflush(0, TCIFLUSH);
>  				}
>  
> -				// Purge unread characters
> -				tcflush(0, TCIFLUSH);
> +				// Wait for min of flip or move deltas
> +				SleepTime = (deltaFlipTime < deltaMoveTime) ?
> +					deltaFlipTime : deltaMoveTime;
> +				usleep(SleepTime);
>  			}
> -
> -			// Wait for min of flip or move deltas
> -			SleepTime = (deltaFlipTime < deltaMoveTime) ?
> -				deltaFlipTime : deltaMoveTime;
> -			usleep(SleepTime);
> +			free(sprite_plane_id);
> +			free(sprite_x);
> +			free(sprite_y);
> +			free(delta_x);
> +			free(delta_y);
> +			sprite_plane_id = NULL;
> +			sprite_plane_count = 0;
> +			sprite_x = sprite_y = delta_x = delta_y = NULL;
>  		}
> -
> -		free(sprite_plane_id);
> -		free(sprite_x);
> -		free(sprite_y);
> -		free(delta_x);
> -		free(delta_y);
> -		sprite_plane_id = NULL;
> -		sprite_plane_count = 0;
> -		sprite_x = sprite_y = delta_x = delta_y = NULL;
> +		keep_moving = 1;
>  	}
> -
>  out:
>  	// Purge unread characters
>  	tcflush(0, TCIFLUSH);
> @@ -886,6 +916,8 @@ static void usage(char *name)
>  		"\t-h\t[optional] output help message\n"
>  		"\t-t\t[optional] enable tiling\n"
>  		"\t-o\t[optional] <output rect width>x<output rect height>\n\n"
> +		"\t-a\t[time] for passing sleep time in seconds before disabling planes in each cycle of stress test\n"
> +		"\t-n\t[n] Stress cycle count\n\n"
>  		"Keyboard control for sprite movement and flip rate ...\n"
>  		"\t'q' or 'Q' - Quit the program\n"
>  		"\t'n' or 'N' - Switch to next display\n"
> @@ -905,8 +937,9 @@ int main(int argc, char **argv)
>  	int                 plane_width = 0,
>  			    plane_height = 0,
>  			    out_width = 0,
> -			    out_height = 0;
> -	static char         optstr[] = "ds:o:th";
> +			    out_height = 0,
> +			    delay_time = 0;
> +	static char         optstr[] = "ds:o:th:a:n:";
>  
>  	opterr = 0;
>  	while ((c = getopt(argc, argv, optstr)) != -1) {
> @@ -926,6 +959,14 @@ int main(int argc, char **argv)
>  			if (sscanf(optarg, "%dx%d", &out_width, &out_height) != 2)
>  				usage(argv[0]);
>  			break;
> +		case 'a':		/* Delay time for disabling sprites */
> +			if (sscanf(optarg, "%d", &delay_time) != 1)
> +				usage(argv[0]);
> +			break;
> +		case 'n':		/* Stress cycle count  */
> +			if (sscanf(optarg, "%d", &sprite_iteration_count) != 1)
> +				usage(argv[0]);
> +			break;
>  		default:
>  			printf("unknown option %c\n", c);
>  			/* fall through */
> @@ -942,7 +983,7 @@ int main(int argc, char **argv)
>  		if (out_height < (plane_height / 2))
>  			out_height = plane_height;
>  
> -		ricochet(enable_tiling, plane_width, plane_height, out_width, out_height, dump_info);
> +		ricochet(enable_tiling, plane_width, plane_height, out_width, out_height, dump_info, delay_time);
>  	} else {
>  		printf("Sprite dimensions are required:\n");
>  		usage(argv[0]);
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff mbox

Patch

diff --git a/demos/intel_sprite_on.c b/demos/intel_sprite_on.c
index 23fc56c..ad6b163 100644
--- a/demos/intel_sprite_on.c
+++ b/demos/intel_sprite_on.c
@@ -49,6 +49,8 @@ 
 
 #include "ioctl_wrappers.h"
 
+
+static int sprite_iteration_count = 1;
 /*
  * Mode setting with the kernel interfaces is a bit of a chore.
  * First you have to find the connector in question and make sure the
@@ -476,7 +478,7 @@  static int prepare_sprite_surfaces(int fd, int sprite_width, int sprite_height,
 }
 
 static void ricochet(int tiled, int sprite_w, int sprite_h,
-		     int out_w, int out_h, int dump_info)
+		     int out_w, int out_h, int dump_info, int delay_time)
 {
 	int                                 ret;
 	int                                 gfx_fd;
@@ -499,7 +501,7 @@  static void ricochet(int tiled, int sprite_w, int sprite_h,
 					    prim_fb_id;
 	struct drm_intel_sprite_colorkey    set;
 	struct connector                    curr_connector;
-	drmModeRes                          *gfx_resources;
+	drmModeRes                          *gfx_resources = NULL;
 	struct termios                      orig_term,
 					    curr_term;
 	int                                 c_index;
@@ -518,259 +520,264 @@  static void ricochet(int tiled, int sprite_w, int sprite_h,
 	char                                key;
 	int				    sprite_plane_count = 0;
 	int 				    i;
+	int sprite_loop = 0;
+	int disable_timer = 0;
+	drmModePlaneRes *plane_resources;
+	drmModePlane *ovr;
 	// Open up I915 graphics device
 	gfx_fd = drmOpen("i915", NULL);
 	if (gfx_fd < 0) {
 		printf("Failed to load i915 driver: %s\n", strerror(errno));
 		return;
 	}
-
-	// Obtain pointer to struct containing graphics resources
-	gfx_resources = drmModeGetResources(gfx_fd);
-	if (!gfx_resources) {
-		printf("drmModeGetResources failed: %s\n", strerror(errno));
-		return;
-	}
-
-	if (dump_info != 0) {
-		dump_connectors(gfx_fd, gfx_resources);
-		dump_crtcs(gfx_fd, gfx_resources);
-		dump_planes(gfx_fd, gfx_resources);
-	}
-
-	// Save previous terminal settings
-	if (tcgetattr( 0, &orig_term) != 0) {
-		printf("tcgetattr failure: %s\n",
-				strerror(errno));
-		return;
-	}
-
-	// Set up input to return characters immediately
-	curr_term = orig_term;
-	curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
-	curr_term.c_cc[VMIN] = 0;       // No minimum number of characters
-	curr_term.c_cc[VTIME] = 0 ;     // Return immediately, even if
-	// nothing has been entered.
-	if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
-		printf("tcgetattr failure: %s\n", strerror(errno));
-		return;
-	}
-
-	// Cycle through all connectors and display the flying sprite
-	// where there are displays attached and the hardware will support it.
-	for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++)  {
-		curr_connector.id = gfx_resources->connectors[c_index];
-
-		// Find the native (preferred) display mode
-		connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
-		if (curr_connector.mode_valid == 0) {
-			printf("No valid preferred mode detected\n");
-			goto out;
-		}
-
-		// Determine if sprite hardware is available on pipe
-		// associated with this connector.
-		sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector,
-							  &sprite_plane_id);
-		if (!sprite_plane_count) {
-			printf("Failed to find sprite plane on crtc\n");
-			goto out;
+	/* Stress Cycle iteration */
+	for (sprite_loop = 0; sprite_loop < sprite_iteration_count; sprite_loop++) {
+		// Obtain pointer to struct containing graphics resources
+		disable_timer = 0;
+		gfx_resources = drmModeGetResources(gfx_fd);
+		if (!gfx_resources) {
+			printf("drmModeGetResources failed: %s\n", strerror(errno));
+			return;
 		}
 
-		// Width and height of preferred mode
-		prim_width = curr_connector.mode.hdisplay;
-		prim_height = curr_connector.mode.vdisplay;
-
-		// Allocate and fill memory for primary surface
-		ret = prepare_primary_surface(
-				gfx_fd,
-				prim_width,
-				prim_height,
-				&prim_handle,
-				&prim_stride,
-				&prim_size,
-				tiled);
-		if (ret != 0) {
-			printf("Failed to add primary fb (%dx%d): %s\n",
-				prim_width, prim_height, strerror(errno));
-			goto out;
+		if (dump_info != 0) {
+			dump_connectors(gfx_fd, gfx_resources);
+			dump_crtcs(gfx_fd, gfx_resources);
+			dump_planes(gfx_fd, gfx_resources);
 		}
 
-		// Add the primary surface framebuffer
-		ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32,
-				   prim_stride, prim_handle, &prim_fb_id);
-		gem_close(gfx_fd, prim_handle);
-
-		if (ret != 0) {
-			printf("Failed to add primary fb (%dx%d): %s\n",
-					prim_width, prim_height, strerror(errno));
-			goto out;
+		// Save previous terminal settings
+		if (tcgetattr( 0, &orig_term) != 0) {
+			printf("tcgetattr failure: %s\n",
+				strerror(errno));
+			return;
 		}
 
-		// Allocate and fill sprite surfaces
-		ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces,
-					      &sprite_handles[0],
-					      &sprite_stride, &sprite_size,
-					      tiled);
-		if (ret != 0) {
-			printf("Preparation of sprite surfaces failed %dx%d\n",
-				sprite_w, sprite_h);
-			goto out;
+		// Set up input to return characters immediately
+		curr_term = orig_term;
+		curr_term.c_lflag &= ~(ICANON | ECHO | ECHONL);
+		curr_term.c_cc[VMIN] = 0;       // No minimum number of characters
+		curr_term.c_cc[VTIME] = 0 ;     // Return immediately, even if
+		// nothing has been entered.
+		if (tcsetattr( 0, TCSANOW, &curr_term) != 0) {
+			printf("tcgetattr failure: %s\n", strerror(errno));
+			return;
 		}
 
-		// Add the sprite framebuffers
-		for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
-			handles[0] = sprite_handles[sprite_index];
-			handles[1] = handles[0];
-			handles[2] = handles[0];
-			handles[3] = handles[0];
-			pitches[0] = sprite_stride;
-			pitches[1] = sprite_stride;
-			pitches[2] = sprite_stride;
-			pitches[3] = sprite_stride;
-			memset(offsets, 0, sizeof(offsets));
-
-			ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h,
-					    DRM_FORMAT_XRGB8888,
-					    handles, pitches, offsets,
-					    &sprite_fb_id[sprite_index], plane_flags);
-			gem_close(gfx_fd, sprite_handles[sprite_index]);
-
-			if (ret) {
-				printf("Failed to add sprite fb (%dx%d): %s\n",
-				       sprite_w, sprite_h, strerror(errno));
-
-				sprite_index--;
-				while (sprite_index >= 0) {
-					drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
-					sprite_index--;
-				}
+		// Cycle through all connectors and display the flying sprite
+		// where there are displays attached and the hardware will support it.
+		for (c_index = 0; c_index < gfx_resources->count_connectors; c_index++)  {
+			curr_connector.id = gfx_resources->connectors[c_index];
+			// Find the native (preferred) display mode
+			connector_find_preferred_mode(gfx_fd, gfx_resources, &curr_connector);
+			if (curr_connector.mode_valid == 0) {
+				printf("No valid preferred mode detected\n");
 				goto out;
 			}
-		}
 
-		if (dump_info != 0) {
-			printf("Displayed Mode Connector struct:\n"
-				"    .id = %d\n"
-				"    .mode_valid = %d\n"
-				"    .crtc = %d\n"
-				"    .pipe = %d\n"
-				"    drmModeModeInfo ...\n"
-				"        .name = %s\n"
-				"        .type = %d\n"
-				"        .flags = %08x\n"
-				"    drmModeEncoder ...\n"
-				"        .encoder_id = %d\n"
-				"        .encoder_type = %d (%s)\n"
-				"        .crtc_id = %d\n"
-				"        .possible_crtcs = %d\n"
-				"        .possible_clones = %d\n"
-				"    drmModeConnector ...\n"
-				"        .connector_id = %d\n"
-				"        .encoder_id = %d\n"
-				"        .connector_type = %d (%s)\n"
-				"        .connector_type_id = %d\n\n",
-				curr_connector.id,
-				curr_connector.mode_valid,
-				curr_connector.crtc,
-				curr_connector.pipe,
-				curr_connector.mode.name,
-				curr_connector.mode.type,
-				curr_connector.mode.flags,
-				curr_connector.encoder->encoder_id,
-				curr_connector.encoder->encoder_type,
-				kmstest_encoder_type_str(curr_connector.encoder->encoder_type),
-				curr_connector.encoder->crtc_id,
-				curr_connector.encoder->possible_crtcs,
-				curr_connector.encoder->possible_clones,
-				curr_connector.connector->connector_id,
-				curr_connector.connector->encoder_id,
-				curr_connector.connector->connector_type,
-				kmstest_connector_type_str(curr_connector.connector->connector_type),
-				curr_connector.connector->connector_type_id);
-
-			printf("Sprite surface dimensions = %dx%d\n"
-				"Sprite output dimensions = %dx%d\n"
-				"Press any key to continue >\n",
-				sprite_w, sprite_h, out_w, out_h);
-
-			// Wait for a key-press
-			while( read(0, &key, 1) == 0);
-			// Purge unread characters
-			tcflush(0, TCIFLUSH);
-		}
+			// Determine if sprite hardware is available on pipe
+			// associated with this connector.
+			sprite_plane_count = connector_find_plane(gfx_fd, &curr_connector,
+								  &sprite_plane_id);
+			if (!sprite_plane_count) {
+				printf("Failed to find sprite plane on crtc\n");
+				goto out;
+			}
 
-		// Set up the primary display mode
-		ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id,
-				     0, 0, &curr_connector.id, 1, &curr_connector.mode);
-		if (ret != 0) {
-			printf("Failed to set mode (%dx%d@%dHz): %s\n",
-				prim_width, prim_height, curr_connector.mode.vrefresh,
-				strerror(errno));
-			continue;
-		}
+			// Width and height of preferred mode
+			prim_width = curr_connector.mode.hdisplay;
+			prim_height = curr_connector.mode.vdisplay;
+
+			// Allocate and fill memory for primary surface
+			ret = prepare_primary_surface(
+					gfx_fd,
+					prim_width,
+					prim_height,
+					&prim_handle,
+					&prim_stride,
+					&prim_size,
+					tiled);
+			if (ret != 0) {
+				printf("Failed to add primary fb (%dx%d): %s\n",
+					prim_width, prim_height, strerror(errno));
+				goto out;
+			}
 
-		// Set the sprite colorkey state
-		for(i = 0; i < sprite_plane_count; i++) {
-			set.plane_id = sprite_plane_id[i];
-			set.min_value = 0;
-			set.max_value = 0;
-			set.flags = I915_SET_COLORKEY_NONE;
-			ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
-					      sizeof(set));
-			assert(ret == 0);
-		}
+			// Add the primary surface framebuffer
+			ret = drmModeAddFB(gfx_fd, prim_width, prim_height, 24, 32,
+					   prim_stride, prim_handle, &prim_fb_id);
+			gem_close(gfx_fd, prim_handle);
 
-		// Set up sprite output dimensions, initial position, etc.
-		if (out_w > prim_width / 2)
-			out_w = prim_width / 2;
-		if (out_h > prim_height / 2)
-			out_h = prim_height / 2;
+			if (ret != 0) {
+				printf("Failed to add primary fb (%dx%d): %s\n",
+						prim_width, prim_height, strerror(errno));
+				goto out;
+			}
 
-		delta_x = (int *) malloc(sprite_plane_count * sizeof(int));
-		delta_y = (int *) malloc(sprite_plane_count * sizeof(int));
-		sprite_x = (int *) malloc(sprite_plane_count * sizeof(int));
-		sprite_y = (int *) malloc(sprite_plane_count * sizeof(int));
+			// Allocate and fill sprite surfaces
+			ret = prepare_sprite_surfaces(gfx_fd, sprite_w, sprite_h, num_surfaces,
+						      &sprite_handles[0],
+						      &sprite_stride, &sprite_size,
+						      tiled);
+			if (ret != 0) {
+				printf("Preparation of sprite surfaces failed %dx%d\n",
+					sprite_w, sprite_h);
+				goto out;
+			}
 
-		/* Initializing the coordinates (x,y) of the available sprites on the
-		 * connector, equally spaced along the diagonal of the rectangle
-		 * {(0,0),(prim_width/2, prim_height/2)}.
-		 */
-		for(i = 0; i < sprite_plane_count; i++) {
-			delta_x[i] = 3;
-			delta_y[i] = 4;
-			sprite_x[i] = i * (prim_width / (2 * sprite_plane_count));
-			sprite_y[i] = i * (prim_height / (2 * sprite_plane_count));
-		}
+			// Add the sprite framebuffers
+			for (sprite_index = 0; sprite_index < num_surfaces; sprite_index++) {
+				handles[0] = sprite_handles[sprite_index];
+				handles[1] = handles[0];
+				handles[2] = handles[0];
+				handles[3] = handles[0];
+				pitches[0] = sprite_stride;
+				pitches[1] = sprite_stride;
+				pitches[2] = sprite_stride;
+				pitches[3] = sprite_stride;
+				memset(offsets, 0, sizeof(offsets));
+
+				ret = drmModeAddFB2(gfx_fd, sprite_w, sprite_h,
+						    DRM_FORMAT_XRGB8888,
+						    handles, pitches, offsets,
+						    &sprite_fb_id[sprite_index], plane_flags);
+				gem_close(gfx_fd, sprite_handles[sprite_index]);
+
+				if (ret) {
+					printf("Failed to add sprite fb (%dx%d): %s\n",
+					       sprite_w, sprite_h, strerror(errno));
 
-		currTime = 0;
-		prevFlipTime = 0;       // Will force immediate sprite flip
-		prevMoveTime = 0;       // Will force immediate sprite move
-		deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
-		deltaMoveTime = 100000; // Move sprite every 100 ms
-		sprite_index = num_surfaces - 1;
-		keep_moving = 1;
+					sprite_index--;
+					while (sprite_index >= 0) {
+						drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
+						sprite_index--;
+					}
+					goto out;
+				}
+			}
 
-		// Bounce sprite off the walls
-		while (keep_moving) {
-			// Obtain system time in usec.
-			if (gettimeofday( &stTimeVal, NULL ) != 0)
-				printf("gettimeofday error: %s\n", strerror(errno));
-			else
-				currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;
+			if (dump_info != 0) {
+				printf("Displayed Mode Connector struct:\n"
+					"    .id = %d\n"
+					"    .mode_valid = %d\n"
+					"    .crtc = %d\n"
+					"    .pipe = %d\n"
+					"    drmModeModeInfo ...\n"
+					"        .name = %s\n"
+					"        .type = %d\n"
+					"        .flags = %08x\n"
+					"    drmModeEncoder ...\n"
+					"        .encoder_id = %d\n"
+					"        .encoder_type = %d (%s)\n"
+					"        .crtc_id = %d\n"
+					"        .possible_crtcs = %d\n"
+					"        .possible_clones = %d\n"
+					"    drmModeConnector ...\n"
+					"        .connector_id = %d\n"
+					"        .encoder_id = %d\n"
+					"        .connector_type = %d (%s)\n"
+					"        .connector_type_id = %d\n\n",
+					curr_connector.id,
+					curr_connector.mode_valid,
+					curr_connector.crtc,
+					curr_connector.pipe,
+					curr_connector.mode.name,
+					curr_connector.mode.type,
+					curr_connector.mode.flags,
+					curr_connector.encoder->encoder_id,
+					curr_connector.encoder->encoder_type,
+					kmstest_encoder_type_str(curr_connector.encoder->encoder_type),
+					curr_connector.encoder->crtc_id,
+					curr_connector.encoder->possible_crtcs,
+					curr_connector.encoder->possible_clones,
+					curr_connector.connector->connector_id,
+					curr_connector.connector->encoder_id,
+					curr_connector.connector->connector_type,
+					kmstest_connector_type_str(curr_connector.connector->connector_type),
+					curr_connector.connector->connector_type_id);
+
+				printf("Sprite surface dimensions = %dx%d\n"
+					"Sprite output dimensions = %dx%d\n"
+					"Press any key to continue >\n",
+					sprite_w, sprite_h, out_w, out_h);
+
+				// Wait for a key-press
+				while( read(0, &key, 1) == 0);
+				// Purge unread characters
+				tcflush(0, TCIFLUSH);
+			}
 
-			// Check if it's time to flip the sprite surface
-			if (currTime - prevFlipTime > deltaFlipTime) {
-				sprite_index = (sprite_index + 1) % num_surfaces;
+			// Set up the primary display mode
+			ret = drmModeSetCrtc(gfx_fd, curr_connector.crtc, prim_fb_id,
+					     0, 0, &curr_connector.id, 1, &curr_connector.mode);
+			if (ret != 0) {
+				printf("Failed to set mode (%dx%d@%dHz): %s\n",
+					prim_width, prim_height, curr_connector.mode.vrefresh,
+					strerror(errno));
+				continue;
+			}
 
-				prevFlipTime = currTime;
+			// Set the sprite colorkey state
+			for(i = 0; i < sprite_plane_count; i++) {
+				set.plane_id = sprite_plane_id[i];
+				set.min_value = 0;
+				set.max_value = 0;
+				set.flags = I915_SET_COLORKEY_NONE;
+				ret = drmCommandWrite(gfx_fd, DRM_I915_SET_SPRITE_COLORKEY, &set,
+					      sizeof(set));
+				assert(ret == 0);
 			}
 
-			// Move the sprite on the screen and flip
-			// the surface if the index has changed
-			// NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16
+			// Set up sprite output dimensions, initial position, etc.
+			if (out_w > prim_width / 2)
+				out_w = prim_width / 2;
+			if (out_h > prim_height / 2)
+				out_h = prim_height / 2;
+
+			delta_x = (int *) malloc(sprite_plane_count * sizeof(int));
+			delta_y = (int *) malloc(sprite_plane_count * sizeof(int));
+			sprite_x = (int *) malloc(sprite_plane_count * sizeof(int));
+			sprite_y = (int *) malloc(sprite_plane_count * sizeof(int));
+
+			/* Initializing the coordinates (x,y) of the available sprites on the
+			 * connector, equally spaced along the diagonal of the rectangle
+			 * {(0,0),(prim_width/2, prim_height/2)}.
+		 	*/
 			for(i = 0; i < sprite_plane_count; i++) {
-				if (drmModeSetPlane(gfx_fd, sprite_plane_id[i],
+				delta_x[i] = 3;
+				delta_y[i] = 4;
+				sprite_x[i] = i * (prim_width / (2 * sprite_plane_count));
+				sprite_y[i] = i * (prim_height / (2 * sprite_plane_count));
+			}
+
+			currTime = 0;
+			prevFlipTime = 0;       // Will force immediate sprite flip
+			prevMoveTime = 0;       // Will force immediate sprite move
+			deltaFlipTime = 500000; // Flip sprite surface every 1/2 second
+			deltaMoveTime = 100000; // Move sprite every 100 ms
+			sprite_index = num_surfaces - 1;
+			keep_moving = 1;
+
+			// Bounce sprite off the walls
+			while (keep_moving) {
+				// Obtain system time in usec.
+				if (gettimeofday( &stTimeVal, NULL ) != 0)
+					printf("gettimeofday error: %s\n", strerror(errno));
+				else
+					currTime = ((long long)stTimeVal.tv_sec * 1000000) + stTimeVal.tv_usec;
+
+				// Check if it's time to flip the sprite surface
+				if (currTime - prevFlipTime > deltaFlipTime) {
+					sprite_index = (sprite_index + 1) % num_surfaces;
+
+					prevFlipTime = currTime;
+				}
+
+				// Move the sprite on the screen and flip
+				// the surface if the index has changed
+				// NB: sprite_w and sprite_h must be 16.16 fixed point, herego << 16
+				for(i = 0; i < sprite_plane_count; i++) {
+					if (drmModeSetPlane(gfx_fd, sprite_plane_id[i],
 						    curr_connector.crtc,
 						    sprite_fb_id[sprite_index],
 						    plane_flags,
@@ -778,95 +785,118 @@  static void ricochet(int tiled, int sprite_w, int sprite_h,
 						    out_w, out_h,
 						    0, 0,
 						    sprite_w << 16, sprite_h << 16))
-					printf("Failed to enable sprite plane: %s\n",
-						strerror(errno));
-			}
-
-			// Check if it's time to move the sprite surface
-			if (currTime - prevMoveTime > deltaMoveTime)  {
+						printf("Failed to enable sprite plane: %s\n",
+							strerror(errno));
+				}
 
-				// Compute the next position for sprite
-				for(i = 0; i < sprite_plane_count; i++) {
-					sprite_x[i] += delta_x[i];
-					sprite_y[i] += delta_y[i];
-					if (sprite_x[i] < 0) {
-						sprite_x[i] = 0;
-						delta_x[i] = -delta_x[i];
-					}
-					else if (sprite_x[i] > prim_width - out_w) {
-						sprite_x[i] = prim_width - out_w;
-						delta_x[i] = -delta_x[i];
+				// Check if it's time to move the sprite surface
+				if (currTime - prevMoveTime > deltaMoveTime)  {
+
+					// Compute the next position for sprite
+					for(i = 0; i < sprite_plane_count; i++) {
+						sprite_x[i] += delta_x[i];
+						sprite_y[i] += delta_y[i];
+						if (sprite_x[i] < 0) {
+							sprite_x[i] = 0;
+							delta_x[i] = -delta_x[i];
+						}
+						else if (sprite_x[i] > prim_width - out_w) {
+							sprite_x[i] = prim_width - out_w;
+							delta_x[i] = -delta_x[i];
+						}
+
+						if (sprite_y[i] < 0) {
+							sprite_y[i] = 0;
+							delta_y[i] = -delta_y[i];
+						}
+						else if (sprite_y[i] > prim_height - out_h) {
+							sprite_y[i] = prim_height - out_h;
+							delta_y[i] = -delta_y[i];
+						}
 					}
-
-					if (sprite_y[i] < 0) {
-						sprite_y[i] = 0;
-						delta_y[i] = -delta_y[i];
+					prevMoveTime = currTime;
+				}
+				if (delay_time != 0) {
+					if (disable_timer == delay_time) {
+						plane_resources = drmModeGetPlaneResources(gfx_fd);
+						if (!plane_resources) {
+							printf("drmModeGetPlaneResources failed:%s\n", strerror(errno));
+							return;
+						}
+					for (i = 0; i < plane_resources->count_planes; i++) {
+						ovr = drmModeGetPlane(gfx_fd, plane_resources->planes[i]);
+						if (!ovr) {
+							printf("drmModeGetPlane failed:%s\n", strerror(errno));
+							continue;
+						}
+						drmModeFreePlane(ovr);
 					}
-					else if (sprite_y[i] > prim_height - out_h) {
-						sprite_y[i] = prim_height - out_h;
-						delta_y[i] = -delta_y[i];
+					while (sprite_index >= 0) {
+						drmModeRmFB(gfx_fd, sprite_fb_id[sprite_index]);
+						sprite_index--;
 					}
+					keep_moving = 0;
+					} else
+						disable_timer++;
 				}
-				prevMoveTime = currTime;
-			}
 
-			// Fetch a key from input (non-blocking)
-			if (read(0, &key, 1) == 1) {
-				switch (key) {
-				case 'q':       // Kill the program
-				case 'Q':
-					goto out;
-					break;
-				case 's':       // Slow down sprite movement;
-					deltaMoveTime = (deltaMoveTime * 100) / 90;
-					if (deltaMoveTime > 800000) {
-						deltaMoveTime = 800000;
-					}
-					break;
-				case 'S':       // Speed up sprite movement;
-					deltaMoveTime = (deltaMoveTime * 100) / 110;
-					if (deltaMoveTime < 2000) {
-						deltaMoveTime = 2000;
+				// Fetch a key from input (non-blocking)
+				if (read(0, &key, 1) == 1) {
+					switch (key) {
+					case 'q':       // Kill the program
+					case 'Q':
+						goto out;
+						break;
+					case 's':       // Slow down sprite movement;
+						deltaMoveTime = (deltaMoveTime * 100) / 90;
+						if (deltaMoveTime > 800000) {
+							deltaMoveTime = 800000;
+						}
+						break;
+					case 'S':       // Speed up sprite movement;
+						deltaMoveTime = (deltaMoveTime * 100) / 110;
+						if (deltaMoveTime < 2000) {
+							deltaMoveTime = 2000;
+						}
+						break;
+					case 'f':       // Slow down sprite flipping;
+						deltaFlipTime = (deltaFlipTime * 100) / 90;
+						if (deltaFlipTime > 1000000)
+							deltaFlipTime = 1000000;
+						break;
+					case 'F':       // Speed up sprite flipping;
+						deltaFlipTime = (deltaFlipTime * 100) / 110;
+						if (deltaFlipTime < 20000)
+							deltaFlipTime = 20000;
+						break;
+					case 'n':       // Next connector
+					case 'N':
+						keep_moving = 0;
+						break;
+					default:
+						break;
 					}
-					break;
-				case 'f':       // Slow down sprite flipping;
-					deltaFlipTime = (deltaFlipTime * 100) / 90;
-					if (deltaFlipTime > 1000000)
-						deltaFlipTime = 1000000;
-					break;
-				case 'F':       // Speed up sprite flipping;
-					deltaFlipTime = (deltaFlipTime * 100) / 110;
-					if (deltaFlipTime < 20000)
-						deltaFlipTime = 20000;
-					break;
-				case 'n':       // Next connector
-				case 'N':
-					keep_moving = 0;
-					break;
-				default:
-					break;
+	
+					// Purge unread characters
+					tcflush(0, TCIFLUSH);
 				}
 
-				// Purge unread characters
-				tcflush(0, TCIFLUSH);
+				// Wait for min of flip or move deltas
+				SleepTime = (deltaFlipTime < deltaMoveTime) ?
+					deltaFlipTime : deltaMoveTime;
+				usleep(SleepTime);
 			}
-
-			// Wait for min of flip or move deltas
-			SleepTime = (deltaFlipTime < deltaMoveTime) ?
-				deltaFlipTime : deltaMoveTime;
-			usleep(SleepTime);
+			free(sprite_plane_id);
+			free(sprite_x);
+			free(sprite_y);
+			free(delta_x);
+			free(delta_y);
+			sprite_plane_id = NULL;
+			sprite_plane_count = 0;
+			sprite_x = sprite_y = delta_x = delta_y = NULL;
 		}
-
-		free(sprite_plane_id);
-		free(sprite_x);
-		free(sprite_y);
-		free(delta_x);
-		free(delta_y);
-		sprite_plane_id = NULL;
-		sprite_plane_count = 0;
-		sprite_x = sprite_y = delta_x = delta_y = NULL;
+		keep_moving = 1;
 	}
-
 out:
 	// Purge unread characters
 	tcflush(0, TCIFLUSH);
@@ -886,6 +916,8 @@  static void usage(char *name)
 		"\t-h\t[optional] output help message\n"
 		"\t-t\t[optional] enable tiling\n"
 		"\t-o\t[optional] <output rect width>x<output rect height>\n\n"
+		"\t-a\t[time] for passing sleep time in seconds before disabling planes in each cycle of stress test\n"
+		"\t-n\t[n] Stress cycle count\n\n"
 		"Keyboard control for sprite movement and flip rate ...\n"
 		"\t'q' or 'Q' - Quit the program\n"
 		"\t'n' or 'N' - Switch to next display\n"
@@ -905,8 +937,9 @@  int main(int argc, char **argv)
 	int                 plane_width = 0,
 			    plane_height = 0,
 			    out_width = 0,
-			    out_height = 0;
-	static char         optstr[] = "ds:o:th";
+			    out_height = 0,
+			    delay_time = 0;
+	static char         optstr[] = "ds:o:th:a:n:";
 
 	opterr = 0;
 	while ((c = getopt(argc, argv, optstr)) != -1) {
@@ -926,6 +959,14 @@  int main(int argc, char **argv)
 			if (sscanf(optarg, "%dx%d", &out_width, &out_height) != 2)
 				usage(argv[0]);
 			break;
+		case 'a':		/* Delay time for disabling sprites */
+			if (sscanf(optarg, "%d", &delay_time) != 1)
+				usage(argv[0]);
+			break;
+		case 'n':		/* Stress cycle count  */
+			if (sscanf(optarg, "%d", &sprite_iteration_count) != 1)
+				usage(argv[0]);
+			break;
 		default:
 			printf("unknown option %c\n", c);
 			/* fall through */
@@ -942,7 +983,7 @@  int main(int argc, char **argv)
 		if (out_height < (plane_height / 2))
 			out_height = plane_height;
 
-		ricochet(enable_tiling, plane_width, plane_height, out_width, out_height, dump_info);
+		ricochet(enable_tiling, plane_width, plane_height, out_width, out_height, dump_info, delay_time);
 	} else {
 		printf("Sprite dimensions are required:\n");
 		usage(argv[0]);