Implement explicit synchronization

* 12to11.c (XLMain): Initialize explicit synchronization.
* Imakefile (SRCS, OBJS): Remove generated files.
(ScannerTarget): New macro.
(clean): Clean GENSRCS as well.
(linux-dmabuf-unstable-v1.h):
(linux-dmabuf-unstable-v1.c):
(xdg-shell.h):
(xdg-shell.c):
(primary-selection-unstable-v1.h):
(primary-selection-unstable-v1.c): Remove and replace with
ScannerTarget.
* README: Announce explicit synchronization support.
* compositor.h (union _RenderFence): New union.
(struct _RenderFuncs): Add fence functions.
(struct _Surface): New fields for explicit synchronization
objects and release callbacks.
* egl.c (EglInitFuncs, EglInitGlFuncs, EglInitDisplay):
Initialize functions and extensions used for explicit
synchronization, and set render func flags.
(ImportFdFence, WaitFence, DeleteFence, HandleFenceReadable)
(GetFinishFence): New functions.
(egl_render_funcs): Add those functions.
(AddRenderFlag): New function.
* fns.c (MaybeInstallBusHandler): Fix coding style.
* picture_renderer.c (ImportFdFence, WaitFence, DeleteFence)
(GetFinishFence): New stubs.
(picture_render_funcs): Add those functions; they should never
be called.
* renderer.c (RenderImportFdFence):
(RenderWaitFence):
(RenderDeleteFence):
(RenderGetFinishFence): New wrapper functions.
* run.c (struct _PollFd, XLAddWriteFd, XLAddReadFd): Add pollfd
field to callback args.
(RunStep): Pass them to callbacks.  Also, fix a comment.
* surface.c (DoRelease): New function.
(DestroySurface): Clear release if possible.
(SavePendingState, TryEarlyRelease): Extract release code to
DoRelease.
(InternalCommit): Wait for sync fences before continuing.
(Commit): Close acquire fence and release sync release object.
(HandleSurfaceDestroy): Destroy release callback and close
acquire fence.
(XLCreateSurface): Clear acquire fence field with right initial
value.
* xdata.c (NoticeTransferWritable):
(NoticeTransferReadable):
(NoticeConversionTransferReadable):
(NoticeConversionTransferWritable): Adjust arguments for new
callback data.
This commit is contained in:
oldosfan 2022-09-25 08:21:31 +00:00
parent 28f1410e35
commit ebcc957302
11 changed files with 362 additions and 78 deletions

View file

@ -121,6 +121,7 @@ XLMain (int argc, char **argv)
XLInitXSettings ();
XLInitIconSurfaces ();
XLInitPrimarySelection ();
XLInitExplicitSynchronization ();
/* This has to come after the rest of the initialization. */
DetermineServerTime ();
XLRunCompositor ();

View file

@ -17,25 +17,24 @@ LOCAL_LIBRARIES = $(XLIB) $(EXTENSIONLIB) $(XCBLIB) $(XCB) $(XCB_SHM) \
INCLUDES := $(DRMINCLUDES) $(PIXMANINCLUDES)
SRCS = 12to11.c run.c alloc.c fns.c output.c compositor.c \
xdg-shell.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 linux-dmabuf-unstable-v1.c dmabuf.c \
buffer.c select.c xdata.c xsettings.c dnd.c icon_surface.c \
primary-selection-unstable-v1.c primary_selection.c \
renderer.c picture_renderer.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
OBJS = 12to11.o run.o alloc.o fns.o output.o compositor.o \
xdg-shell.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 linux-dmabuf-unstable-v1.o dmabuf.o \
buffer.o select.o xdata.o xsettings.o dnd.o icon_surface.o \
primary-selection-unstable-v1.o primary_selection.o \
renderer.o picture_renderer.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
GENHEADERS = transfer_atoms.h primary-selection-unstable-v1.h \
linux-dmabuf-unstable-v1.h xdg-shell.h
linux-dmabuf-unstable-v1.h xdg-shell.h \
linux-explicit-synchronization-unstable-v1.h
#ifdef HaveEglSupport
@ -94,37 +93,34 @@ transfer_atoms.h: short_types.txt mime0.awk mime1.awk mime2.awk mime3.awk \
awk -f mime3.awk short_types.txt >> $@
awk -f mime4.awk short_types.txt >> $@
/* Now, define generated files. */
#define ScannerTarget(name) @@\
name.h: name.xml @@\
$(WAYLAND_SCANNER) server-header $< $@ @@\
@@\
name.c: name.xml name.h @@\
$(WAYLAND_SCANNER) private-code $< $@ @@\
@@\
GENHEADERS := $(GENHEADERS) name.h @@\
OBJS := $(OBJS) name.o @@\
SRCS := $(SRCS) name.c @@\
GENSRCS := $(GENSRCS) name.c @@\
ScannerTarget(linux-dmabuf-unstable-v1)
ScannerTarget(xdg-shell)
ScannerTarget(primary-selection-unstable-v1)
ScannerTarget(linux-explicit-synchronization-unstable-v1)
/* Make OBJS depend on scanner headers, and depend on both them and SRCS. */
$(OBJS): $(GENHEADERS)
/* depend somehow does not depend on SRCS, even though some of OBJS
are generated. */
depend:: $(GENHEADERS) $(SRCS)
linux-dmabuf-unstable-v1.h: linux-dmabuf-unstable-v1.xml
$(WAYLAND_SCANNER) server-header $< $@
linux-dmabuf-unstable-v1.c: linux-dmabuf-unstable-v1.xml \
linux-dmabuf-unstable-v1.h
$(WAYLAND_SCANNER) private-code $< $@
xdg-shell.h: xdg-shell.xml
$(WAYLAND_SCANNER) server-header $< $@
xdg-shell.c: xdg-shell.xml xdg-shell.h
$(WAYLAND_SCANNER) private-code $< $@
primary-selection-unstable-v1.h: primary-selection-unstable-v1.xml
$(WAYLAND_SCANNER) server-header $< $@
primary-selection-unstable-v1.c: primary-selection-unstable-v1.xml \
primary-selection-unstable-v1.h
$(WAYLAND_SCANNER) private-code $< $@
cleandir::
$(RM) linux-dmabuf-unstable-v1.c linux-dmabuf-unstable-v1.h \
xdg-shell.c xdg-shell.h primary-selection-unstable-v1.c \
primary-selection-unstable-v1.h
$(RM) transfer_atoms.h short_types.txt
$(RM) $(GENHEADERS) $(GENSRCS) transfer_atoms.h short_types.txt
/* Undefine _BSD_SOURCE and _SVID_SOURCE, since both are deprecated
and are also superseeded by _GNU_SOURCE. */

4
README
View file

@ -65,6 +65,10 @@ complete degree:
'zwp_linux_dmabuf_v1', version: 4
'zwp_primary_selection_device_manager_v1', version: 1
When built with EGL, the following Wayland protocol is also supported:
'zwp_linux_explicit_synchronization_v1', version: 2
With the main caveat being that zwp_linux_dmabuf_v1 has no real
support for multiple-provider setups (help wanted).

View file

@ -101,6 +101,7 @@ typedef struct _BufferFuncs BufferFuncs;
typedef union _RenderTarget RenderTarget;
typedef union _RenderBuffer RenderBuffer;
typedef union _RenderFence RenderFence;
typedef struct _DmaBufAttributes DmaBufAttributes;
typedef struct _SharedMemoryAttributes SharedMemoryAttributes;
@ -183,13 +184,24 @@ union _RenderBuffer
void *pointer;
};
union _RenderFence
{
/* The XID of the fence resource, if that is what it is. */
XID xid;
/* The pointer to the fence, if that is what it is. */
void *pointer;
};
enum
{
/* The render target always preserves previously drawn contents;
IOW, target_age always returns 0. */
NeverAges = 1,
NeverAges = 1,
/* Buffers attached can always be immediately released. */
ImmediateRelease = 1 << 2,
ImmediateRelease = 1 << 2,
/* The render target supports explicit synchronization. */
SupportsExplicitSync = 1 << 3,
};
struct _RenderFuncs
@ -258,6 +270,25 @@ struct _RenderFuncs
may chose to return 0 instead of 1. */
int (*target_age) (RenderTarget);
/* Create a rendering "fence" object, that serves to explicitly
specify the order of rendering requests between different
programs. Fence-related functions must only be defined if
SupportsExplicitSync is set. */
RenderFence (*import_fd_fence) (int, Bool *);
/* Wait for the given fence object. This is guaranteed to make all
drawing commands execute after the fence has been triggered, but
does not typically block. */
void (*wait_fence) (RenderFence);
/* Delete the given fence object. */
void (*delete_fence) (RenderFence);
/* Get a file descriptor describing a fence that is triggered upon
the completion of all drawing commands made before it is
called. */
int (*get_finish_fence) (Bool *);
/* Some flags. NeverAges means targets always preserve contents
that were previously drawn. */
int flags;
@ -351,6 +382,10 @@ extern void RenderComposite (RenderBuffer, RenderTarget, Operation, int,
extern void RenderResetTransform (RenderBuffer);
extern void RenderFinishRender (RenderTarget);
extern int RenderTargetAge (RenderTarget);
extern RenderFence RenderImportFdFence (int, Bool *);
extern void RenderWaitFence (RenderFence);
extern void RenderDeleteFence (RenderFence);
extern int RenderGetFinishFence (Bool *);
extern DrmFormat *RenderGetDrmFormats (int *);
extern dev_t RenderGetRenderDevice (Bool *);
@ -372,8 +407,8 @@ typedef struct _PollFd WriteFd;
typedef struct _PollFd ReadFd;
extern void XLRunCompositor (void);
extern WriteFd *XLAddWriteFd (int, void *, void (*) (int, void *));
extern ReadFd *XLAddReadFd (int, void *, void (*) (int, void *));
extern WriteFd *XLAddWriteFd (int, void *, void (*) (int, void *, ReadFd *));
extern ReadFd *XLAddReadFd (int, void *, void (*) (int, void *, ReadFd *));
extern void XLRemoveWriteFd (WriteFd *);
extern void XLRemoveReadFd (ReadFd *);
@ -595,6 +630,11 @@ extern void ViewSetScale (View *, int);
extern Subcompositor *ViewGetSubcompositor (View *);
/* Forward declarations from explicit_synchronization.c. */
typedef struct _Synchronization Synchronization;
typedef struct _SyncRelease SyncRelease;
/* Defined in surface.c. */
typedef struct _State State;
@ -783,6 +823,15 @@ struct _Surface
/* X, Y of the last coordinates that were used to update this
surface's entered outputs. */
int output_x, output_y;
/* The associated explicit synchronization resource, if any. */
Synchronization *synchronization;
/* The associated sync release resource, if any. */
SyncRelease *release;
/* The associated sync acquire fd, or -1. */
int acquire_fence;
};
struct _RoleFuncs
@ -1275,6 +1324,14 @@ extern void InitEgl (void);
#endif
/* Defined in explicit_synchronization.c. */
extern void XLDestroyRelease (SyncRelease *);
extern void XLSyncCommit (Synchronization *);
extern void XLSyncRelease (SyncRelease *);
extern void XLWaitFence (Surface *);
extern void XLInitExplicitSynchronization (void);
/* Utility functions that don't belong in a specific file. */
#define ArrayElements(arr) (sizeof (arr) / sizeof (arr)[0])

135
egl.c
View file

@ -321,6 +321,12 @@ static PFNEGLQUERYDISPLAYATTRIBEXTPROC IQueryDisplayAttrib;
static PFNEGLQUERYDEVICESTRINGEXTPROC IQueryDeviceString;
static PFNEGLQUERYDMABUFFORMATSEXTPROC IQueryDmaBufFormats;
static PFNEGLQUERYDMABUFMODIFIERSEXTPROC IQueryDmaBufModifiers;
static PFNEGLCREATESYNCKHRPROC ICreateSync;
static PFNEGLDESTROYSYNCKHRPROC IDestroySync;
static PFNEGLCLIENTWAITSYNCKHRPROC IClientWaitSync;
static PFNEGLGETSYNCATTRIBKHRPROC IGetSyncAttrib;
static PFNEGLWAITSYNCKHRPROC IWaitSync;
static PFNEGLDUPNATIVEFENCEFDANDROIDPROC IDupNativeFenceFD;
/* The EGL display handle. */
static EGLDisplay egl_display;
@ -507,12 +513,24 @@ EglInitFuncs (void)
"EGL_EXT_image_dma_buf_import_modifiers");
LoadProc (QueryDmaBufModifiers, "EXT",
"EGL_EXT_image_dma_buf_import_modifiers");
LoadProc (CreateSync, "KHR", "EGL_KHR_fence_sync");
LoadProc (DestroySync, "KHR", "EGL_KHR_fence_sync");
LoadProc (ClientWaitSync, "KHR", "EGL_KHR_fence_sync");
LoadProc (GetSyncAttrib, "KHR", "EGL_KHR_fence_sync");
LoadProc (WaitSync, "KHR", "EGL_KHR_wait_sync");
LoadProc (DupNativeFenceFD, "ANDROID", "EGL_ANDROID_native_fence_sync");
}
static void
EglInitGlFuncs (void)
{
LoadProcGl (EGLImageTargetTexture2D, "OES", "GL_OES_EGL_image");
/* We treat eglWaitSyncKHR specially, since it only works if the
server client API also supports GL_OES_EGL_sync. */
if (!HaveGlExtension ("GL_OES_EGL_sync"))
IWaitSync = NULL;
}
static Visual *
@ -768,6 +786,9 @@ EglCompileShaders (void)
composite_rectangle_fragment_shader_external);
}
/* Forward declaration. */
static void AddRenderFlag (int);
static Bool
EglInitDisplay (void)
{
@ -816,6 +837,11 @@ EglInitDisplay (void)
CheckExtension (ICreateImage);
CheckExtension (IDestroyImage);
/* If both EGL fences and EGL_ANDROID_native_fence_sync are
supported, enable explicit sync. */
if (ICreateSync && IDupNativeFenceFD)
AddRenderFlag (SupportsExplicitSync);
/* Otherwise, the display has been initialized. */
egl_major = major;
egl_minor = minor;
@ -1275,6 +1301,105 @@ TargetAge (RenderTarget target)
return -1;
}
static RenderFence
ImportFdFence (int fd, Bool *error)
{
EGLSyncKHR *fence;
EGLint attribs[3];
attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
attribs[1] = fd;
attribs[2] = EGL_NONE;
/* This fence is supposed to assume ownership over the given file
descriptor. */
fence = ICreateSync (egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID,
attribs);
if (fence == EGL_NO_SYNC_KHR)
{
*error = True;
return (RenderFence) NULL;
}
return (RenderFence) (void *) fence;
}
static void
WaitFence (RenderFence fence)
{
/* N.B. that here egl_context must be current, which should always
be true. */
if (IWaitSync)
/* This is more asynchronous, as it doesn't wait for the fence
on the CPU. */
IWaitSync (egl_display, fence.pointer, 0);
else
/* But eglWaitSyncKHR isn't available everywhere. */
IClientWaitSync (egl_display, fence.pointer, 0,
EGL_FOREVER_KHR);
/* If either of these requests fail, simply proceed to read from the
protected data. */
}
static void
DeleteFence (RenderFence fence)
{
if (!IDestroySync (egl_display, fence.pointer))
/* There is no way to continue without leaking memory, and this
shouldn't happen. */
abort ();
}
static void
HandleFenceReadable (int fd, void *data, ReadFd *readfd)
{
XLRemoveReadFd (readfd);
/* Now destroy the native fence. */
if (!IDestroySync (egl_display, data))
abort ();
/* And close the file descriptor. */
close (fd);
}
static int
GetFinishFence (Bool *error)
{
EGLint attribs;
EGLSyncKHR *fence;
EGLint fd;
attribs = EGL_NONE;
/* Create the fence. EGL_SYNC_CONDITION_KHR should default to
EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR, meaning it will signal once
all prior drawing commands complete. */
fence = ICreateSync (egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID,
&attribs);
if (fence == EGL_NO_SYNC_KHR)
{
*error = True;
return -1;
}
/* Obtain the file descriptor. */
fd = IDupNativeFenceFD (egl_display, fence);
if (fd == -1)
*error = True;
else
/* Delete the fence after it is signalled. Duplicate the fd, as
it will be closed by the caller. */
XLAddReadFd (dup (fd), fence, HandleFenceReadable);
return fd;
}
static RenderFuncs egl_render_funcs =
{
.init_render_funcs = InitRenderFuncs,
@ -1292,9 +1417,19 @@ static RenderFuncs egl_render_funcs =
.reset_transform = ResetTransform,
.finish_render = FinishRender,
.target_age = TargetAge,
.import_fd_fence = ImportFdFence,
.wait_fence = WaitFence,
.delete_fence = DeleteFence,
.get_finish_fence = GetFinishFence,
.flags = ImmediateRelease,
};
static void
AddRenderFlag (int flags)
{
egl_render_funcs.flags |= flags;
}
static DrmFormat *
GetDrmFormats (int *num_formats)
{

2
fns.c
View file

@ -726,7 +726,7 @@ MaybeInstallBusHandler (void)
if (bus_handler_installed)
return;
bus_handler_installed = 1;
bus_handler_installed = True;
memset (&act, 0, sizeof act);
/* Install a SIGBUS handler. When a client truncates the file

View file

@ -340,6 +340,38 @@ TargetAge (RenderTarget target)
return 0;
}
/* At first glance, it seems like this should be easy to support using
DRI3 and synchronization extension fences. Unfortunately, the
"fences" used by DRI3 are userspace fences implemented by the
xshmfence library, and not Android dma-fences, so there is no
straightforward implementation. */
static RenderFence
ImportFdFence (int fd, Bool *error)
{
*error = True;
return (RenderFence) (XID) None;
}
static void
WaitFence (RenderFence fence)
{
/* Unsupported. */
}
static void
DeleteFence (RenderFence fence)
{
/* Unsupported. */
}
static int
GetFinishFence (Bool *error)
{
*error = True;
return -1;
}
static RenderFuncs picture_render_funcs =
{
.init_render_funcs = InitRenderFuncs,
@ -354,6 +386,10 @@ static RenderFuncs picture_render_funcs =
.composite = Composite,
.reset_transform = ResetTransform,
.target_age = TargetAge,
.import_fd_fence = ImportFdFence,
.wait_fence = WaitFence,
.delete_fence = DeleteFence,
.get_finish_fence = GetFinishFence,
.flags = NeverAges,
};

View file

@ -162,6 +162,32 @@ RenderTargetAge (RenderTarget target)
return render_funcs.target_age (target);
}
RenderFence
RenderImportFdFence (int fd, Bool *error)
{
/* Fence-related functions must be defined if
SupportExplicitSync is in flags. */
return render_funcs.import_fd_fence (fd, error);
}
void
RenderWaitFence (RenderFence fence)
{
return render_funcs.wait_fence (fence);
}
void
RenderDeleteFence (RenderFence fence)
{
return render_funcs.delete_fence (fence);
}
int
RenderGetFinishFence (Bool *error)
{
return render_funcs.get_finish_fence (error);
}
DrmFormat *
RenderGetDrmFormats (int *n_formats)
{

12
run.c
View file

@ -37,7 +37,7 @@ struct _PollFd
/* Callback run with the fd number and data when the fd becomes
writable or readable. */
void (*poll_callback) (int, void *);
void (*poll_callback) (int, void *, PollFd *);
/* Data for the callback. */
void *data;
@ -54,7 +54,8 @@ static int num_poll_fd;
static PollFd poll_fds;
WriteFd *
XLAddWriteFd (int fd, void *data, void (*poll_callback) (int, void *))
XLAddWriteFd (int fd, void *data, void (*poll_callback) (int, void *,
WriteFd *))
{
WriteFd *record;
@ -75,7 +76,8 @@ XLAddWriteFd (int fd, void *data, void (*poll_callback) (int, void *))
}
ReadFd *
XLAddReadFd (int fd, void *data, void (*poll_callback) (int, void *))
XLAddReadFd (int fd, void *data, void (*poll_callback) (int, void *,
ReadFd *))
{
WriteFd *record;
@ -278,9 +280,9 @@ RunStep (void)
/* Check that pollfds[j] is still valid, and wasn't
removed while handling X events. */
&& pollfds[j]->write_fd != -1)
/* Then call the write callback. */
/* Then call the poll callback. */
pollfds[j]->poll_callback (pollfds[j]->write_fd,
pollfds[j]->data);
pollfds[j]->data, pollfds[j]);
}
}
}

View file

@ -299,6 +299,16 @@ ClearBuffer (State *state)
state->buffer = NULL;
}
static void
DoRelease (Surface *surface, ExtBuffer *buffer)
{
/* Release the buffer now. */
if (surface->role && !(renderer_flags & ImmediateRelease))
surface->role->funcs.release_buffer (surface, surface->role, buffer);
else
XLReleaseBuffer (buffer);
}
static void
DestroySurface (struct wl_client *client,
struct wl_resource *resource)
@ -652,13 +662,7 @@ SavePendingState (Surface *surface)
it is a mistake! */
&& (surface->cached_state.buffer
!= surface->current_state.buffer))
{
if (surface->role && !(renderer_flags & ImmediateRelease))
surface->role->funcs.release_buffer (surface, surface->role,
surface->cached_state.buffer);
else
XLReleaseBuffer (surface->cached_state.buffer);
}
DoRelease (surface, surface->cached_state.buffer);
if (surface->pending_state.buffer)
{
@ -745,11 +749,7 @@ TryEarlyRelease (Surface *surface)
if (!RenderCanReleaseNow (render_buffer))
return;
/* Release the buffer now. */
if (surface->role && !(renderer_flags & ImmediateRelease))
surface->role->funcs.release_buffer (surface, surface->role, buffer);
else
XLReleaseBuffer (buffer);
DoRelease (surface, buffer);
/* Set the flag saying that the buffer has been released. */
surface->current_state.pending |= BufferAlreadyReleased;
@ -762,18 +762,12 @@ InternalCommit (Surface *surface, State *pending)
if (pending->pending & PendingBuffer)
{
if ((surface->current_state.buffer != pending->buffer)
/* The buffer may already released if its contents were
copied, i.e. uploaded to a texture, during updates. */
&& !(surface->current_state.pending & BufferAlreadyReleased)
&& surface->current_state.buffer)
{
if (surface->role && !(renderer_flags & ImmediateRelease))
surface->role->funcs.release_buffer (surface, surface->role,
surface->current_state.buffer);
else
XLReleaseBuffer (surface->current_state.buffer);
}
/* The buffer may already released if its contents were
copied, i.e. uploaded to a texture, during updates. */
if (!(surface->current_state.pending & BufferAlreadyReleased)
&& surface->current_state.buffer
&& surface->current_state.buffer != pending->buffer)
DoRelease (surface, surface->current_state.buffer);
/* Clear this flag now, since the attached buffer has
changed. */
@ -855,7 +849,8 @@ InternalCommit (Surface *surface, State *pending)
}
/* Run commit callbacks. This tells synchronous subsurfaces to
update. */
update, and tells explicit synchronization to wait for any sync
fence. */
RunCommitCallbacks (surface);
if (surface->subsurfaces)
@ -863,6 +858,9 @@ InternalCommit (Surface *surface, State *pending)
they run in the right order. */
XLSubsurfaceHandleParentCommit (surface);
/* Wait for any sync fence to be triggered before proceeding. */
XLWaitFence (surface);
if (!surface->role)
{
XLDefaultCommit (surface);
@ -887,6 +885,24 @@ Commit (struct wl_client *client, struct wl_resource *resource)
surface = wl_resource_get_user_data (resource);
/* First, clear the acquire fence if it is set. If a
synchronization object is attached, the following call will then
attach any new fence specified. */
if (surface->acquire_fence != -1)
close (surface->acquire_fence);
/* Release any attached explicit synchronization release callback.
XXX: this is not right with synchronous subsurfaces? */
if (surface->release)
XLSyncRelease (surface->release);
if (surface->synchronization)
/* This is done here so early commit hooks can be run for
i.e. synchronous subsurfaces. */
XLSyncCommit (surface->synchronization);
if (surface->role && surface->role->funcs.early_commit
/* The role chose to postpone the commit for a later time. */
&& !surface->role->funcs.early_commit (surface, surface->role))
@ -1056,6 +1072,14 @@ HandleSurfaceDestroy (struct wl_resource *resource)
/* Free the window scaling factor callback. */
XLRemoveScaleChangeCallback (surface->scale_callback_key);
/* If a release is attached, destroy it and its resource. */
if (surface->release)
XLDestroyRelease (surface->release);
/* Likewise if a fence is attached. */
if (surface->acquire_fence != -1)
close (surface->acquire_fence);
FinalizeState (&surface->pending_state);
FinalizeState (&surface->current_state);
FinalizeState (&surface->cached_state);
@ -1153,6 +1177,9 @@ XLCreateSurface (struct wl_client *client,
/* Clear surface output coordinates. */
surface->output_x = INT_MIN;
surface->output_y = INT_MIN;
/* Set the acquire fence fd to -1. */
surface->acquire_fence = -1;
}
void

View file

@ -431,7 +431,7 @@ MaybeFinishDelayedTransfer (ReadTransfer *transfer,
}
static void
NoticeTransferWritable (int fd, void *data)
NoticeTransferWritable (int fd, void *data, WriteFd *writefd)
{
ReadTransfer *transfer;
TransferInfo *info;
@ -1260,7 +1260,7 @@ TypeFromTarget (Atom target, Bool primary)
}
static void
NoticeTransferReadable (int fd, void *data)
NoticeTransferReadable (int fd, void *data, ReadFd *readfd)
{
WriteTransfer *transfer;
WriteInfo *info;
@ -1460,7 +1460,7 @@ GetClipboardCallback (WriteTransfer *transfer, Atom target,
static void
NoticeConversionTransferReadable (int fd, void *data)
NoticeConversionTransferReadable (int fd, void *data, ReadFd *readfd)
{
WriteTransfer *transfer;
ConversionWriteInfo *info;
@ -1726,7 +1726,7 @@ FinishConversionTransfer (ReadTransfer *transfer, ConversionTransferInfo *info)
}
static void
NoticeConversionTransferWritable (int fd, void *data)
NoticeConversionTransferWritable (int fd, void *data, WriteFd *writefd)
{
ConversionTransferInfo *info;
ssize_t written;