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_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

View file

@ -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

View file

@ -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;
}

View file

@ -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;