kms_flip.c 33.6 KB
Newer Older
Jesse Barnes's avatar
Jesse Barnes committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright 2012 Intel Corporation
 *   Jesse Barnes <jesse.barnes@intel.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

24
#ifdef HAVE_CONFIG_H
Jesse Barnes's avatar
Jesse Barnes committed
25
#include "config.h"
26
#endif
Jesse Barnes's avatar
Jesse Barnes committed
27 28 29

#include <cairo.h>
#include <errno.h>
30
#include <fcntl.h>
Jesse Barnes's avatar
Jesse Barnes committed
31 32 33 34 35 36 37
#include <math.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
Imre Deak's avatar
Imre Deak committed
38
#include <linux/kd.h>
Jesse Barnes's avatar
Jesse Barnes committed
39 40 41 42

#include "i915_drm.h"
#include "drmtest.h"
#include "testdisplay.h"
43
#include "rendercopy.h"
Jesse Barnes's avatar
Jesse Barnes committed
44

45
#define TEST_DPMS		(1 << 0)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#define TEST_WITH_DUMMY_BCS	(1 << 1)
#define TEST_WITH_DUMMY_RCS	(1 << 2)
#define TEST_PAN		(1 << 3)
#define TEST_MODESET		(1 << 4)
#define TEST_CHECK_TS		(1 << 5)
#define TEST_EBUSY		(1 << 6)
#define TEST_EINVAL		(1 << 7)
#define TEST_FLIP		(1 << 8)
#define TEST_VBLANK		(1 << 9)
#define TEST_VBLANK_BLOCK	(1 << 10)
#define TEST_VBLANK_ABSOLUTE	(1 << 11)
#define TEST_VBLANK_EXPIRED_SEQ	(1 << 12)
#define TEST_FB_RECREATE	(1 << 13)
#define TEST_RMFB		(1 << 14)
#define TEST_HANG		(1 << 15)
#define TEST_NOEVENT		(1 << 16)
#define TEST_FB_BAD_TILING	(1 << 17)
#define TEST_SINGLE_BUFFER	(1 << 18)
#define TEST_DPMS_OFF		(1 << 19)
65

66
#define EVENT_FLIP		(1 << 0)
67
#define EVENT_VBLANK		(1 << 1)
68

69 70 71 72
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
#define DRM_CAP_TIMESTAMP_MONOTONIC 6
#endif

Jesse Barnes's avatar
Jesse Barnes committed
73 74
drmModeRes *resources;
int drm_fd;
75 76 77
static drm_intel_bufmgr *bufmgr;
struct intel_batchbuffer *batch;
uint32_t devid;
Jesse Barnes's avatar
Jesse Barnes committed
78
int test_time = 3;
79
static bool monotonic_timestamp;
Jesse Barnes's avatar
Jesse Barnes committed
80

81 82
static drmModeConnector *last_connector;

Jesse Barnes's avatar
Jesse Barnes committed
83 84 85 86 87 88 89
uint32_t *fb_ptr;

struct type_name {
	int type;
	const char *name;
};

90 91 92 93 94 95 96 97 98
struct event_state {
	const char *name;

	/*
	 * Event data for the last event that has already passed our check.
	 * Updated using the below current_* vars in update_state().
	 */
	struct timeval last_ts;			/* kernel reported timestamp */
	struct timeval last_received_ts;	/* the moment we received it */
99
	unsigned int last_seq;			/* kernel reported seq. num */
100 101 102 103 104 105 106

	/*
	 * Event data for for the current event that we just received and
	 * going to check for validity. Set in event_handler().
	 */
	struct timeval current_ts;		/* kernel reported timestamp */
	struct timeval current_received_ts;	/* the moment we received it */
107
	unsigned int current_seq;		/* kernel reported seq. num */
108 109

	int count;				/* # of events of this type */
110 111 112

	/* Step between the current and next 'target' sequence number. */
	int seq_step;
113 114
};

Jesse Barnes's avatar
Jesse Barnes committed
115 116
struct test_output {
	int mode_valid;
117 118 119 120 121 122
	drmModeModeInfo kmode[4];
	drmModeEncoder *kencoder[4];
	drmModeConnector *kconnector[4];
	uint32_t _connector[4];
	uint32_t _crtc[4];
	int count; /* 1:1 mapping between crtc:connector */
123
	int flags;
124
	int pipe; /* primary pipe for vblank */
Jesse Barnes's avatar
Jesse Barnes committed
125
	unsigned int current_fb_id;
126 127
	unsigned int fb_width;
	unsigned int fb_height;
128
	unsigned int fb_ids[3];
Daniel Vetter's avatar
Daniel Vetter committed
129
	int bpp, depth;
130
	struct kmstest_fb fb_info[3];
131 132

	struct event_state flip_state;
133
	struct event_state vblank_state;
134
	unsigned int pending_events;
Jesse Barnes's avatar
Jesse Barnes committed
135 136
};

137 138 139 140 141 142 143 144 145 146

static unsigned long gettime_us(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC, &ts);

	return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
}

147
static void emit_dummy_load__bcs(struct test_output *o)
148
{
149
	int i, limit;
150 151 152 153
	drm_intel_bo *dummy_bo, *target_bo, *tmp_bo;
	struct kmstest_fb *fb_info = &o->fb_info[o->current_fb_id];
	unsigned pitch = fb_info->stride;

154 155
	limit = intel_gen(devid) < 6 ? 500 : 5000;

156
	dummy_bo = drm_intel_bo_alloc(bufmgr, "dummy_bo", fb_info->size, 4096);
Daniel Vetter's avatar
Daniel Vetter committed
157
	igt_assert(dummy_bo);
158
	target_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "imported", fb_info->gem_handle);
Daniel Vetter's avatar
Daniel Vetter committed
159
	igt_assert(target_bo);
160

161
	for (i = 0; i < limit; i++) {
162 163 164 165 166 167 168 169
		BEGIN_BATCH(8);
		OUT_BATCH(XY_SRC_COPY_BLT_CMD |
			  XY_SRC_COPY_BLT_WRITE_ALPHA |
			  XY_SRC_COPY_BLT_WRITE_RGB);
		OUT_BATCH((3 << 24) | /* 32 bits */
			  (0xcc << 16) | /* copy ROP */
			  pitch);
		OUT_BATCH(0 << 16 | 0);
170
		OUT_BATCH(o->fb_height << 16 | o->fb_width);
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
		OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
		OUT_BATCH(0 << 16 | 0);
		OUT_BATCH(pitch);
		OUT_RELOC_FENCED(target_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
		ADVANCE_BATCH();

		if (IS_GEN6(devid) || IS_GEN7(devid)) {
			BEGIN_BATCH(3);
			OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
			OUT_BATCH(0);
			OUT_BATCH(0);
			ADVANCE_BATCH();
		}

		tmp_bo = dummy_bo;
		dummy_bo = target_bo;
		target_bo = tmp_bo;
	}
	intel_batchbuffer_flush(batch);

	drm_intel_bo_unreference(dummy_bo);
	drm_intel_bo_unreference(target_bo);
}

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
static void emit_dummy_load__rcs(struct test_output *o)
{
	const struct kmstest_fb *fb_info = &o->fb_info[o->current_fb_id];
	render_copyfunc_t copyfunc;
	struct scratch_buf sb[2], *src, *dst;
	int i, limit;

	copyfunc = get_render_copyfunc(devid);
	if (copyfunc == NULL)
		return emit_dummy_load__bcs(o);

	limit = intel_gen(devid) < 6 ? 500 : 5000;

	sb[0].bo = drm_intel_bo_alloc(bufmgr, "dummy_bo", fb_info->size, 4096);
	igt_assert(sb[0].bo);
	sb[0].size = sb[0].bo->size;
	sb[0].tiling = I915_TILING_NONE;
	sb[0].data = NULL;
	sb[0].num_tiles = sb[0].bo->size;
214
	sb[0].stride = 4 * o->fb_width;
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

	sb[1].bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "imported", fb_info->gem_handle);
	igt_assert(sb[1].bo);
	sb[1].size = sb[1].bo->size;
	sb[1].tiling = fb_info->tiling;
	sb[1].data = NULL;
	sb[1].num_tiles = sb[1].bo->size;
	sb[1].stride = fb_info->stride;

	src = &sb[0];
	dst = &sb[1];

	for (i = 0; i < limit; i++) {
		struct scratch_buf *tmp;

		copyfunc(batch,
			 src, 0, 0,
232
			 o->fb_width, o->fb_height,
233 234 235 236 237 238 239 240 241 242 243 244
			 dst, 0, 0);

		tmp = src;
		src = dst;
		dst = tmp;
	}
	intel_batchbuffer_flush(batch);

	drm_intel_bo_unreference(sb[0].bo);
	drm_intel_bo_unreference(sb[1].bo);
}

245
static int set_connector_dpms(drmModeConnector *connector, int mode)
246 247 248
{
	int i, dpms = 0;

249
	for (i = 0; i < connector->count_props; i++) {
250 251
		struct drm_mode_get_property prop;

252
		prop.prop_id = connector->props[i];
253 254 255 256 257 258 259 260 261 262 263 264
		prop.count_values = 0;
		prop.count_enum_blobs = 0;
		if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
			continue;

		if (strcmp(prop.name, "DPMS"))
			continue;

		dpms = prop.prop_id;
		break;
	}
	if (!dpms) {
265 266
		fprintf(stderr, "DPMS property not found on %d\n",
			connector->connector_id);
267 268 269 270
		errno = ENOENT;
		return -1;
	}

271 272 273 274 275 276
	return drmModeConnectorSetProperty(drm_fd, connector->connector_id,
					   dpms, mode);
}

static int set_dpms(struct test_output *o, int mode)
{
277 278 279 280 281 282 283 284 285
	int n;

	for (n = 0; n < o->count; n++) {
		int ret = set_connector_dpms(o->kconnector[n], mode);
		if (ret)
			return ret;
	}

	return 0;
286 287
}

288 289
static void set_flag(unsigned int *v, unsigned int flag)
{
Daniel Vetter's avatar
Daniel Vetter committed
290
	igt_assert(!(*v & flag));
291 292 293 294 295
	*v |= flag;
}

static void clear_flag(unsigned int *v, unsigned int flag)
{
Daniel Vetter's avatar
Daniel Vetter committed
296
	igt_assert(*v & flag);
297 298 299
	*v &= ~flag;
}

300
static int do_page_flip(struct test_output *o, int fb_id, bool event)
301
{
302
	int n, ret = 0;
303

304 305 306 307 308 309
	for (n = 0; n < o->count; n++) {
		ret = drmModePageFlip(drm_fd, o->_crtc[n], fb_id, event ? DRM_MODE_PAGE_FLIP_EVENT : 0,
				      event ? o : NULL);
		if (ret == 0 && event)
			set_flag(&o->pending_events, EVENT_FLIP);
	}
310 311

	return ret;
312 313
}

314 315 316 317 318
struct vblank_reply {
	unsigned int sequence;
	struct timeval ts;
};

319 320 321
static int __wait_for_vblank(unsigned int flags, int crtc_idx,
			      int target_seq, unsigned long ret_data,
			      struct vblank_reply *reply)
322 323 324 325
{
	drmVBlank wait_vbl;
	int ret;
	unsigned crtc_idx_mask;
326
	bool event = !(flags & TEST_VBLANK_BLOCK);
327 328 329 330

	memset(&wait_vbl, 0, sizeof(wait_vbl));

	crtc_idx_mask = crtc_idx << DRM_VBLANK_HIGH_CRTC_SHIFT;
Daniel Vetter's avatar
Daniel Vetter committed
331
	igt_assert(!(crtc_idx_mask & ~DRM_VBLANK_HIGH_CRTC_MASK));
332 333

	wait_vbl.request.type = crtc_idx_mask;
334
	if (flags & TEST_VBLANK_ABSOLUTE)
335 336 337 338 339
		wait_vbl.request.type |= DRM_VBLANK_ABSOLUTE;
	else
		wait_vbl.request.type |= DRM_VBLANK_RELATIVE;
	if (event) {
		wait_vbl.request.type |= DRM_VBLANK_EVENT;
340
		wait_vbl.request.signal = ret_data;
341 342 343 344 345 346 347 348 349
	}
	wait_vbl.request.sequence = target_seq;

	ret = drmWaitVBlank(drm_fd, &wait_vbl);

	if (ret == 0) {
		reply->ts.tv_sec = wait_vbl.reply.tval_sec;
		reply->ts.tv_usec = wait_vbl.reply.tval_usec;
		reply->sequence = wait_vbl.reply.sequence;
350 351
	} else
		ret = -errno;
352 353 354 355

	return ret;
}

356 357 358 359 360 361 362 363 364 365 366 367 368
static int do_wait_for_vblank(struct test_output *o, int pipe_id,
			      int target_seq, struct vblank_reply *reply)
{
	int ret;

	ret = __wait_for_vblank(o->flags, pipe_id, target_seq, (unsigned long)o,
				reply);
	if (ret == 0 && !(o->flags & TEST_VBLANK_BLOCK))
		set_flag(&o->pending_events, EVENT_VBLANK);

	return ret;
}

369 370 371
static bool
analog_tv_connector(struct test_output *o)
{
372
	uint32_t connector_type = o->kconnector[0]->connector_type;
373 374 375 376 377 378 379

	return connector_type == DRM_MODE_CONNECTOR_TV ||
		connector_type == DRM_MODE_CONNECTOR_9PinDIN ||
		connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
		connector_type == DRM_MODE_CONNECTOR_Composite;
}

380 381 382
static void event_handler(struct event_state *es, unsigned int frame,
			  unsigned int sec, unsigned int usec)
{
383 384 385 386 387 388 389 390 391 392 393 394 395
	struct timeval now;

	if (monotonic_timestamp) {
		struct timespec ts;

		clock_gettime(CLOCK_MONOTONIC, &ts);
		now.tv_sec = ts.tv_sec;
		now.tv_usec = ts.tv_nsec / 1000;
	} else {
		gettimeofday(&now, NULL);
	}
	es->current_received_ts = now;

396 397
	es->current_ts.tv_sec = sec;
	es->current_ts.tv_usec = usec;
398
	es->current_seq = frame;
399 400
}

Jesse Barnes's avatar
Jesse Barnes committed
401 402 403 404
static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
			      unsigned int usec, void *data)
{
	struct test_output *o = data;
405

406
	clear_flag(&o->pending_events, EVENT_FLIP);
407
	event_handler(&o->flip_state, frame, sec, usec);
408 409
}

410 411
static double frame_time(struct test_output *o)
{
412
	return 1000.0 * 1000.0 / o->kmode[0].vrefresh;
413 414
}

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
static void fixup_premature_vblank_ts(struct test_output *o,
				      struct event_state *es)
{
	/*
	 * In case a power off event preempts the completion of a
	 * wait-for-vblank event the kernel will return a wf-vblank event with
	 * a zeroed-out timestamp. In order that check_state() doesn't
	 * complain replace this ts with a valid ts. As we can't calculate the
	 * exact timestamp, just use the time we received the event.
	 */
	struct timeval tv;

	if (!(o->flags & (TEST_DPMS | TEST_MODESET)))
		return;

	if (o->vblank_state.current_ts.tv_sec != 0 ||
	    o->vblank_state.current_ts.tv_usec != 0)
		return;

	tv.tv_sec = 0;
	tv.tv_usec = 1;
	timersub(&es->current_received_ts, &tv, &es->current_ts);
}

439 440 441 442 443 444 445
static void vblank_handler(int fd, unsigned int frame, unsigned int sec,
			      unsigned int usec, void *data)
{
	struct test_output *o = data;

	clear_flag(&o->pending_events, EVENT_VBLANK);
	event_handler(&o->vblank_state, frame, sec, usec);
446
	fixup_premature_vblank_ts(o, &o->vblank_state);
447 448
}

449
static void check_state(struct test_output *o, struct event_state *es)
450 451 452
{
	struct timeval diff;
	double usec_interflip;
453

454
	timersub(&es->current_ts, &es->current_received_ts, &diff);
455 456
	if ((!analog_tv_connector(o)) &&
	    (diff.tv_sec > 0 || (diff.tv_sec == 0 && diff.tv_usec > 2000))) {
457 458
		fprintf(stderr, "%s ts delayed for too long: %is, %iusec\n",
			es->name, (int)diff.tv_sec, (int)diff.tv_usec);
459
		igt_fail(5);
460
	}
Jesse Barnes's avatar
Jesse Barnes committed
461

462 463 464
	if (es->count == 0)
		return;

465 466 467 468 469
	if (!timercmp(&es->last_received_ts, &es->current_ts, <)) {
		fprintf(stderr, "%s ts before the %s was issued!\n",
				es->name, es->name);

		timersub(&es->current_ts, &es->last_received_ts, &diff);
470 471
		fprintf(stderr, "timerdiff %is, %ius\n",
			(int) diff.tv_sec, (int) diff.tv_usec);
472
		igt_fail(6);
473 474
	}

475
	/* This bounding matches the one in DRM_IOCTL_WAIT_VBLANK. */
476 477 478 479 480 481
	if (!(o->flags & (TEST_DPMS | TEST_MODESET))) {
		/* check only valid if no modeset happens in between, that
		 * increments by (1 << 23) on each step. */
		if (es->current_seq - (es->last_seq + es->seq_step) > 1UL << 23) {
			fprintf(stderr, "unexpected %s seq %u, should be >= %u\n",
				es->name, es->current_seq, es->last_seq + es->seq_step);
482
			igt_fail(10);
483
		}
484 485 486
	}

	if ((o->flags & TEST_CHECK_TS) && (!analog_tv_connector(o))) {
487
		timersub(&es->current_ts, &es->last_ts, &diff);
488
		usec_interflip = (double)es->seq_step * frame_time(o);
489 490 491 492
		if (fabs((((double) diff.tv_usec) - usec_interflip) /
		    usec_interflip) > 0.005) {
			fprintf(stderr, "inter-%s ts jitter: %is, %ius\n",
				es->name,
493
				(int) diff.tv_sec, (int) diff.tv_usec);
494
			igt_fail(9);
495
		}
496

497
		if (es->current_seq != es->last_seq + es->seq_step) {
498 499 500
			fprintf(stderr, "unexpected %s seq %u, expected %u\n",
					es->name, es->current_seq,
					es->last_seq + es->seq_step);
501
			igt_fail(9);
502
		}
503
	}
504 505
}

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
static void check_state_correlation(struct test_output *o,
				    struct event_state *es1,
				    struct event_state *es2)
{
	struct timeval tv_diff;
	double ftime;
	double usec_diff;
	int seq_diff;

	if (es1->count == 0 || es2->count == 0)
		return;

	timersub(&es2->current_ts, &es1->current_ts, &tv_diff);
	usec_diff = tv_diff.tv_sec * 1000 * 1000 + tv_diff.tv_usec;

	seq_diff = es2->current_seq - es1->current_seq;
	ftime = frame_time(o);
	usec_diff -= seq_diff * ftime;

	if (fabs(usec_diff) / ftime > 0.005) {
		fprintf(stderr,
			"timestamp mismatch between %s and %s (diff %.4f sec)\n",
			es1->name, es2->name, usec_diff / 1000 / 1000);
529
		igt_fail(14);
530 531 532
	}
}

533 534
static void check_all_state(struct test_output *o,
			    unsigned int completed_events)
535
{
536 537 538 539 540 541
	bool flip, vblank;

	flip = completed_events & EVENT_FLIP;
	vblank = completed_events & EVENT_VBLANK;

	if (flip)
542
		check_state(o, &o->flip_state);
543
	if (vblank)
544
		check_state(o, &o->vblank_state);
545 546 547

	if (flip && vblank)
		check_state_correlation(o, &o->flip_state, &o->vblank_state);
548 549
}

Daniel Vetter's avatar
Daniel Vetter committed
550 551 552 553 554 555 556 557
static void recreate_fb(struct test_output *o)
{
	drmModeFBPtr r;
	struct kmstest_fb *fb_info = &o->fb_info[o->current_fb_id];
	uint32_t new_fb_id;

	/* Call rmfb/getfb/addfb to ensure those don't introduce stalls */
	r = drmModeGetFB(drm_fd, fb_info->fb_id);
Daniel Vetter's avatar
Daniel Vetter committed
558
	igt_assert(r);
Daniel Vetter's avatar
Daniel Vetter committed
559 560 561 562 563 564

	do_or_die(drmModeAddFB(drm_fd, o->fb_width, o->fb_height, o->depth,
			       o->bpp, fb_info->stride,
			       r->handle, &new_fb_id));

	gem_close(drm_fd, r->handle);
565
	drmFree(r);
Daniel Vetter's avatar
Daniel Vetter committed
566 567 568 569 570 571
	do_or_die(drmModeRmFB(drm_fd, fb_info->fb_id));

	o->fb_ids[o->current_fb_id] = new_fb_id;
	o->fb_info[o->current_fb_id].fb_id = new_fb_id;
}

572 573 574 575 576 577 578
static void set_y_tiling(struct test_output *o, int fb_idx)
{
	drmModeFBPtr r;
	struct kmstest_fb *fb_info = &o->fb_info[fb_idx];

	/* Call rmfb/getfb/addfb to ensure those don't introduce stalls */
	r = drmModeGetFB(drm_fd, fb_info->fb_id);
Daniel Vetter's avatar
Daniel Vetter committed
579
	igt_assert(r);
580 581 582 583 584 585
	gem_set_tiling(drm_fd, r->handle, I915_TILING_Y, fb_info->stride);
	gem_close(drm_fd, r->handle);
	drmFree(r);
}


586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
static int exec_nop(int fd, uint32_t handle)
{
	struct drm_i915_gem_execbuffer2 execbuf;
	struct drm_i915_gem_exec_object2 gem_exec[1];
	uint32_t b[2] = {MI_BATCH_BUFFER_END};
	int r;

	gem_write(fd, handle, 0, b, sizeof(b));

	gem_exec[0].handle = handle;
	gem_exec[0].relocation_count = 0;
	gem_exec[0].relocs_ptr = 0;
	gem_exec[0].alignment = 0;
	gem_exec[0].offset = 0;
	gem_exec[0].flags = 0;
	gem_exec[0].rsvd1 = 0;
	gem_exec[0].rsvd2 = 0;

	execbuf.buffers_ptr = (uintptr_t)gem_exec;
	execbuf.buffer_count = 1;
	execbuf.batch_start_offset = 0;
	execbuf.batch_len = 8;
	execbuf.cliprects_ptr = 0;
	execbuf.num_cliprects = 0;
	execbuf.DR1 = 0;
	execbuf.DR4 = 0;
	execbuf.flags =  I915_EXEC_RENDER;
	i915_execbuffer2_set_context_id(execbuf, 0);
	execbuf.rsvd2 = 0;

	r = drmIoctl(fd,
			DRM_IOCTL_I915_GEM_EXECBUFFER2,
			&execbuf);
	if (r)
		fprintf(stderr, "failed to exec: %s\n",
			strerror(errno));
	return r;
}

625 626 627 628 629 630 631 632
static void eat_error_state(struct test_output *o)
{
	static const char dfs_base[] = "/sys/kernel/debug/dri";
	static const char dfs_entry_error[] = "i915_error_state";
	static const char dfs_entry_stop[] = "i915_ring_stop";
	static const char data[] = "";
	static char tmp[128];
	char fname[FILENAME_MAX];
633
	int card_index = drm_get_card();
634 635 636
	int fd;
	ssize_t r;

Daniel Vetter's avatar
Daniel Vetter committed
637
	igt_assert(card_index != -1);
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674

	/* clear the error state */
	snprintf(fname, FILENAME_MAX, "%s/%i/%s",
		 dfs_base, card_index, dfs_entry_error);

	fd = open(fname, O_WRONLY);
	if (fd < 0) {
		fprintf(stderr, "failed to open '%s': %s\n",
			fname, strerror(errno));
		return;
	}

	r = write(fd, data, sizeof data);
	if (r < 0)
		fprintf(stderr, "failed to write '%s': %s\n",
			fname, strerror(errno));
	close(fd);

	/* and check whether stop_rings is not reset, i.e. the hang has indeed
	 * happened */
	snprintf(fname, FILENAME_MAX, "%s/%i/%s",
		 dfs_base, card_index, dfs_entry_stop);

	fd = open(fname, O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "failed to open '%s': %s\n",
			fname, strerror(errno));
		return;
	}

	r = read(fd, tmp, sizeof tmp);
	if (r < 0)
		fprintf(stderr, "failed to read '%s': %s\n",
			fname, strerror(errno));

	if (atoi(tmp) != 0) {
		fprintf(stderr, "no gpu hang detected, stop_rings is still %s\n", tmp);
675
		igt_fail(20);
676 677 678 679 680
	}

	close(fd);
}

681 682 683 684 685 686
static void hang_gpu(struct test_output *o)
{
	static const char dfs_base[] = "/sys/kernel/debug/dri";
	static const char dfs_entry[] = "i915_ring_stop";
	static const char data[] = "0xf";
	char fname[FILENAME_MAX];
687
	int card_index = drm_get_card();
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
	int fd;
	ssize_t r;

	snprintf(fname, FILENAME_MAX, "%s/%i/%s",
		 dfs_base, card_index, dfs_entry);

	fd = open(fname, O_WRONLY);
	if (fd < 0) {
		fprintf(stderr, "failed to open '%s': %s\n",
			fname, strerror(errno));
		return;
	}

	r = write(fd, data, sizeof data);
	if (r < 0)
		fprintf(stderr, "failed to write '%s': %s\n",
			fname, strerror(errno));

	close(fd);
}

709 710 711 712 713 714 715 716 717 718 719 720 721
static int set_mode(struct test_output *o, int fb, int x, int y)
{
	int n;

	for (n = 0; n < o->count; n++) {
		if (drmModeSetCrtc(drm_fd, o->_crtc[n], fb,
				   x, y, &o->_connector[n], 1, &o->kmode[n]))
			return -1;
	}

	return 0;
}

722 723
/* Return mask of completed events. */
static unsigned int run_test_step(struct test_output *o)
724 725 726 727
{
	unsigned int new_fb_id;
	/* for funny reasons page_flip returns -EBUSY on disabled crtcs ... */
	int expected_einval = o->flags & TEST_MODESET ? -EBUSY : -EINVAL;
728
	unsigned int completed_events = 0;
729
	bool do_flip;
730
	bool do_vblank;
731 732
	struct vblank_reply vbl_reply;
	unsigned int target_seq;
733
	uint32_t handle = 0;	/* Suppress GCC warning */
734 735 736 737

	target_seq = o->vblank_state.seq_step;
	if (o->flags & TEST_VBLANK_ABSOLUTE)
		target_seq += o->vblank_state.last_seq;
738

739 740 741 742 743
	/*
	 * It's possible that we don't have a pending flip here, in case both
	 * wf-vblank and flip were scheduled and the wf-vblank event was
	 * delivered earlier. The same applies to vblank events w.r.t flip.
	 */
744
	do_flip = (o->flags & TEST_FLIP) && !(o->pending_events & EVENT_FLIP);
745 746
	do_vblank = (o->flags & TEST_VBLANK) &&
		    !(o->pending_events & EVENT_VBLANK);
747

748 749
	if (o->flags & TEST_WITH_DUMMY_BCS)
		emit_dummy_load__bcs(o);
750

751 752
	if (o->flags & TEST_WITH_DUMMY_RCS)
		emit_dummy_load__rcs(o);
753

754 755 756
	if (!(o->flags & TEST_SINGLE_BUFFER))
		o->current_fb_id = !o->current_fb_id;

Daniel Vetter's avatar
Daniel Vetter committed
757 758
	if (o->flags & TEST_FB_RECREATE)
		recreate_fb(o);
759 760
	new_fb_id = o->fb_ids[o->current_fb_id];

761 762 763
	if (o->flags & TEST_FB_BAD_TILING)
		new_fb_id = o->fb_ids[2];

764 765 766 767 768 769 770 771 772 773 774
	if ((o->flags & TEST_VBLANK_EXPIRED_SEQ) &&
	    !(o->pending_events & EVENT_VBLANK) && o->flip_state.count > 0) {
		struct vblank_reply reply;
		unsigned int exp_seq;
		unsigned long start;

		exp_seq = o->flip_state.current_seq;
		start = gettime_us();
		do_or_die(__wait_for_vblank(TEST_VBLANK_ABSOLUTE |
					    TEST_VBLANK_BLOCK, o->pipe, exp_seq,
					    0, &reply));
Daniel Vetter's avatar
Daniel Vetter committed
775 776 777
		igt_assert(gettime_us() - start < 500);
		igt_assert(reply.sequence == exp_seq);
		igt_assert(timercmp(&reply.ts, &o->flip_state.last_ts, ==));
778 779
	}

780
	if (do_flip && (o->flags & TEST_EINVAL) && o->flip_state.count > 0)
Daniel Vetter's avatar
Daniel Vetter committed
781
		igt_assert(do_page_flip(o, new_fb_id, true) == expected_einval);
782

783 784 785
	if (o->flags & TEST_FB_BAD_TILING)
		new_fb_id = o->fb_ids[o->current_fb_id];

786
	if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
Daniel Vetter's avatar
Daniel Vetter committed
787
		igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply)
788 789
		       == -EINVAL);

790 791 792
	if (o->flags & TEST_DPMS_OFF)
		do_or_die(set_dpms(o, DRM_MODE_DPMS_OFF));

793
	if (o->flags & TEST_MODESET) {
794
		if (set_mode(o, o->fb_ids[o->current_fb_id], 0, 0)) {
795 796
			fprintf(stderr, "failed to restore output mode: %s\n",
				strerror(errno));
797
			igt_fail(7);
798 799 800
		}
	}

801
	if (o->flags & TEST_DPMS)
802
		do_or_die(set_dpms(o, DRM_MODE_DPMS_ON));
Jesse Barnes's avatar
Jesse Barnes committed
803

804 805
	printf("."); fflush(stdout);

806 807 808 809 810 811
	if (do_flip && (o->flags & TEST_HANG)) {
		handle = gem_create(drm_fd, 4096);
		hang_gpu(o);
		exec_nop(drm_fd, handle);
	}

812
	if (do_flip)
813
		do_or_die(do_page_flip(o, new_fb_id, !(o->flags & TEST_NOEVENT)));
814

815 816 817 818 819 820 821 822 823 824 825
	if (do_vblank) {
		do_or_die(do_wait_for_vblank(o, o->pipe, target_seq,
					     &vbl_reply));
		if (o->flags & TEST_VBLANK_BLOCK) {
			event_handler(&o->vblank_state, vbl_reply.sequence,
				      vbl_reply.ts.tv_sec,
				      vbl_reply.ts.tv_usec);
			completed_events = EVENT_VBLANK;
		}
	}

826
	if (do_flip && (o->flags & TEST_EBUSY))
Daniel Vetter's avatar
Daniel Vetter committed
827
		igt_assert(do_page_flip(o, new_fb_id, true) == -EBUSY);
828

829 830 831
	if (do_flip && (o->flags & TEST_RMFB))
		recreate_fb(o);

832 833
	/* pan before the flip completes */
	if (o->flags & TEST_PAN) {
834 835
		int count = do_flip ?
			o->flip_state.count : o->vblank_state.count;
836
		int x_ofs = count * 10 > o->fb_width ?  o->fb_width : count * 10;
837

838
		if (set_mode(o, o->fb_ids[o->current_fb_id], x_ofs, 0)){
839 840
			fprintf(stderr, "failed to pan (%dx%d@%dHz): %s\n",
				o->fb_width, o->fb_height,
841
				o->kmode[0].vrefresh, strerror(errno));
842
			igt_fail(7);
843 844 845
		}
	}

846
	if (o->flags & TEST_DPMS)
847
		do_or_die(set_dpms(o, DRM_MODE_DPMS_OFF));
848

849
	if (o->flags & TEST_MODESET && !(o->flags & TEST_RMFB)) {
850
		if (set_mode(o, 0 /* no fb */, 0, 0)) {
851 852
			fprintf(stderr, "failed to disable output: %s\n",
				strerror(errno));
853
			igt_fail(7);
854 855 856
		}
	}

857
	if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
Daniel Vetter's avatar
Daniel Vetter committed
858
		igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply)
859 860
		       == -EINVAL);

861
	if (do_flip && (o->flags & TEST_EINVAL) && !(o->flags & TEST_FB_BAD_TILING))
Daniel Vetter's avatar
Daniel Vetter committed
862
		igt_assert(do_page_flip(o, new_fb_id, true) == expected_einval);
863

864 865 866
	if (do_flip && (o->flags & TEST_HANG)) {
		gem_sync(drm_fd, handle);
		gem_close(drm_fd, handle);
867
		eat_error_state(o);
868 869
	}

870
	return completed_events;
871
}
872

873 874 875 876
static void update_state(struct event_state *es)
{
	es->last_received_ts = es->current_received_ts;
	es->last_ts = es->current_ts;
877
	es->last_seq = es->current_seq;
878 879 880
	es->count++;
}

881 882
static void update_all_state(struct test_output *o,
			     unsigned int completed_events)
883
{
884 885
	if (completed_events & EVENT_FLIP)
		update_state(&o->flip_state);
886 887 888

	if (completed_events & EVENT_VBLANK)
		update_state(&o->vblank_state);
Jesse Barnes's avatar
Jesse Barnes committed
889 890
}

891 892
static void connector_find_preferred_mode(uint32_t connector_id, int crtc_idx,
					  struct test_output *o)
Jesse Barnes's avatar
Jesse Barnes committed
893
{
894
	struct kmstest_connector_config config;
Jesse Barnes's avatar
Jesse Barnes committed
895

896 897
	if (kmstest_get_connector_config(drm_fd, connector_id, 1 << crtc_idx,
					 &config) < 0) {
898
		o->mode_valid = 0;
Jesse Barnes's avatar
Jesse Barnes committed
899 900 901
		return;
	}

902
	o->pipe = config.pipe;
903 904 905 906
	o->kconnector[0] = config.connector;
	o->kencoder[0] = config.encoder;
	o->_crtc[0] = config.crtc->crtc_id;
	o->kmode[0] = config.default_mode;
907
	o->mode_valid = 1;
908 909 910 911

	o->fb_width = o->kmode[0].hdisplay;
	o->fb_height = o->kmode[0].vdisplay;

Jesse Barnes's avatar
Jesse Barnes committed
912 913
}

Imre Deak's avatar
Imre Deak committed
914
static void paint_flip_mode(struct kmstest_fb *fb, bool odd_frame)
Jesse Barnes's avatar
Jesse Barnes committed
915
{
Imre Deak's avatar
Imre Deak committed
916 917 918 919 920
	cairo_t *cr = kmstest_get_cairo_ctx(drm_fd, fb);
	int width = fb->width;
	int height = fb->height;

	kmstest_paint_test_pattern(cr, width, height);
Jesse Barnes's avatar
Jesse Barnes committed
921

922 923 924 925
	if (odd_frame)
		cairo_rectangle(cr, width/4, height/2, width/4, height/8);
	else
		cairo_rectangle(cr, width/2, height/2, width/4, height/8);
Jesse Barnes's avatar
Jesse Barnes committed
926 927 928

	cairo_set_source_rgb(cr, 1, 1, 1);
	cairo_fill(cr);
Imre Deak's avatar
Imre Deak committed
929

Daniel Vetter's avatar
Daniel Vetter committed
930
	igt_assert(!cairo_status(cr));
Jesse Barnes's avatar
Jesse Barnes committed
931 932
}

933 934 935
static int
fb_is_bound(struct test_output *o, int fb)
{
936
	int n;
937

938 939
	for (n = 0; n < o->count; n++) {
		struct drm_mode_crtc mode;
940

941 942 943 944 945 946 947 948 949
		mode.crtc_id = o->_crtc[n];
		if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETCRTC, &mode))
			return 0;

		if (!mode.mode_valid || mode.fb_id != fb)
			return false;
	}

	return true;
950 951
}

952 953
static void check_final_state(struct test_output *o, struct event_state *es,
			      unsigned int ellapsed)
954
{
955 956
	if (es->count == 0) {
		fprintf(stderr, "no %s event received\n", es->name);
957
		igt_fail(12);
958 959
	}

960 961 962 963
	/* Verify we drop no frames, but only if it's not a TV encoder, since
	 * those use some funny fake timings behind userspace's back. */
	if (o->flags & TEST_CHECK_TS && !analog_tv_connector(o)) {
		int expected;
964
		int count = es->count;
965

966
		count *= es->seq_step;
967
		expected = ellapsed * o->kmode[0].vrefresh / (1000 * 1000);
968
		if (count < expected * 99/100) {
969
			fprintf(stderr, "dropped frames, expected %d, counted %d, encoder type %d\n",
970
				expected, count, o->kencoder[0]->encoder_type);
971
			igt_fail(3);
972 973 974 975
		}
	}
}

976 977 978 979 980
/*
 * Wait until at least one pending event completes. Return mask of completed
 * events.
 */
static unsigned int wait_for_events(struct test_output *o)
Jesse Barnes's avatar
Jesse Barnes committed
981
{
982 983 984
	drmEventContext evctx;
	struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
	fd_set fds;
985
	unsigned int event_mask;
Jesse Barnes's avatar
Jesse Barnes committed
986
	int ret;
987

988
	event_mask = o->pending_events;
Daniel Vetter's avatar
Daniel Vetter committed
989
	igt_assert(event_mask);
990

991 992
	memset(&evctx, 0, sizeof evctx);
	evctx.version = DRM_EVENT_CONTEXT_VERSION;
993
	evctx.vblank_handler = vblank_handler;
994 995 996
	evctx.page_flip_handler = page_flip_handler;

	/* make timeout lax with the dummy load */
997
	if (o->flags & (TEST_WITH_DUMMY_BCS | TEST_WITH_DUMMY_RCS))
998 999 1000 1001
		timeout.tv_sec *= 10;

	FD_ZERO(&fds);
	FD_SET(drm_fd, &fds);
1002 1003 1004
	do {
		ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout);
	} while (ret < 0 && errno == EINTR);
1005 1006 1007 1008

	if (ret <= 0) {
		fprintf(stderr, "select timed out or error (ret %d)\n",
				ret);
1009
		igt_fail(1);
1010 1011
	} else if (FD_ISSET(0, &fds)) {
		fprintf(stderr, "no fds active, breaking\n");
1012
		igt_fail(2);
1013 1014 1015
	}

	do_or_die(drmHandleEvent(drm_fd, &evctx));
1016 1017

	event_mask ^= o->pending_events;
Daniel Vetter's avatar
Daniel Vetter committed
1018
	igt_assert(event_mask);
1019 1020

	return event_mask;
1021 1022 1023 1024