Fully implement tearing control

* 12to11.man: Document new protocol.
* compositor.h (enum _RenderMode): Add RenderModeVsyncAsync.
* picture_renderer.c (SwapBackBuffers, PresentToWindow)
(NotifyMsc): Handle new render mode.
* sync_source.c (GetWantedSynchronizationType): Use presentation
if the mode is VsyncAsync.
(NoteFrame): Set the vsync presentation mode to
RenderModeVsyncAsync.
This commit is contained in:
hujianwei 2022-11-24 06:12:06 +00:00
parent bd3d0a96e0
commit 151473bfb5
4 changed files with 37 additions and 6 deletions

View file

@ -272,6 +272,7 @@ zwp_pointer_constraints_v1 1
zwp_relative_pointer_manager 1 zwp_relative_pointer_manager 1
zwp_idle_inhibit_manager_v1 1 zwp_idle_inhibit_manager_v1 1
xdg_activation_v1 1 xdg_activation_v1 1
wp_tearing_control_manager_v1 1
.TE .TE
.PP .PP
When the protocol translator is built with EGL support, the following When the protocol translator is built with EGL support, the following

View file

@ -321,6 +321,9 @@ enum _RenderMode
RenderModeAsync, RenderModeAsync,
/* Synchronize rendering with the vertical refresh. */ /* Synchronize rendering with the vertical refresh. */
RenderModeVsync, RenderModeVsync,
/* Synchronize rendering with the vertical refresh but allow async
presentation if deadlines were missed. */
RenderModeVsyncAsync,
}; };
struct _RenderFuncs struct _RenderFuncs

View file

@ -847,6 +847,13 @@ SwapBackBuffers (PictureTarget *target, pixman_region32_t *damage)
back_buffer->pixmap, present_serial, back_buffer->pixmap, present_serial,
None, region, 0, 0, None, None, fence, None, region, 0, 0, None, None, fence,
PresentOptionAsync, 0, 0, 0, NULL, 0); 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 else
/* Present the pixmap synchronously at the next frame. */ /* Present the pixmap synchronously at the next frame. */
XPresentPixmap (compositor.display, target->window, XPresentPixmap (compositor.display, target->window,
@ -1927,6 +1934,12 @@ PresentToWindow (RenderTarget target, RenderBuffer source,
XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap, XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap,
++present_serial, None, region, 0, 0, None, None, None, ++present_serial, None, region, 0, 0, None, None, None,
PresentOptionAsync, 0, 0, 0, NULL, 0); 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 else
/* Present the pixmap at the next msc. */ /* Present the pixmap at the next msc. */
XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap, XPresentPixmap (compositor.display, pict_target->window, buffer->pixmap,
@ -1972,7 +1985,7 @@ NotifyMsc (RenderTarget target, RenderCompletionFunc callback,
pict_target = target.pointer; pict_target = target.pointer;
if (pict_target->render_mode != RenderModeVsync) if (pict_target->render_mode == RenderModeAsync)
return NULL; return NULL;
/* Allocate a presentation completion callback. */ /* Allocate a presentation completion callback. */
@ -1982,8 +1995,14 @@ NotifyMsc (RenderTarget target, RenderCompletionFunc callback,
callback_rec->id = ++present_serial; callback_rec->id = ++present_serial;
/* Ask for a notification. */ /* Ask for a notification. */
if (pict_target->render_mode == RenderModeVsync)
XPresentNotifyMSC (compositor.display, pict_target->window, XPresentNotifyMSC (compositor.display, pict_target->window,
present_serial, 0, 1, 0); present_serial, 0, 1, 0);
else
XPresentNotifyMSC (compositor.display, pict_target->window,
present_serial, pict_target->next_msc,
1, 0);
return callback_rec; return callback_rec;
} }

View file

@ -112,6 +112,13 @@ GetWantedSynchronizationType (SyncHelper *helper)
return SyncTypeFrameClock; 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. */ #ifdef AllowPresent /* TODO: make this work. */
/* Otherwise, use Present. */ /* Otherwise, use Present. */
return SyncTypePresent; return SyncTypePresent;
@ -307,10 +314,11 @@ NoteFrame (FrameMode mode, uint64_t id, void *data,
} }
else if (wanted == SyncTypePresent) else if (wanted == SyncTypePresent)
{ {
/* Since presentation is wanted, switch the renderer to /* Since presentation is wanted (which can currently only be
vsync mode. */ 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)) helper->last_msc + 1))
{ {
wanted = SyncTypeFrameClock; wanted = SyncTypeFrameClock;