diff --git a/12to11.man b/12to11.man index eb788fa..d038d02 100644 --- a/12to11.man +++ b/12to11.man @@ -272,6 +272,7 @@ zwp_pointer_constraints_v1 1 zwp_relative_pointer_manager 1 zwp_idle_inhibit_manager_v1 1 xdg_activation_v1 1 +wp_tearing_control_manager_v1 1 .TE .PP When the protocol translator is built with EGL support, the following diff --git a/compositor.h b/compositor.h index d000c0f..e8468e1 100644 --- a/compositor.h +++ b/compositor.h @@ -321,6 +321,9 @@ enum _RenderMode RenderModeAsync, /* Synchronize rendering with the vertical refresh. */ RenderModeVsync, + /* Synchronize rendering with the vertical refresh but allow async + presentation if deadlines were missed. */ + RenderModeVsyncAsync, }; struct _RenderFuncs diff --git a/picture_renderer.c b/picture_renderer.c index c2d5e14..da350da 100644 --- a/picture_renderer.c +++ b/picture_renderer.c @@ -847,6 +847,13 @@ SwapBackBuffers (PictureTarget *target, pixman_region32_t *damage) back_buffer->pixmap, present_serial, None, region, 0, 0, None, None, fence, PresentOptionAsync, 0, 0, 0, NULL, 0); + else if (target->render_mode == RenderModeVsyncAsync) + /* Present the pixmap asynchronously at the next frame. */ + XPresentPixmap (compositor.display, target->window, + back_buffer->pixmap, present_serial, + None, region, 0, 0, None, None, fence, + PresentOptionAsync, target->next_msc, + 1, 0, NULL, 0); else /* Present the pixmap synchronously at the next frame. */ XPresentPixmap (compositor.display, target->window, @@ -1927,6 +1934,12 @@ PresentToWindow (RenderTarget target, RenderBuffer source, XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap, ++present_serial, None, region, 0, 0, None, None, None, PresentOptionAsync, 0, 0, 0, NULL, 0); + else if (pict_target->render_mode == RenderModeVsyncAsync) + /* Present the pixmap at the next msc if possible. Otherwise, + present the pixmap asynchronously. */ + XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap, + ++present_serial, None, region, 0, 0, None, None, None, + PresentOptionAsync, pict_target->next_msc, 1, 0, NULL, 0); else /* Present the pixmap at the next msc. */ XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap, @@ -1972,7 +1985,7 @@ NotifyMsc (RenderTarget target, RenderCompletionFunc callback, pict_target = target.pointer; - if (pict_target->render_mode != RenderModeVsync) + if (pict_target->render_mode == RenderModeAsync) return NULL; /* Allocate a presentation completion callback. */ @@ -1982,8 +1995,14 @@ NotifyMsc (RenderTarget target, RenderCompletionFunc callback, callback_rec->id = ++present_serial; /* Ask for a notification. */ - XPresentNotifyMSC (compositor.display, pict_target->window, - present_serial, 0, 1, 0); + if (pict_target->render_mode == RenderModeVsync) + XPresentNotifyMSC (compositor.display, pict_target->window, + present_serial, 0, 1, 0); + else + XPresentNotifyMSC (compositor.display, pict_target->window, + present_serial, pict_target->next_msc, + 1, 0); + return callback_rec; } diff --git a/sync_source.c b/sync_source.c index 5a1a661..3bef5dc 100644 --- a/sync_source.c +++ b/sync_source.c @@ -112,6 +112,13 @@ GetWantedSynchronizationType (SyncHelper *helper) return SyncTypeFrameClock; } + /* If tearing is allowed, then use present targeting the next + frame. */ + if (helper->role->surface + && (helper->role->surface->current_state.presentation_hint + == PresentationHintAsync)) + return SyncTypePresent; + #ifdef AllowPresent /* TODO: make this work. */ /* Otherwise, use Present. */ return SyncTypePresent; @@ -307,10 +314,11 @@ NoteFrame (FrameMode mode, uint64_t id, void *data, } else if (wanted == SyncTypePresent) { - /* Since presentation is wanted, switch the renderer to - vsync mode. */ + /* Since presentation is wanted (which can currently only be + due to the client having requested a presentation hint of + "async"), switch the renderer to vsync-async mode. */ - if (!RenderSetRenderMode (helper->target, RenderModeVsync, + if (!RenderSetRenderMode (helper->target, RenderModeVsyncAsync, helper->last_msc + 1)) { wanted = SyncTypeFrameClock;