compositor-drm: Don't page flip before a mode is set
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
This commit is contained in:
committed by
Kristian Høgsberg
parent
be7c4dd2a0
commit
95eb3a2eb4
+1
-1
@@ -133,7 +133,7 @@ if ENABLE_DRM_COMPOSITOR
|
|||||||
drm_backend = drm-backend.la
|
drm_backend = drm-backend.la
|
||||||
drm_backend_la_LDFLAGS = -module -avoid-version
|
drm_backend_la_LDFLAGS = -module -avoid-version
|
||||||
drm_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(DRM_COMPOSITOR_LIBS) \
|
drm_backend_la_LIBADD = $(COMPOSITOR_LIBS) $(DRM_COMPOSITOR_LIBS) \
|
||||||
../shared/libshared.la
|
../shared/libshared.la -lrt
|
||||||
drm_backend_la_CFLAGS = \
|
drm_backend_la_CFLAGS = \
|
||||||
$(COMPOSITOR_CFLAGS) \
|
$(COMPOSITOR_CFLAGS) \
|
||||||
$(DRM_COMPOSITOR_CFLAGS) \
|
$(DRM_COMPOSITOR_CFLAGS) \
|
||||||
|
|||||||
+27
-5
@@ -37,6 +37,7 @@
|
|||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
@@ -52,6 +53,10 @@
|
|||||||
#include "udev-seat.h"
|
#include "udev-seat.h"
|
||||||
#include "launcher-util.h"
|
#include "launcher-util.h"
|
||||||
|
|
||||||
|
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
|
||||||
|
#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
|
||||||
|
#endif
|
||||||
|
|
||||||
static int option_current_mode = 0;
|
static int option_current_mode = 0;
|
||||||
static char *output_name;
|
static char *output_name;
|
||||||
static char *output_mode;
|
static char *output_mode;
|
||||||
@@ -114,6 +119,8 @@ struct drm_compositor {
|
|||||||
int use_pixman;
|
int use_pixman;
|
||||||
|
|
||||||
uint32_t prev_state;
|
uint32_t prev_state;
|
||||||
|
|
||||||
|
clockid_t clock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_mode {
|
struct drm_mode {
|
||||||
@@ -663,10 +670,19 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
|
|||||||
output_base->compositor;
|
output_base->compositor;
|
||||||
uint32_t fb_id;
|
uint32_t fb_id;
|
||||||
|
|
||||||
if (output->current)
|
struct timespec ts;
|
||||||
fb_id = output->current->fb_id;
|
|
||||||
else
|
if (!output->current) {
|
||||||
fb_id = output->original_crtc->buffer_id;
|
/* 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,
|
if (drmModePageFlip(compositor->drm.fd, output->crtc_id, fb_id,
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
||||||
@@ -1184,7 +1200,8 @@ static int
|
|||||||
init_drm(struct drm_compositor *ec, struct udev_device *device)
|
init_drm(struct drm_compositor *ec, struct udev_device *device)
|
||||||
{
|
{
|
||||||
const char *filename, *sysnum;
|
const char *filename, *sysnum;
|
||||||
int fd;
|
uint64_t cap;
|
||||||
|
int fd, ret;
|
||||||
|
|
||||||
sysnum = udev_device_get_sysnum(device);
|
sysnum = udev_device_get_sysnum(device);
|
||||||
if (sysnum)
|
if (sysnum)
|
||||||
@@ -1207,6 +1224,11 @@ init_drm(struct drm_compositor *ec, struct udev_device *device)
|
|||||||
|
|
||||||
ec->drm.fd = fd;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user