forked from 12to11/12to11
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:
parent
28f1410e35
commit
ebcc957302
11 changed files with 362 additions and 78 deletions
1
12to11.c
1
12to11.c
|
@ -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 ();
|
||||
|
|
74
Imakefile
74
Imakefile
|
@ -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
4
README
|
@ -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).
|
||||
|
||||
|
|
65
compositor.h
65
compositor.h
|
@ -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
135
egl.c
|
@ -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
2
fns.c
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
26
renderer.c
26
renderer.c
|
@ -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
12
run.c
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
77
surface.c
77
surface.c
|
@ -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
|
||||
|
|
8
xdata.c
8
xdata.c
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue