flip_test: check whether wait_vblank fails when it should
[platform/upstream/intel-gpu-tools.git] / tests / flip_test.c
1 /*
2  * Copyright 2012 Intel Corporation
3  *   Jesse Barnes <jesse.barnes@intel.com>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 #include "config.h"
25
26 #include <assert.h>
27 #include <cairo.h>
28 #include <errno.h>
29 #include <math.h>
30 #include <stdint.h>
31 #include <unistd.h>
32 #include <sys/poll.h>
33 #include <sys/time.h>
34 #include <sys/mman.h>
35 #include <sys/ioctl.h>
36
37 #include "i915_drm.h"
38 #include "drmtest.h"
39 #include "testdisplay.h"
40 #include "intel_bufmgr.h"
41 #include "intel_batchbuffer.h"
42 #include "intel_gpu_tools.h"
43
44 #define TEST_DPMS               (1 << 0)
45 #define TEST_WITH_DUMMY_LOAD    (1 << 1)
46 #define TEST_PAN                (1 << 2)
47 #define TEST_MODESET            (1 << 3)
48 #define TEST_CHECK_TS           (1 << 4)
49 #define TEST_EBUSY              (1 << 5)
50 #define TEST_EINVAL             (1 << 6)
51 #define TEST_FLIP               (1 << 7)
52 #define TEST_VBLANK             (1 << 8)
53 #define TEST_VBLANK_BLOCK       (1 << 9)
54 #define TEST_VBLANK_ABSOLUTE    (1 << 10)
55
56 #define EVENT_FLIP              (1 << 0)
57 #define EVENT_VBLANK            (1 << 1)
58
59 drmModeRes *resources;
60 int drm_fd;
61 static drm_intel_bufmgr *bufmgr;
62 struct intel_batchbuffer *batch;
63 uint32_t devid;
64 int test_time = 3;
65
66 uint32_t *fb_ptr;
67
68 struct type_name {
69         int type;
70         const char *name;
71 };
72
73 struct event_state {
74         const char *name;
75
76         /*
77          * Event data for the last event that has already passed our check.
78          * Updated using the below current_* vars in update_state().
79          */
80         struct timeval last_ts;                 /* kernel reported timestamp */
81         struct timeval last_received_ts;        /* the moment we received it */
82         unsigned int last_seq;                  /* kernel reported seq. num */
83
84         /*
85          * Event data for for the current event that we just received and
86          * going to check for validity. Set in event_handler().
87          */
88         struct timeval current_ts;              /* kernel reported timestamp */
89         struct timeval current_received_ts;     /* the moment we received it */
90         unsigned int current_seq;               /* kernel reported seq. num */
91
92         int count;                              /* # of events of this type */
93
94         /* Step between the current and next 'target' sequence number. */
95         int seq_step;
96 };
97
98 struct test_output {
99         const char *test_name;
100         uint32_t id;
101         int mode_valid;
102         drmModeModeInfo mode;
103         drmModeEncoder *encoder;
104         drmModeConnector *connector;
105         int crtc;
106         int pipe;
107         int flags;
108         unsigned int current_fb_id;
109         unsigned int fb_width;
110         unsigned int fb_height;
111         unsigned int fb_ids[2];
112         struct kmstest_fb fb_info[2];
113
114         struct event_state flip_state;
115         struct event_state vblank_state;
116         unsigned int pending_events;
117 };
118
119 static void emit_dummy_load(struct test_output *o)
120 {
121         int i, limit;
122         drm_intel_bo *dummy_bo, *target_bo, *tmp_bo;
123         struct kmstest_fb *fb_info = &o->fb_info[o->current_fb_id];
124         unsigned pitch = fb_info->stride;
125
126         limit = intel_gen(devid) < 6 ? 500 : 5000;
127
128         dummy_bo = drm_intel_bo_alloc(bufmgr, "dummy_bo", fb_info->size, 4096);
129         assert(dummy_bo);
130         target_bo = gem_handle_to_libdrm_bo(bufmgr, drm_fd, "imported", fb_info->gem_handle);
131         assert(target_bo);
132
133         for (i = 0; i < limit; i++) {
134                 BEGIN_BATCH(8);
135                 OUT_BATCH(XY_SRC_COPY_BLT_CMD |
136                           XY_SRC_COPY_BLT_WRITE_ALPHA |
137                           XY_SRC_COPY_BLT_WRITE_RGB);
138                 OUT_BATCH((3 << 24) | /* 32 bits */
139                           (0xcc << 16) | /* copy ROP */
140                           pitch);
141                 OUT_BATCH(0 << 16 | 0);
142                 OUT_BATCH((o->mode.vdisplay) << 16 | (o->mode.hdisplay));
143                 OUT_RELOC_FENCED(dummy_bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
144                 OUT_BATCH(0 << 16 | 0);
145                 OUT_BATCH(pitch);
146                 OUT_RELOC_FENCED(target_bo, I915_GEM_DOMAIN_RENDER, 0, 0);
147                 ADVANCE_BATCH();
148
149                 if (IS_GEN6(devid) || IS_GEN7(devid)) {
150                         BEGIN_BATCH(3);
151                         OUT_BATCH(XY_SETUP_CLIP_BLT_CMD);
152                         OUT_BATCH(0);
153                         OUT_BATCH(0);
154                         ADVANCE_BATCH();
155                 }
156
157                 tmp_bo = dummy_bo;
158                 dummy_bo = target_bo;
159                 target_bo = tmp_bo;
160         }
161         intel_batchbuffer_flush(batch);
162
163         drm_intel_bo_unreference(dummy_bo);
164         drm_intel_bo_unreference(target_bo);
165 }
166
167 static int set_dpms(struct test_output *o, int mode)
168 {
169         int i, dpms = 0;
170
171         for (i = 0; i < o->connector->count_props; i++) {
172                 struct drm_mode_get_property prop;
173
174                 prop.prop_id = o->connector->props[i];
175                 prop.count_values = 0;
176                 prop.count_enum_blobs = 0;
177                 if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
178                         continue;
179
180                 if (strcmp(prop.name, "DPMS"))
181                         continue;
182
183                 dpms = prop.prop_id;
184                 break;
185         }
186         if (!dpms) {
187                 fprintf(stderr, "DPMS property not found on %d\n", o->id);
188                 errno = ENOENT;
189                 return -1;
190         }
191
192         return drmModeConnectorSetProperty(drm_fd, o->id, dpms, mode);
193 }
194
195 static void set_flag(unsigned int *v, unsigned int flag)
196 {
197         assert(!(*v & flag));
198         *v |= flag;
199 }
200
201 static void clear_flag(unsigned int *v, unsigned int flag)
202 {
203         assert(*v & flag);
204         *v &= ~flag;
205 }
206
207 static int do_page_flip(struct test_output *o, int fb_id)
208 {
209         int ret;
210
211         ret = drmModePageFlip(drm_fd, o->crtc, fb_id, DRM_MODE_PAGE_FLIP_EVENT,
212                                 o);
213         if (ret == 0)
214                 set_flag(&o->pending_events, EVENT_FLIP);
215
216         return ret;
217 }
218
219 struct vblank_reply {
220         unsigned int sequence;
221         struct timeval ts;
222 };
223
224 static int do_wait_for_vblank(struct test_output *o, int crtc_idx,
225                               int target_seq, struct vblank_reply *reply)
226 {
227         drmVBlank wait_vbl;
228         int ret;
229         unsigned crtc_idx_mask;
230         bool event = !(o->flags & TEST_VBLANK_BLOCK);
231
232         memset(&wait_vbl, 0, sizeof(wait_vbl));
233
234         crtc_idx_mask = crtc_idx << DRM_VBLANK_HIGH_CRTC_SHIFT;
235         assert(!(crtc_idx_mask & ~DRM_VBLANK_HIGH_CRTC_MASK));
236
237         wait_vbl.request.type = crtc_idx_mask;
238         if (o->flags & TEST_VBLANK_ABSOLUTE)
239                 wait_vbl.request.type |= DRM_VBLANK_ABSOLUTE;
240         else
241                 wait_vbl.request.type |= DRM_VBLANK_RELATIVE;
242         if (event) {
243                 wait_vbl.request.type |= DRM_VBLANK_EVENT;
244                 wait_vbl.request.signal = (unsigned long)o;
245         }
246         wait_vbl.request.sequence = target_seq;
247
248         ret = drmWaitVBlank(drm_fd, &wait_vbl);
249
250         if (ret == 0) {
251                 reply->ts.tv_sec = wait_vbl.reply.tval_sec;
252                 reply->ts.tv_usec = wait_vbl.reply.tval_usec;
253                 reply->sequence = wait_vbl.reply.sequence;
254
255                 if (event) {
256                         assert(!(o->pending_events & EVENT_VBLANK));
257                         o->pending_events |= EVENT_VBLANK;
258                 }
259         } else
260                 ret = -errno;
261
262         return ret;
263 }
264
265 static bool
266 analog_tv_connector(struct test_output *o)
267 {
268         uint32_t connector_type = o->connector->connector_type;
269
270         return connector_type == DRM_MODE_CONNECTOR_TV ||
271                 connector_type == DRM_MODE_CONNECTOR_9PinDIN ||
272                 connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
273                 connector_type == DRM_MODE_CONNECTOR_Composite;
274 }
275
276 static void event_handler(struct event_state *es, unsigned int frame,
277                           unsigned int sec, unsigned int usec)
278 {
279         gettimeofday(&es->current_received_ts, NULL);
280         es->current_ts.tv_sec = sec;
281         es->current_ts.tv_usec = usec;
282         es->current_seq = frame;
283 }
284
285 static void page_flip_handler(int fd, unsigned int frame, unsigned int sec,
286                               unsigned int usec, void *data)
287 {
288         struct test_output *o = data;
289
290         clear_flag(&o->pending_events, EVENT_FLIP);
291         event_handler(&o->flip_state, frame, sec, usec);
292 }
293
294 static void vblank_handler(int fd, unsigned int frame, unsigned int sec,
295                               unsigned int usec, void *data)
296 {
297         struct test_output *o = data;
298
299         clear_flag(&o->pending_events, EVENT_VBLANK);
300         event_handler(&o->vblank_state, frame, sec, usec);
301 }
302
303 static void check_state(struct test_output *o, struct event_state *es)
304 {
305         struct timeval diff;
306         double usec_interflip;
307
308         timersub(&es->current_ts, &es->current_received_ts, &diff);
309         if (diff.tv_sec > 0 || (diff.tv_sec == 0 && diff.tv_usec > 2000)) {
310                 fprintf(stderr, "%s ts delayed for too long: %is, %iusec\n",
311                         es->name, (int)diff.tv_sec, (int)diff.tv_usec);
312                 exit(5);
313         }
314
315         if (!timercmp(&es->last_received_ts, &es->current_ts, <)) {
316                 fprintf(stderr, "%s ts before the %s was issued!\n",
317                                 es->name, es->name);
318
319                 timersub(&es->current_ts, &es->last_received_ts, &diff);
320                 fprintf(stderr, "timerdiff %is, %ius\n",
321                         (int) diff.tv_sec, (int) diff.tv_usec);
322                 exit(6);
323         }
324
325         if (es->count == 0)
326                 return;
327
328         /* This bounding matches the one in DRM_IOCTL_WAIT_VBLANK. */
329         if (es->current_seq - (es->last_seq + es->seq_step) > 1UL << 23) {
330                 fprintf(stderr, "unexpected %s seq %u, should be >= %u\n",
331                         es->name, es->current_seq, es->last_seq + es->seq_step);
332                 exit(10);
333         }
334
335         if ((o->flags & TEST_CHECK_TS) && (!analog_tv_connector(o))) {
336                 timersub(&es->current_ts, &es->last_ts, &diff);
337                 usec_interflip = (double)es->seq_step /
338                                  ((double)o->mode.vrefresh) * 1000.0 * 1000.0;
339                 if (fabs((((double) diff.tv_usec) - usec_interflip) /
340                     usec_interflip) > 0.005) {
341                         fprintf(stderr, "inter-%s ts jitter: %is, %ius\n",
342                                 es->name,
343                                 (int) diff.tv_sec, (int) diff.tv_usec);
344                         /* atm this is way too easy to hit, thanks to the hpd
345                          * poll helper :( hence make it non-fatal for now */
346                         //exit(9);
347                 }
348
349                 if (es->current_seq != es->last_seq + es->seq_step) {
350                         fprintf(stderr, "unexpected %s seq %u, expected %u\n",
351                                         es->name, es->current_seq,
352                                         es->last_seq + es->seq_step);
353                         /* no exit, due to the same reason as above */
354                 }
355         }
356 }
357
358 static void check_all_state(struct test_output *o,
359                             unsigned int completed_events)
360 {
361         if (completed_events & EVENT_FLIP)
362                 check_state(o, &o->flip_state);
363         if (completed_events & EVENT_VBLANK)
364                 check_state(o, &o->vblank_state);
365 }
366
367 /* Return mask of completed events. */
368 static unsigned int run_test_step(struct test_output *o)
369 {
370         unsigned int new_fb_id;
371         /* for funny reasons page_flip returns -EBUSY on disabled crtcs ... */
372         int expected_einval = o->flags & TEST_MODESET ? -EBUSY : -EINVAL;
373         unsigned int completed_events = 0;
374         bool do_flip;
375         bool do_vblank;
376         struct vblank_reply vbl_reply;
377         unsigned int target_seq;
378
379         target_seq = o->vblank_state.seq_step;
380         if (o->flags & TEST_VBLANK_ABSOLUTE)
381                 target_seq += o->vblank_state.last_seq;
382
383         do_flip = (o->flags & TEST_FLIP) && !(o->pending_events & EVENT_FLIP);
384         do_vblank = (o->flags & TEST_VBLANK) &&
385                     !(o->pending_events & EVENT_VBLANK);
386
387         if (o->flags & TEST_WITH_DUMMY_LOAD)
388                 emit_dummy_load(o);
389
390
391         o->current_fb_id = !o->current_fb_id;
392         new_fb_id = o->fb_ids[o->current_fb_id];
393
394         if (do_flip && (o->flags & TEST_EINVAL) && o->flip_state.count > 0)
395                 assert(do_page_flip(o, new_fb_id) == expected_einval);
396
397         if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
398                 assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply)
399                        == -EINVAL);
400
401         if (o->flags & TEST_MODESET) {
402                 if (drmModeSetCrtc(drm_fd, o->crtc,
403                                    o->fb_ids[o->current_fb_id],
404                                    0, 0,
405                                    &o->id, 1, &o->mode)) {
406                         fprintf(stderr, "failed to restore output mode: %s\n",
407                                 strerror(errno));
408                         exit(7);
409                 }
410         }
411
412         if (o->flags & TEST_DPMS)
413                 do_or_die(set_dpms(o, DRM_MODE_DPMS_ON));
414
415         printf("."); fflush(stdout);
416
417         if (do_flip)
418                 do_or_die(do_page_flip(o, new_fb_id));
419
420         if (do_vblank) {
421                 do_or_die(do_wait_for_vblank(o, o->pipe, target_seq,
422                                              &vbl_reply));
423                 if (o->flags & TEST_VBLANK_BLOCK) {
424                         event_handler(&o->vblank_state, vbl_reply.sequence,
425                                       vbl_reply.ts.tv_sec,
426                                       vbl_reply.ts.tv_usec);
427                         completed_events = EVENT_VBLANK;
428                 }
429         }
430
431         if (do_flip && (o->flags & TEST_EBUSY))
432                 assert(do_page_flip(o, new_fb_id) == -EBUSY);
433
434         /* pan before the flip completes */
435         if (o->flags & TEST_PAN) {
436                 int count = do_flip ?
437                         o->flip_state.count : o->vblank_state.count;
438                 int x_ofs = count * 10 > o->mode.hdisplay ?
439                             o->mode.hdisplay : count * 10;
440
441                 if (drmModeSetCrtc(drm_fd, o->crtc, o->fb_ids[o->current_fb_id],
442                                    x_ofs, 0, &o->id, 1, &o->mode)) {
443                         fprintf(stderr, "failed to pan (%dx%d@%dHz): %s\n",
444                                 o->fb_width, o->fb_height,
445                                 o->mode.vrefresh, strerror(errno));
446                         exit(7);
447                 }
448         }
449
450         if (o->flags & TEST_DPMS)
451                 do_or_die(set_dpms(o, DRM_MODE_DPMS_OFF));
452
453         if (o->flags & TEST_MODESET) {
454                 if (drmModeSetCrtc(drm_fd, o->crtc,
455                                    0, /* no fb */
456                                    0, 0,
457                                    NULL, 0, NULL)) {
458                         fprintf(stderr, "failed to disable output: %s\n",
459                                 strerror(errno));
460                         exit(7);
461                 }
462         }
463
464         if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > 0)
465                 assert(do_wait_for_vblank(o, o->pipe, target_seq, &vbl_reply)
466                        == -EINVAL);
467
468         if (do_flip && (o->flags & TEST_EINVAL))
469                 assert(do_page_flip(o, new_fb_id) == expected_einval);
470
471         return completed_events;
472 }
473
474 static void update_state(struct event_state *es)
475 {
476         es->last_received_ts = es->current_received_ts;
477         es->last_ts = es->current_ts;
478         es->last_seq = es->current_seq;
479         es->count++;
480 }
481
482 static void update_all_state(struct test_output *o,
483                              unsigned int completed_events)
484 {
485         if (completed_events & EVENT_FLIP)
486                 update_state(&o->flip_state);
487
488         if (completed_events & EVENT_VBLANK)
489                 update_state(&o->vblank_state);
490 }
491
492 static void connector_find_preferred_mode(struct test_output *o, int crtc_id)
493 {
494         drmModeConnector *connector;
495         drmModeEncoder *encoder = NULL;
496         int i, j;
497
498         /* First, find the connector & mode */
499         o->mode_valid = 0;
500         o->crtc = 0;
501         connector = drmModeGetConnector(drm_fd, o->id);
502         assert(connector);
503
504         if (connector->connection != DRM_MODE_CONNECTED) {
505                 drmModeFreeConnector(connector);
506                 return;
507         }
508
509         if (!connector->count_modes) {
510                 fprintf(stderr, "connector %d has no modes\n", o->id);
511                 drmModeFreeConnector(connector);
512                 return;
513         }
514
515         if (connector->connector_id != o->id) {
516                 fprintf(stderr, "connector id doesn't match (%d != %d)\n",
517                         connector->connector_id, o->id);
518                 drmModeFreeConnector(connector);
519                 return;
520         }
521
522         for (j = 0; j < connector->count_modes; j++) {
523                 o->mode = connector->modes[j];
524                 if (o->mode.type & DRM_MODE_TYPE_PREFERRED) {
525                         o->mode_valid = 1;
526                         break;
527                 }
528         }
529
530         if (!o->mode_valid) {
531                 if (connector->count_modes > 0) {
532                         /* use the first mode as test mode */
533                         o->mode = connector->modes[0];
534                         o->mode_valid = 1;
535                 }
536                 else {
537                         fprintf(stderr, "failed to find any modes on connector %d\n",
538                                 o->id);
539                         return;
540                 }
541         }
542
543         /* Now get the encoder */
544         for (i = 0; i < connector->count_encoders; i++) {
545                 encoder = drmModeGetEncoder(drm_fd, connector->encoders[i]);
546
547                 if (!encoder) {
548                         fprintf(stderr, "could not get encoder %i: %s\n",
549                                 resources->encoders[i], strerror(errno));
550                         drmModeFreeEncoder(encoder);
551                         continue;
552                 }
553
554                 break;
555         }
556
557         o->encoder = encoder;
558
559         if (i == resources->count_encoders) {
560                 fprintf(stderr, "failed to find encoder\n");
561                 o->mode_valid = 0;
562                 return;
563         }
564
565         /* Find first CRTC not in use */
566         for (i = 0; i < resources->count_crtcs; i++) {
567                 if (resources->crtcs[i] != crtc_id)
568                         continue;
569                 if (resources->crtcs[i] &&
570                     (o->encoder->possible_crtcs & (1<<i))) {
571                         o->crtc = resources->crtcs[i];
572                         break;
573                 }
574         }
575
576         if (!o->crtc) {
577                 fprintf(stderr, "could not find requested crtc %d\n", crtc_id);
578                 o->mode_valid = 0;
579                 return;
580         }
581
582         o->connector = connector;
583 }
584
585 static void
586 paint_flip_mode(cairo_t *cr, int width, int height, void *priv)
587 {
588         bool odd_frame = (bool) priv;
589
590         if (odd_frame)
591                 cairo_rectangle(cr, width/4, height/2, width/4, height/8);
592         else
593                 cairo_rectangle(cr, width/2, height/2, width/4, height/8);
594
595         cairo_set_source_rgb(cr, 1, 1, 1);
596         cairo_fill(cr);
597 }
598
599 static int
600 fb_is_bound(struct test_output *o, int fb)
601 {
602         struct drm_mode_crtc mode;
603
604         mode.crtc_id = o->crtc;
605         if (drmIoctl(drm_fd, DRM_IOCTL_MODE_GETCRTC, &mode))
606                 return 0;
607
608         return mode.mode_valid && mode.fb_id == fb;
609 }
610
611 static void check_final_state(struct test_output *o, struct event_state *es,
612                               unsigned int ellapsed)
613 {
614         if (es->count == 0) {
615                 fprintf(stderr, "no %s event received\n", es->name);
616                 exit(12);
617         }
618
619         /* Verify we drop no frames, but only if it's not a TV encoder, since
620          * those use some funny fake timings behind userspace's back. */
621         if (o->flags & TEST_CHECK_TS && !analog_tv_connector(o)) {
622                 int expected;
623                 int count = es->count;
624
625                 count *= es->seq_step;
626                 expected = ellapsed * o->mode.vrefresh / (1000 * 1000);
627                 if (count < expected * 99/100) {
628                         fprintf(stderr, "dropped frames, expected %d, counted %d, encoder type %d\n",
629                                 expected, count, o->encoder->encoder_type);
630                         exit(3);
631                 }
632         }
633 }
634
635 /*
636  * Wait until at least one pending event completes. Return mask of completed
637  * events.
638  */
639 static unsigned int wait_for_events(struct test_output *o)
640 {
641         drmEventContext evctx;
642         struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
643         fd_set fds;
644         unsigned int event_mask;
645         int ret;
646
647         event_mask = o->pending_events;
648         assert(event_mask);
649
650         memset(&evctx, 0, sizeof evctx);
651         evctx.version = DRM_EVENT_CONTEXT_VERSION;
652         evctx.vblank_handler = vblank_handler;
653         evctx.page_flip_handler = page_flip_handler;
654
655         /* make timeout lax with the dummy load */
656         if (o->flags & TEST_WITH_DUMMY_LOAD)
657                 timeout.tv_sec *= 10;
658
659         FD_ZERO(&fds);
660         FD_SET(0, &fds);
661         FD_SET(drm_fd, &fds);
662         ret = select(drm_fd + 1, &fds, NULL, NULL, &timeout);
663
664         if (ret <= 0) {
665                 fprintf(stderr, "select timed out or error (ret %d)\n",
666                                 ret);
667                 exit(1);
668         } else if (FD_ISSET(0, &fds)) {
669                 fprintf(stderr, "no fds active, breaking\n");
670                 exit(2);
671         }
672
673         do_or_die(drmHandleEvent(drm_fd, &evctx));
674
675         event_mask ^= o->pending_events;
676         assert(event_mask);
677
678         return event_mask;
679 }
680
681 /* Returned the ellapsed time in us */
682 static unsigned event_loop(struct test_output *o, unsigned duration_sec)
683 {
684         struct timeval start, end;
685         struct timeval tv_dur;
686
687         gettimeofday(&start, NULL);
688         end.tv_sec = start.tv_sec + duration_sec;
689         end.tv_usec = start.tv_usec;
690
691         while (1) {
692                 struct timeval now;
693                 unsigned int completed_events;
694
695                 completed_events = run_test_step(o);
696                 if (o->pending_events)
697                         completed_events |= wait_for_events(o);
698                 check_all_state(o, completed_events);
699                 update_all_state(o, completed_events);
700
701                 gettimeofday(&now, NULL);
702                 if (!timercmp(&now, &end, <))
703                         break;
704         }
705
706         gettimeofday(&end, NULL);
707         timersub(&end, &start, &tv_dur);
708
709         /* Flush any remaining events */
710         if (o->pending_events)
711                 wait_for_events(o);
712
713         return tv_dur.tv_sec * 1000 * 1000 + tv_dur.tv_usec;
714 }
715
716 static void run_test_on_crtc(struct test_output *o, int crtc, int duration)
717 {
718         int bpp = 32, depth = 24;
719         unsigned ellapsed;
720
721         connector_find_preferred_mode(o, crtc);
722         if (!o->mode_valid)
723                 return;
724
725         fprintf(stdout, "Beginning %s on crtc %d, connector %d\n",
726                 o->test_name, crtc, o->id);
727
728         o->fb_width = o->mode.hdisplay;
729         o->fb_height = o->mode.vdisplay;
730
731         if (o->flags & TEST_PAN)
732                 o->fb_width *= 2;
733
734         o->fb_ids[0] = kmstest_create_fb(drm_fd, o->fb_width, o->fb_height, bpp,
735                                          depth, false, &o->fb_info[0],
736                                          paint_flip_mode, (void *)false);
737         o->fb_ids[1] = kmstest_create_fb(drm_fd, o->fb_width, o->fb_height, bpp,
738                                          depth, false, &o->fb_info[1],
739                                          paint_flip_mode, (void *)true);
740
741         if (!o->fb_ids[0] || !o->fb_ids[1]) {
742                 fprintf(stderr, "failed to create fbs\n");
743                 exit(3);
744         }
745
746         kmstest_dump_mode(&o->mode);
747         if (drmModeSetCrtc(drm_fd, o->crtc, o->fb_ids[0], 0, 0,
748                            &o->id, 1, &o->mode)) {
749                 fprintf(stderr, "failed to set mode (%dx%d@%dHz): %s\n",
750                         o->fb_width, o->fb_height, o->mode.vrefresh,
751                         strerror(errno));
752                 exit(3);
753         }
754         assert(fb_is_bound(o, o->fb_ids[0]));
755
756         /* quiescent the hw a bit so ensure we don't miss a single frame */
757         if (o->flags & TEST_CHECK_TS)
758                 sleep(1);
759
760         gettimeofday(&o->flip_state.last_ts, NULL);
761         gettimeofday(&o->vblank_state.last_ts, NULL);
762
763         if (do_page_flip(o, o->fb_ids[1])) {
764                 fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
765                 exit(4);
766         }
767         wait_for_events(o);
768
769         o->current_fb_id = 1;
770         o->flip_state.seq_step = 1;
771         if (o->flags & TEST_VBLANK_ABSOLUTE)
772                 o->vblank_state.seq_step = 5;
773         else
774                 o->vblank_state.seq_step = 1;
775
776         ellapsed = event_loop(o, duration);
777
778         if (o->flags & TEST_FLIP)
779                 check_final_state(o, &o->flip_state, ellapsed);
780         if (o->flags & TEST_VBLANK)
781                 check_final_state(o, &o->vblank_state, ellapsed);
782
783         fprintf(stdout, "\n%s on crtc %d, connector %d: PASSED\n\n",
784                 o->test_name, crtc, o->id);
785
786         kmstest_remove_fb(drm_fd, o->fb_ids[1]);
787         kmstest_remove_fb(drm_fd, o->fb_ids[0]);
788
789         drmModeFreeEncoder(o->encoder);
790         drmModeFreeConnector(o->connector);
791 }
792
793 static int get_pipe_from_crtc_id(int crtc_id)
794 {
795         struct drm_i915_get_pipe_from_crtc_id pfci;
796         int ret;
797
798         memset(&pfci, 0, sizeof(pfci));
799         pfci.crtc_id = crtc_id;
800         ret = drmIoctl(drm_fd, DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID, &pfci);
801         assert(ret == 0);
802
803         return pfci.pipe;
804 }
805
806 static int run_test(int duration, int flags, const char *test_name)
807 {
808         struct test_output o;
809         int c, i;
810
811         resources = drmModeGetResources(drm_fd);
812         if (!resources) {
813                 fprintf(stderr, "drmModeGetResources failed: %s\n",
814                         strerror(errno));
815                 exit(5);
816         }
817
818         /* Find any connected displays */
819         for (c = 0; c < resources->count_connectors; c++) {
820                 for (i = 0; i < resources->count_crtcs; i++) {
821                         int crtc;
822
823                         memset(&o, 0, sizeof(o));
824                         o.test_name = test_name;
825                         o.id = resources->connectors[c];
826                         o.flags = flags;
827                         o.flip_state.name = "flip";
828                         o.vblank_state.name = "vblank";
829                         crtc = resources->crtcs[i];
830                         o.pipe = get_pipe_from_crtc_id(crtc);
831
832                         run_test_on_crtc(&o, crtc, duration);
833                 }
834         }
835
836         drmModeFreeResources(resources);
837         return 1;
838 }
839
840 int main(int argc, char **argv)
841 {
842         struct {
843                 int duration;
844                 int flags;
845                 const char *name;
846         } tests[] = {
847                 { 15, TEST_VBLANK | TEST_CHECK_TS, "wf-vblank" },
848                 { 15, TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_CHECK_TS,
849                                         "blocking wf-vblank" },
850                 { 5,  TEST_VBLANK | TEST_VBLANK_ABSOLUTE,
851                                         "absolute wf-vblank" },
852                 { 5,  TEST_VBLANK | TEST_VBLANK_BLOCK | TEST_VBLANK_ABSOLUTE,
853                                         "blocking absolute wf-vblank" },
854                 { 30,  TEST_VBLANK | TEST_DPMS | TEST_EINVAL, "wf-vblank vs dpms" },
855                 { 30,  TEST_VBLANK | TEST_DPMS | TEST_WITH_DUMMY_LOAD,
856                                         "delayed wf-vblank vs dpms" },
857                 { 30,  TEST_VBLANK | TEST_MODESET | TEST_EINVAL, "wf-vblank vs modeset" },
858                 { 30,  TEST_VBLANK | TEST_MODESET | TEST_WITH_DUMMY_LOAD,
859                                         "delayed wf-vblank vs modeset" },
860
861                 { 15, TEST_FLIP | TEST_CHECK_TS | TEST_EBUSY , "plain flip" },
862                 { 30, TEST_FLIP | TEST_DPMS | TEST_EINVAL, "flip vs dpms" },
863                 { 30, TEST_FLIP | TEST_DPMS | TEST_WITH_DUMMY_LOAD, "delayed flip vs dpms" },
864                 { 5,  TEST_FLIP | TEST_PAN, "flip vs panning" },
865                 { 30, TEST_FLIP | TEST_PAN | TEST_WITH_DUMMY_LOAD, "delayed flip vs panning" },
866                 { 30, TEST_FLIP | TEST_MODESET | TEST_EINVAL, "flip vs modeset" },
867                 { 30, TEST_FLIP | TEST_MODESET | TEST_WITH_DUMMY_LOAD, "delayed flip vs modeset" },
868
869                 { 5, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_ABSOLUTE |
870                       TEST_CHECK_TS, "flip vs absolute wf-vblank" },
871                 { 5, TEST_FLIP | TEST_VBLANK | TEST_CHECK_TS,
872                                         "flip vs wf-vblank" },
873                 { 5, TEST_FLIP | TEST_VBLANK | TEST_VBLANK_BLOCK |
874                         TEST_CHECK_TS, "flip vs blocking wf-vblank" },
875         };
876         int i;
877
878         drm_fd = drm_open_any();
879
880         bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 4096);
881         devid = intel_get_drm_devid(drm_fd);
882         batch = intel_batchbuffer_alloc(bufmgr, devid);
883
884         for (i = 0; i < sizeof(tests) / sizeof (tests[0]); i++) {
885                 printf("running testcase: %s\n", tests[i].name);
886                 run_test(tests[i].duration, tests[i].flags, tests[i].name);
887         }
888
889         close(drm_fd);
890
891         return 0;
892 }