compositor: set presentation.presented flags
Change weston_output_finish_frame() signature so that backends are required to set the flags, that will be reported on the Presentation 'presented' event. This is meant for output-wide feedback flags. Flags that vary per wl_surface are subject for the following patch. All start_repaint_loop functions use the special private flag PRESENTATION_FEEDBACK_INVALID to mark, that this call of weston_output_finish_frame() cannot trigger the 'presented' event. If it does, we now hit an assert, and should then investigate why a fake update triggered Presentation feedback. DRM: Page flip is always vsync'd, and always gets the completion timestamp from the kernel which should correspond well to hardware. Completion is triggered by the kernel/hardware. Vblank handler is only used with the broken planes path, therefore do not report VSYNC, because we cannot guarantee all the planes updated at the same time. We cannot set the INVALID, because it would abort the compositor if the broken planes path was ever used. This is a hack that will get fixed with nuclear pageflip support in the future. fbdev: No vsync, update done by copy, no completion event from hardware, and completion time is totally fake. headless: No real output to update. RDP: Guessing that maybe no vsync, fake time, and copy make sense (pixels sent over network). Also no event that the pixels have been shown? RPI: Presumably Dispmanx updates are vsync'd. We get a completion event from the driver, but need to read the clock ourselves, so the completion time is somewhat unreliable. Zero-copy flag not implemented though it would be theoretically possible with EGL clients (zero-copy is a per-surface flag anyway, so in this patch). Wayland: No information how the host compositor is doing updates, so make a safe guess without assuming vsync or hardware completion event. While we do get some timestamp from the host compositor, it is not the completion time. Would need to hook to the Presentation extension of the host compositor to get more accurate flags. X11: No idea about vsync, completion event, or copying. Also the timestamp is a fake. Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> Reviewed-by: Mario Kleiner <mario.kleiner.de@gmail.com> Tested-by: Mario Kleiner <mario.kleiner.de@gmail.com> Acked-by: Mario Kleiner <mario.kleiner.de@gmail.com>
This commit is contained in:
parent
0de22a38e6
commit
363aa7bc76
|
@ -50,6 +50,7 @@
|
|||
#include "libinput-seat.h"
|
||||
#include "launcher-util.h"
|
||||
#include "vaapi-recorder.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
|
||||
#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
|
||||
|
@ -720,7 +721,8 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
|
|||
finish_frame:
|
||||
/* if we cannot page-flip, immediately finish frame */
|
||||
clock_gettime(compositor->base.presentation_clock, &ts);
|
||||
weston_output_finish_frame(output_base, &ts);
|
||||
weston_output_finish_frame(output_base, &ts,
|
||||
PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -741,6 +743,8 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
|
|||
struct drm_sprite *s = (struct drm_sprite *)data;
|
||||
struct drm_output *output = s->output;
|
||||
struct timespec ts;
|
||||
uint32_t flags = PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
|
||||
PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
|
||||
|
||||
drm_output_update_msc(output, frame);
|
||||
output->vblank_pending = 0;
|
||||
|
@ -752,7 +756,7 @@ vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
|
|||
if (!output->page_flip_pending) {
|
||||
ts.tv_sec = sec;
|
||||
ts.tv_nsec = usec * 1000;
|
||||
weston_output_finish_frame(&output->base, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,6 +769,9 @@ page_flip_handler(int fd, unsigned int frame,
|
|||
{
|
||||
struct drm_output *output = (struct drm_output *) data;
|
||||
struct timespec ts;
|
||||
uint32_t flags = PRESENTATION_FEEDBACK_KIND_VSYNC |
|
||||
PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
|
||||
PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
|
||||
|
||||
drm_output_update_msc(output, frame);
|
||||
|
||||
|
@ -784,7 +791,7 @@ page_flip_handler(int fd, unsigned int frame,
|
|||
else if (!output->vblank_pending) {
|
||||
ts.tv_sec = sec;
|
||||
ts.tv_nsec = usec * 1000;
|
||||
weston_output_finish_frame(&output->base, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, flags);
|
||||
|
||||
/* We can't call this from frame_notify, because the output's
|
||||
* repaint needed flag is cleared just after that */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "pixman-renderer.h"
|
||||
#include "libinput-seat.h"
|
||||
#include "gl-renderer.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
struct fbdev_compositor {
|
||||
struct weston_compositor base;
|
||||
|
@ -117,7 +118,7 @@ fbdev_output_start_repaint_loop(struct weston_output *output)
|
|||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -220,8 +221,10 @@ static int
|
|||
finish_frame_handler(void *data)
|
||||
{
|
||||
struct fbdev_output *output = data;
|
||||
struct timespec ts;
|
||||
|
||||
fbdev_output_start_repaint_loop(&output->base);
|
||||
clock_gettime(output->base.compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "compositor.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
struct headless_compositor {
|
||||
struct weston_compositor base;
|
||||
|
@ -58,13 +59,17 @@ headless_output_start_repaint_loop(struct weston_output *output)
|
|||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
finish_frame_handler(void *data)
|
||||
{
|
||||
headless_output_start_repaint_loop(data);
|
||||
struct headless_output *output = data;
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->base.compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@ rdp_output_start_repaint_loop(struct weston_output *output)
|
|||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -350,7 +350,11 @@ rdp_output_destroy(struct weston_output *output_base)
|
|||
static int
|
||||
finish_frame_handler(void *data)
|
||||
{
|
||||
rdp_output_start_repaint_loop(data);
|
||||
struct rdp_output *output = data;
|
||||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->base.compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "rpi-renderer.h"
|
||||
#include "launcher-util.h"
|
||||
#include "libinput-seat.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
#if 0
|
||||
#define DBG(...) \
|
||||
|
@ -215,8 +216,9 @@ rpi_output_start_repaint_loop(struct weston_output *output)
|
|||
{
|
||||
struct timespec ts;
|
||||
|
||||
/* XXX: do a phony dispmanx update and trigger on its completion? */
|
||||
clock_gettime(output->compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -250,10 +252,13 @@ static void
|
|||
rpi_output_update_complete(struct rpi_output *output,
|
||||
const struct timespec *stamp)
|
||||
{
|
||||
uint32_t flags = PRESENTATION_FEEDBACK_KIND_VSYNC |
|
||||
PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
|
||||
|
||||
DBG("frame update complete(%ld.%09ld)\n",
|
||||
(long)stamp->tv_sec, (long)stamp->tv_nsec);
|
||||
rpi_renderer_finish_frame(&output->base);
|
||||
weston_output_finish_frame(&output->base, stamp);
|
||||
weston_output_finish_frame(&output->base, stamp, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "../shared/os-compatibility.h"
|
||||
#include "../shared/cairo-util.h"
|
||||
#include "fullscreen-shell-client-protocol.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
#define WINDOW_TITLE "Weston Compositor"
|
||||
|
||||
|
@ -313,7 +314,7 @@ frame_done(void *data, struct wl_callback *callback, uint32_t time)
|
|||
/* XXX: use the presentation extension for proper timings */
|
||||
ts.tv_sec = time / 1000;
|
||||
ts.tv_nsec = (time % 1000) * 1000000;
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, 0);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener frame_listener = {
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "pixman-renderer.h"
|
||||
#include "../shared/config-parser.h"
|
||||
#include "../shared/image-loader.h"
|
||||
#include "presentation_timing-server-protocol.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
|
||||
|
||||
|
@ -341,7 +342,7 @@ x11_output_start_repaint_loop(struct weston_output *output)
|
|||
struct timespec ts;
|
||||
|
||||
clock_gettime(output->compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(output, &ts);
|
||||
weston_output_finish_frame(output, &ts, PRESENTATION_FEEDBACK_INVALID);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -450,8 +451,10 @@ static int
|
|||
finish_frame_handler(void *data)
|
||||
{
|
||||
struct x11_output *output = data;
|
||||
struct timespec ts;
|
||||
|
||||
x11_output_start_repaint_loop(&output->base);
|
||||
clock_gettime(output->base.compositor->presentation_clock, &ts);
|
||||
weston_output_finish_frame(&output->base, &ts, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -495,12 +495,12 @@ weston_presentation_feedback_present(
|
|||
struct weston_output *output,
|
||||
uint32_t refresh_nsec,
|
||||
const struct timespec *ts,
|
||||
uint64_t seq)
|
||||
uint64_t seq,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client(feedback->resource);
|
||||
struct wl_resource *o;
|
||||
uint64_t secs;
|
||||
uint32_t flags = 0;
|
||||
|
||||
wl_resource_for_each(o, &output->resource_list) {
|
||||
if (wl_resource_get_client(o) != client)
|
||||
|
@ -524,13 +524,18 @@ weston_presentation_feedback_present_list(struct wl_list *list,
|
|||
struct weston_output *output,
|
||||
uint32_t refresh_nsec,
|
||||
const struct timespec *ts,
|
||||
uint64_t seq)
|
||||
uint64_t seq,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct weston_presentation_feedback *feedback, *tmp;
|
||||
|
||||
assert(!(flags & PRESENTATION_FEEDBACK_INVALID) ||
|
||||
wl_list_empty(list));
|
||||
|
||||
wl_list_for_each_safe(feedback, tmp, list, link)
|
||||
weston_presentation_feedback_present(feedback, output,
|
||||
refresh_nsec, ts, seq);
|
||||
refresh_nsec, ts, seq,
|
||||
flags);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2083,7 +2088,8 @@ weston_compositor_read_input(int fd, uint32_t mask, void *data)
|
|||
|
||||
WL_EXPORT void
|
||||
weston_output_finish_frame(struct weston_output *output,
|
||||
const struct timespec *stamp)
|
||||
const struct timespec *stamp,
|
||||
uint32_t presented_flags)
|
||||
{
|
||||
struct weston_compositor *compositor = output->compositor;
|
||||
struct wl_event_loop *loop =
|
||||
|
@ -2097,7 +2103,8 @@ weston_output_finish_frame(struct weston_output *output,
|
|||
refresh_nsec = 1000000000000UL / output->current_mode->refresh;
|
||||
weston_presentation_feedback_present_list(&output->feedback_list,
|
||||
output, refresh_nsec, stamp,
|
||||
output->msc);
|
||||
output->msc,
|
||||
presented_flags);
|
||||
|
||||
output->frame_time = stamp->tv_sec * 1000 + stamp->tv_nsec / 1000000;
|
||||
|
||||
|
|
|
@ -1066,9 +1066,13 @@ weston_compositor_stack_plane(struct weston_compositor *ec,
|
|||
struct weston_plane *plane,
|
||||
struct weston_plane *above);
|
||||
|
||||
/* An invalid flag in presented_flags to catch logic errors. */
|
||||
#define PRESENTATION_FEEDBACK_INVALID (1U << 31)
|
||||
|
||||
void
|
||||
weston_output_finish_frame(struct weston_output *output,
|
||||
const struct timespec *stamp);
|
||||
const struct timespec *stamp,
|
||||
uint32_t presented_flags);
|
||||
void
|
||||
weston_output_schedule_repaint(struct weston_output *output);
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue