forked from 12to11/12to11
Add tearing control protocol
* 12to11-test.xml (test_surface) <committed>: New event. * 12to11.c (XLMain): Initialize tearing control. * Imakefile (SRCS, OBJS): Add tearing_control.c/.o. (tearing-control-v1): New scanner target. * compositor.h (enum _PresentationHint): New enum. (struct _State): Add fields for tearing control. (enum _ClientDataType): Add tearing control type. * surface.c (SavePendingState, InternalCommit1): Handle presentation hints. * test.c (Commit): Send new committed event. * tests/Imakefile (OBJS16, SRCS16): Add tearing_control_test.c/tearing_control_test.o. (PROGRAMS): Add tearing_control_test. (tearing-control-v1): New scanner target. * tests/buffer_test.c (test_names): Fix typos. * tests/run_tests.sh (standard_tests): Add tearing_control_test. * tests/svnignore.txt: Add tearing_control_test. * xdg_surface.c (UpdateFrameRefreshPrediction): Return whether or not refresh prediction is on. (MaybeRunLateFrame): Don't clear StateLateFrame until after SubcompositorUpdate. (WasFrameQueued): New function. (NoteFrame): If a frame was queued and async presentation was requested, present now.
This commit is contained in:
parent
4c7b4a2c5a
commit
ed9a704e69
11 changed files with 124 additions and 26 deletions
|
@ -178,10 +178,10 @@
|
|||
|
||||
<event name="activated">
|
||||
<description summary="role activated">
|
||||
The activated is sent when the xdg_activation protocol causes
|
||||
the surface associated with the role to be activated. Its
|
||||
parameters constitute the timestamp at which the activation
|
||||
occurred.
|
||||
The activated event is sent when the xdg_activation protocol
|
||||
causes the surface associated with the role to be activated.
|
||||
Its parameters constitute the timestamp at which the
|
||||
activation occurred.
|
||||
|
||||
If the surface that created the activation token used to
|
||||
activate this test surface belongs to the same client that
|
||||
|
@ -194,6 +194,20 @@
|
|||
<arg name="activator_surface" type="object" interface="wl_surface"
|
||||
allow-null="true"/>
|
||||
</event>
|
||||
|
||||
<event name="committed">
|
||||
<description summary="commit happened">
|
||||
The committed event is sent immediately after the role is
|
||||
committed, and contains some information about what choices
|
||||
were taken by the protocol translator during presentation.
|
||||
|
||||
presentation_hint is the presentation hint used by the
|
||||
protocol translator during drawing. Its value is that of the
|
||||
enumerator used internally, where 1 means async and 0 means
|
||||
vsync.
|
||||
</description>
|
||||
<arg name="presentation_hint" type="uint"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="test_scale_lock" version="1">
|
||||
|
|
1
12to11.c
1
12to11.c
|
@ -249,6 +249,7 @@ XLMain (int argc, char **argv)
|
|||
XLInitIdleInhibit ();
|
||||
XLInitPointerGestures ();
|
||||
XLInitXdgActivation ();
|
||||
XLInitTearingControl ();
|
||||
XLInitTest ();
|
||||
|
||||
/* This has to come after the rest of the initialization. */
|
||||
|
|
|
@ -18,8 +18,8 @@ MakeSubdirs($(SUBDIRS))
|
|||
DependSubdirs($(SUBDIRS))
|
||||
#endif
|
||||
|
||||
SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c surface.c region.c shm.c atoms.c subcompositor.c positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c data_device.c xdg_popup.c dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c primary_selection.c renderer.c picture_renderer.c explicit_synchronization.c transform.c wp_viewporter.c decoration.c text_input.c single_pixel_buffer.c drm_lease.c pointer_constraints.c time.c relative_pointer.c keyboard_shortcuts_inhibit.c idle_inhibit.c process.c fence_ring.c pointer_gestures.c test.c buffer_release.c xdg_activation.c
|
||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o surface.o region.o shm.o atoms.o subcompositor.o positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o data_device.o xdg_popup.o dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o primary_selection.o renderer.o picture_renderer.o explicit_synchronization.o transform.o wp_viewporter.o decoration.o text_input.o single_pixel_buffer.o drm_lease.o pointer_constraints.o time.o relative_pointer.o keyboard_shortcuts_inhibit.o idle_inhibit.o process.o fence_ring.o pointer_gestures.o test.o buffer_release.o xdg_activation.o
|
||||
SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c surface.c region.c shm.c atoms.c subcompositor.c positioner.c xdg_wm.c xdg_surface.c xdg_toplevel.c frame_clock.c xerror.c ewmh.c timer.c subsurface.c seat.c data_device.c xdg_popup.c dmabuf.c buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c primary_selection.c renderer.c picture_renderer.c explicit_synchronization.c transform.c wp_viewporter.c decoration.c text_input.c single_pixel_buffer.c drm_lease.c pointer_constraints.c time.c relative_pointer.c keyboard_shortcuts_inhibit.c idle_inhibit.c process.c fence_ring.c pointer_gestures.c test.c buffer_release.c xdg_activation.c tearing_control.c
|
||||
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o surface.o region.o shm.o atoms.o subcompositor.o positioner.o xdg_wm.o xdg_surface.o xdg_toplevel.o frame_clock.o xerror.o ewmh.o timer.o subsurface.o seat.o data_device.o xdg_popup.o dmabuf.o buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o primary_selection.o renderer.o picture_renderer.o explicit_synchronization.o transform.o wp_viewporter.o decoration.o text_input.o single_pixel_buffer.o drm_lease.o pointer_constraints.o time.o relative_pointer.o keyboard_shortcuts_inhibit.o idle_inhibit.o process.o fence_ring.o pointer_gestures.o test.o buffer_release.o xdg_activation.o tearing_control.o
|
||||
GENHEADERS = transfer_atoms.h drm_modifiers.h
|
||||
HEADER = $(GENHEADERS) compositor.h
|
||||
|
||||
|
@ -106,6 +106,7 @@ ScannerTarget(idle-inhibit-unstable-v1)
|
|||
ScannerTarget(pointer-gestures-unstable-v1)
|
||||
ScannerTarget(12to11-test)
|
||||
ScannerTarget(xdg-activation-v1)
|
||||
ScannerTarget(tearing-control-v1)
|
||||
|
||||
/* Make seat.o depend on test_seat.c, as it includes that. Both files
|
||||
are rather special. */
|
||||
|
|
40
compositor.h
40
compositor.h
|
@ -876,6 +876,7 @@ typedef struct _State State;
|
|||
typedef struct _FrameCallback FrameCallback;
|
||||
typedef enum _RoleType RoleType;
|
||||
typedef enum _FocusMode FocusMode;
|
||||
typedef enum _PresentationHint PresentationHint;
|
||||
|
||||
enum _FocusMode
|
||||
{
|
||||
|
@ -901,24 +902,31 @@ enum _RoleType
|
|||
|
||||
enum
|
||||
{
|
||||
PendingNone = 0,
|
||||
PendingOpaqueRegion = 1,
|
||||
PendingInputRegion = (1 << 2),
|
||||
PendingDamage = (1 << 3),
|
||||
PendingSurfaceDamage = (1 << 4),
|
||||
PendingBuffer = (1 << 5),
|
||||
PendingFrameCallbacks = (1 << 6),
|
||||
PendingBufferScale = (1 << 7),
|
||||
PendingAttachments = (1 << 8),
|
||||
PendingViewportSrc = (1 << 9),
|
||||
PendingViewportDest = (1 << 10),
|
||||
PendingBufferTransform = (1 << 11),
|
||||
PendingNone = 0,
|
||||
PendingOpaqueRegion = 1,
|
||||
PendingInputRegion = (1 << 2),
|
||||
PendingDamage = (1 << 3),
|
||||
PendingSurfaceDamage = (1 << 4),
|
||||
PendingBuffer = (1 << 5),
|
||||
PendingFrameCallbacks = (1 << 6),
|
||||
PendingBufferScale = (1 << 7),
|
||||
PendingAttachments = (1 << 8),
|
||||
PendingViewportSrc = (1 << 9),
|
||||
PendingViewportDest = (1 << 10),
|
||||
PendingBufferTransform = (1 << 11),
|
||||
PendingPresentationHint = (1 << 12),
|
||||
|
||||
/* Flags here are stored in `pending' of the current state for
|
||||
space reasons. */
|
||||
BufferAlreadyReleased = (1 << 19),
|
||||
};
|
||||
|
||||
enum _PresentationHint
|
||||
{
|
||||
PresentationHintVsync,
|
||||
PresentationHintAsync,
|
||||
};
|
||||
|
||||
struct _FrameCallback
|
||||
{
|
||||
/* The next and last callbacks. */
|
||||
|
@ -968,6 +976,9 @@ struct _State
|
|||
|
||||
/* Viewport source rectangle. */
|
||||
double src_x, src_y, src_width, src_height;
|
||||
|
||||
/* The presentation hint. Defaults to PresentationHintVsync. */
|
||||
PresentationHint presentation_hint;
|
||||
};
|
||||
|
||||
typedef enum _ClientDataType ClientDataType;
|
||||
|
@ -987,6 +998,7 @@ enum _ClientDataType
|
|||
IdleInhibitData,
|
||||
MaxClientData,
|
||||
XdgActivationData,
|
||||
TearingControlData,
|
||||
};
|
||||
|
||||
struct _DestroyCallback
|
||||
|
@ -1889,6 +1901,10 @@ extern void XLGetTestSeat (struct wl_client *, struct wl_resource *,
|
|||
|
||||
extern void XLInitXdgActivation (void);
|
||||
|
||||
/* Defined in tearing_control.c. */
|
||||
|
||||
extern void XLInitTearingControl (void);
|
||||
|
||||
/* Utility functions that don't belong in a specific file. */
|
||||
|
||||
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])
|
||||
|
|
|
@ -917,6 +917,10 @@ SavePendingState (Surface *surface)
|
|||
pixman_region32_copy (&surface->cached_state.opaque,
|
||||
&surface->pending_state.opaque);
|
||||
|
||||
if (surface->pending_state.pending & PendingPresentationHint)
|
||||
surface->cached_state.presentation_hint
|
||||
= surface->pending_state.presentation_hint;
|
||||
|
||||
if (surface->pending_state.pending & PendingBufferScale)
|
||||
surface->cached_state.buffer_scale
|
||||
= surface->pending_state.buffer_scale;
|
||||
|
@ -1052,6 +1056,10 @@ InternalCommit1 (Surface *surface, State *pending)
|
|||
}
|
||||
}
|
||||
|
||||
if (pending->pending & PendingPresentationHint)
|
||||
surface->current_state.presentation_hint
|
||||
= pending->presentation_hint;
|
||||
|
||||
if (pending->pending & PendingBufferScale)
|
||||
{
|
||||
surface->current_state.buffer_scale = pending->buffer_scale;
|
||||
|
|
5
test.c
5
test.c
|
@ -226,6 +226,11 @@ Commit (Surface *surface, Role *role)
|
|||
mapped. */
|
||||
if (test->flags & IsSurfaceMapped)
|
||||
SubcompositorUpdate (test->subcompositor);
|
||||
|
||||
/* And send the presentation hint. */
|
||||
if (test->role.resource)
|
||||
test_surface_send_committed (test->role.resource,
|
||||
surface->current_state.presentation_hint);
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
|
|
@ -28,6 +28,7 @@ ScannerTarget(viewporter)
|
|||
ScannerTarget(linux-dmabuf-unstable-v1)
|
||||
ScannerTarget(xdg-activation-v1)
|
||||
ScannerTarget(single-pixel-buffer-v1)
|
||||
ScannerTarget(tearing-control-v1)
|
||||
|
||||
/* Not actually a test. */
|
||||
SRCS1 = $(COMMONSRCS) imgview.c
|
||||
|
@ -60,10 +61,25 @@ ScannerTarget(single-pixel-buffer-v1)
|
|||
OBJS14 = $(COMMONSRCS) single_pixel_buffer_test.o
|
||||
SRCS15 = $(COMMONSRCS) buffer_test.c
|
||||
OBJS15 = $(COMMONSRCS) buffer_test.o
|
||||
PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple xdg_activation_test single_pixel_buffer_test buffer_test
|
||||
SRCS16 = $(COMMONSRCS) tearing_control_test.c
|
||||
OBJS16 = $(COMMONSRCS) tearing_control_test.o
|
||||
PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test seat_test dmabuf_test select_test select_helper select_helper_multiple xdg_activation_test single_pixel_buffer_test buffer_test tearing_control_test
|
||||
|
||||
/* Make all objects depend on HEADER. */
|
||||
$(OBJS1): $(HEADER)
|
||||
$(OBJS2): $(HEADER)
|
||||
$(OBJS3): $(HEADER)
|
||||
$(OBJS4): $(HEADER)
|
||||
$(OBJS5): $(HEADER)
|
||||
$(OBJS6): $(HEADER)
|
||||
$(OBJS7): $(HEADER)
|
||||
$(OBJS8): $(HEADER)
|
||||
$(OBJS9): $(HEADER)
|
||||
$(OBJS10): $(HEADER)
|
||||
$(OBJS13): $(HEADER)
|
||||
$(OBJS14): $(HEADER)
|
||||
$(OBJS15): $(HEADER)
|
||||
$(OBJS16): $(HEADER)
|
||||
|
||||
/* And depend on all sources and headers. */
|
||||
depend:: $(HEADER) $(COMMONSRCS)
|
||||
|
@ -83,11 +99,13 @@ NormalProgramTarget(select_helper_multiple,$(OBJS12),NullParameter,$(XLIB),NullP
|
|||
NormalProgramTarget(xdg_activation_test,$(OBJS13),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
|
||||
NormalProgramTarget(single_pixel_buffer_test,$(OBJS14),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
|
||||
NormalProgramTarget(buffer_test,$(OBJS15),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
|
||||
NormalProgramTarget(tearing_control_test,$(OBJS16),NullParameter,$(LOCAL_LIBRARIES),NullParameter)
|
||||
DependTarget3($(SRCS1),$(SRCS2),$(SRCS3))
|
||||
DependTarget3($(SRCS4),$(SRCS5),$(SRCS6))
|
||||
DependTarget3($(SRCS7),$(SRCS8),$(SRCS9))
|
||||
DependTarget3($(SRCS10),$(SRCS11),$(SRCS12))
|
||||
DependTarget3($(SRCS13),$(SRCS14),$(SRCS15))
|
||||
DependTarget3($(SRCS16),NullParameter,NullParameter)
|
||||
|
||||
all:: $(PROGRAMS)
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ enum test_kind
|
|||
static const char *test_names[] =
|
||||
{
|
||||
"buffer_release",
|
||||
"buffer_destroy_kind",
|
||||
"buffer_destroy",
|
||||
};
|
||||
|
||||
#define LAST_TEST BUFFER_DESTROY_KIND
|
||||
|
|
|
@ -23,6 +23,7 @@ declare -a standard_tests=(
|
|||
simple_test damage_test transform_test viewporter_test
|
||||
subsurface_test scale_test seat_test dmabuf_test
|
||||
xdg_activation_test single_pixel_buffer_test buffer_test
|
||||
tearing_control_test
|
||||
)
|
||||
|
||||
make -C . "${standard_tests[@]}"
|
||||
|
|
|
@ -15,6 +15,7 @@ select_helper_multiple
|
|||
xdg_activation_test
|
||||
single_pixel_buffer_test
|
||||
buffer_test
|
||||
tearing_control_test
|
||||
imgview
|
||||
reject.dump
|
||||
Makefile
|
||||
|
|
|
@ -276,7 +276,7 @@ RunFrameCallbacksConditionally (XdgRole *role)
|
|||
role->state |= StatePendingFrameCallback;
|
||||
}
|
||||
|
||||
static void
|
||||
static Bool
|
||||
UpdateFrameRefreshPrediction (XdgRole *role)
|
||||
{
|
||||
int desync_children;
|
||||
|
@ -296,7 +296,11 @@ UpdateFrameRefreshPrediction (XdgRole *role)
|
|||
XLFrameClockSetPredictRefresh (role->clock);
|
||||
else
|
||||
XLFrameClockDisablePredictRefresh (role->clock);
|
||||
|
||||
return desync_children > 0;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -862,15 +866,15 @@ MaybeRunLateFrame (XdgRole *role)
|
|||
|
||||
if (role->state & StateLateFrame)
|
||||
{
|
||||
/* Clear the late frame flag. */
|
||||
role->state &= ~StateLateFrame;
|
||||
|
||||
if (role->state & StateLateFrameAcked)
|
||||
XLFrameClockUnfreeze (role->clock);
|
||||
|
||||
/* Now apply the state in the late frame. */
|
||||
SubcompositorUpdate (role->subcompositor);
|
||||
|
||||
/* Clear the late frame flag. */
|
||||
role->state &= ~StateLateFrame;
|
||||
|
||||
/* Return True, as a new update has started. */
|
||||
return True;
|
||||
}
|
||||
|
@ -1169,10 +1173,20 @@ WriteRedirectProperty (XdgRole *role)
|
|||
(unsigned char *) &bypass_compositor, 1);
|
||||
}
|
||||
|
||||
static Bool
|
||||
WasFrameQueued (XdgRole *role)
|
||||
{
|
||||
/* Return whether or not the translator slept before displaying this
|
||||
frame in response to a frame drawn event. */
|
||||
|
||||
return (role->state & StateLateFrame) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
NoteFrame (FrameMode mode, uint64_t id, void *data)
|
||||
{
|
||||
XdgRole *role;
|
||||
Bool predict_refresh, urgent;
|
||||
|
||||
role = data;
|
||||
|
||||
|
@ -1186,9 +1200,28 @@ NoteFrame (FrameMode mode, uint64_t id, void *data)
|
|||
{
|
||||
/* Update whether or not frame refresh prediction is to be
|
||||
used. */
|
||||
UpdateFrameRefreshPrediction (role);
|
||||
predict_refresh = UpdateFrameRefreshPrediction (role);
|
||||
|
||||
if (XLFrameClockStartFrame (role->clock, False))
|
||||
/* A rule of thumb is to never let the compositing manager
|
||||
read or try to scan out incomplete buffer contents.
|
||||
Thus, if the client asked for async presentation, Commit
|
||||
will still wait for the compositor to finish drawing the
|
||||
last frame.
|
||||
|
||||
In addition, how subsurfaces fit into all of this is
|
||||
unclear. At present, the presentation hint of
|
||||
subsurfaces is simply discarded, and the hint of the
|
||||
topmost surface used instead. In addition, asynchronous
|
||||
subsurfaces will prevent async presentation from taking
|
||||
place at all. */
|
||||
|
||||
urgent = (WasFrameQueued (role)
|
||||
&& !predict_refresh
|
||||
&& role->role.surface
|
||||
&& (role->role.surface->current_state.presentation_hint
|
||||
== PresentationHintAsync));
|
||||
|
||||
if (XLFrameClockStartFrame (role->clock, urgent))
|
||||
role->state |= StateFrameStarted;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue