compositor-drm: Don't page flip before a mode is set
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Tue, 7 May 2013 11:16:59 +0000 (14:16 +0300)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 14 May 2013 14:21:54 +0000 (10:21 -0400)
The function drm_output_start_repaint_loop() unconditionally issues a
page flip, even if the crtc for that output has not been enabled yet.
That causes the page flip to fail, and drm_output_repaint() is never
called.

Solve this by bypassing the initial page flip if the output needs a
mode set.

This has the caveat of affecting latency predictability for that first
frame and when a "driver" mode fullscreen surface causes a mode set.
However, on both cases the mode set would take an unpredictable amount
of time anyway.

https://bugs.freedesktop.org/show_bug.cgi?id=63812
https://bugs.freedesktop.org/show_bug.cgi?id=64183

src/Makefile.am
src/compositor-drm.c

index 1b55181..859f583 100644 (file)
@@ -133,7 +133,7 @@ if ENABLE_DRM_COMPOSITOR
 drm_backend = drm-backend.la
 drm_backend_la_LDFLAGS = -module -avoid-version
 drm_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(DRM_COMPOSITOR_LIBS) \
-       ../shared/libshared.la
+       ../shared/libshared.la -lrt
 drm_backend_la_CFLAGS =                                \
        $(COMPOSITOR_CFLAGS)                    \
        $(DRM_COMPOSITOR_CFLAGS)                \
index bb8ea46..9dce809 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/input.h>
 #include <assert.h>
 #include <sys/mman.h>
+#include <time.h>
 
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 #include "udev-seat.h"
 #include "launcher-util.h"
 
+#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
+#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
+#endif
+
 static int option_current_mode = 0;
 static char *output_name;
 static char *output_mode;
@@ -114,6 +119,8 @@ struct drm_compositor {
        int use_pixman;
 
        uint32_t prev_state;
+
+       clockid_t clock;
 };
 
 struct drm_mode {
@@ -663,10 +670,19 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
                output_base->compositor;
        uint32_t fb_id;
 
-       if (output->current)
-               fb_id = output->current->fb_id;
-       else
-               fb_id = output->original_crtc->buffer_id;
+       struct timespec ts;
+
+       if (!output->current) {
+               /* We can't page flip if there's no mode set */
+               uint32_t msec;
+
+               clock_gettime(compositor->clock, &ts);
+               msec = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+               weston_output_finish_frame(output_base, msec);
+               return;
+       }
+
+       fb_id = output->current->fb_id;
 
        if (drmModePageFlip(compositor->drm.fd, output->crtc_id, fb_id,
                            DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
@@ -1184,7 +1200,8 @@ static int
 init_drm(struct drm_compositor *ec, struct udev_device *device)
 {
        const char *filename, *sysnum;
-       int fd;
+       uint64_t cap;
+       int fd, ret;
 
        sysnum = udev_device_get_sysnum(device);
        if (sysnum)
@@ -1207,6 +1224,11 @@ init_drm(struct drm_compositor *ec, struct udev_device *device)
 
        ec->drm.fd = fd;
 
+       ret = drmGetCap(fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
+       if (ret == 0 && cap == 1)
+               ec->clock = CLOCK_MONOTONIC;
+       else
+               ec->clock = CLOCK_REALTIME;
 
        return 0;
 }