Rework subcompositor damage culling and use a back buffer in the pict renderer

Note that the EGL renderer has been broken by these changes.

* compositor.h (struct _RenderFuncs): Change arguments to
`finish_render'.  Add `cancel_completion_callback'.  Remove
`cancel_presentation'.
(struct _BufferFuncs): Add `is_buffer_opaque'.
* egl.c: Note that the EGL renderer is currently broken.
* fence_ring.c (FenceFree, struct _Fence, GetFence, FenceAwait)
(FenceToXFence): Repurpose fence code as a generic allocator of
fences.
* frame_clock.c (EndFrame): Adjust calculation of even value.
* picture_renderer.c (struct _BufferActivityRecord): Remove
`fence'.
(struct _PictureBuffer): Remove unused field.
(struct _PresentCompletionCallback): Remove unused fields
linking it to the target.
(struct _BackBuffer): New structure.
(IsBufferBusy, SetBufferBusy, ClearBufferBusy): New macros.
(struct _PictureTarget): Add back buffer and GC fields.
(use_sync_fences): Remove variable.
(RecordBufferActivity): Don't take fence.
(UnlinkActivityRecord): Don't wait on fence.
(FreeBackBuffer, FreeBackBuffers, CreateBackBuffer)
(MakePresentationCallback, SwapBackBuffers)
(SwapBackBuffersWithCopy, MaybeAwaitBuffer, GetNextBackBuffer)
(EnsurePicture): New functions.
(TargetFromDrawable): Don't create picture for window targets,
and create GC for those.
(NoteTargetSize): Free back buffers instead of creating
presentation windows.
(DestroyRenderTarget): Free back buffers.
(ViewContainsExtents): Delete function.
(FinishRender): Swap back buffers and handle callbacks.
(CancelCompletionCallback): New function.
(TargetAge): Implement accordingly.
(PresentToWindow, CancelPresentationCallback): Present to the
regular window instead of a separate ``presentation window''.
(CancelPresentation): Remove function.
(picture_render_funcs): Add CancelCompletionCallback; remove
NeverAges and CancelPresentation.
(BufferFromDmaBuf, FinishDmaBufRecord, BufferFromShm): Set
opaque flag accordingly.
(IsBufferOpaque): New function.
(picture_buffer_funcs): Add IsBufferOpaque.
(HandlePresentCompleteNotify, HandlePresentIdleNotify): Handle
back buffer release.

* renderer.c (RenderFinishRender, RenderCancelCompletionCallback)
(RenderCancelPresentation, RenderIsBufferOpaque): Adjust
accordingly.
* seat.c (InterpolateAxes): Fix NULL-pointer dereference.

* subcompositor.c (SetFrozen, IsFrozen): Get rid of unused
state.
(struct _View): Cache the width and height.  Add cull_region
field.
(struct _Subcompositor): Add `render_key' field.
(ViewAfterSizeUpdate): Set cached width and height.
(ViewAttachBuffer): Correctly handle size changes.
(ViewDamage): Apply buffer damage.
(ViewDamageBuffer): use ViewDamage.
(ApplyBufferDamage): New function.:(FillBoxesWithTransparency,
ViewContainsExtents, IntersectBoxes): Delete unused functions.
(RenderCompletedCallback): New function.
(NoViewsAfter): Delete function.
(SkipSlug): New slug.
(SubcompositorUpdateAncillary, TryPresent, AnyParentUnmapped)
(DoCull, DrawBackground, CompositeSingleView, InitBackground)
(SubcompositorComposite1, SubcompositorComposite): New
functions.  Implement new redisplay logic here.
(SubcompositorUpdate, CopyRegion): New function.
(SubcompositorExpose, SubcompositorFree): Clear render callback
if set.
(SubcompositorLookupView): Use cached width and height.
(SubcompositorFreeze, SubcompositorUnfreeze): Remove unused
functions.
* time.c (InitTime): Fix use of uninitialized value initializing
the Sync extension.
* transform.c (TransformBox): Pacify compiler warning.
This commit is contained in:
hujianwei 2022-10-29 05:21:35 +00:00
parent 0b5d44537b
commit a05a62d9d0
10 changed files with 1447 additions and 1349 deletions

View file

@ -161,12 +161,14 @@ typedef enum _BufferTransform BufferTransform;
typedef void *IdleCallbackKey;
typedef void *PresentCompletionKey;
typedef void *RenderCompletionKey;
typedef void (*DmaBufSuccessFunc) (RenderBuffer, void *);
typedef void (*DmaBufFailureFunc) (void *);
typedef void (*BufferIdleFunc) (RenderBuffer, void *);
typedef void (*PresentCompletionFunc) (void *);
typedef void (*RenderCompletionFunc) (void *);
enum _BufferTransform
{
@ -361,20 +363,30 @@ struct _RenderFuncs
int, int, int, int, DrawParams *);
/* Finish rendering, and swap changes in given damage to display.
May be NULL. */
void (*finish_render) (RenderTarget, pixman_region32_t *);
May be NULL. If a callback is passed and a non-NULL key is
returned, then the rendering will not actually have finished
until the callback is run. */
RenderCompletionKey (*finish_render) (RenderTarget, pixman_region32_t *,
RenderCompletionFunc, void *);
/* Cancel the callback returned by finish_render. */
void (*cancel_completion_callback) (RenderCompletionKey);
/* Return the age of the target. Value is a number not less than
-1, describing the "age" of the contents of the target.
-2, describing the "age" of the contents of the target.
-1 means the buffer contains no valid contents, and must be
redrawn from scratch. 0 means the buffer contains the contents
at the time of the last call to `finish_render', 1 means the
buffer contains the contents at the time of the second last
call to `finish_render', and so on.
redrawn from scratch. 0 means the buffer contains the contents
at the time of the last call to `finish_render', 1 means the
buffer contains the contents at the time of the second last call
to `finish_render', and so on.
Note that when a render target is first created, the renderer
may chose to return 0 instead of 1. */
-2 means the buffer contents are of the last call to
FinishRender, but are invalid for any rendering call other than
present_to_window.
Note that when a render target is first created, the renderer may
chose to return 0 instead of 1. */
int (*target_age) (RenderTarget);
/* Create a rendering "fence" object, that serves to explicitly
@ -407,11 +419,6 @@ struct _RenderFuncs
/* Cancel the given presentation callback. */
void (*cancel_presentation_callback) (PresentCompletionKey);
/* Cancel any presentation that might have happened to the window
backing the given target. This must be called before any normal
drawing operations. */
void (*cancel_presentation) (RenderTarget);
/* Some flags. NeverAges means targets always preserve contents
that were previously drawn. */
@ -512,6 +519,10 @@ struct _BufferFuncs
/* Ensure wait_for_idle can be called. May be NULL. */
void (*set_need_wait_for_idle) (RenderTarget);
/* Return whether or not the given buffer can be treated as
completely opaque. */
Bool (*is_buffer_opaque) (RenderBuffer);
/* Called during renderer initialization. */
void (*init_buffer_funcs) (void);
};
@ -535,7 +546,11 @@ extern void RenderFillBoxesWithTransparency (RenderTarget, pixman_box32_t *,
extern void RenderClearRectangle (RenderTarget, int, int, int, int);
extern void RenderComposite (RenderBuffer, RenderTarget, Operation, int,
int, int, int, int, int, DrawParams *);
extern void RenderFinishRender (RenderTarget, pixman_region32_t *);
extern RenderCompletionKey RenderFinishRender (RenderTarget,
pixman_region32_t *,
RenderCompletionFunc,
void *);
extern void RenderCancelCompletionCallback (RenderCompletionKey);
extern int RenderTargetAge (RenderTarget);
extern RenderFence RenderImportFdFence (int, Bool *);
extern void RenderWaitFence (RenderFence);
@ -546,7 +561,6 @@ extern PresentCompletionKey RenderPresentToWindow (RenderTarget, RenderBuffer,
PresentCompletionFunc,
void *);
extern void RenderCancelPresentationCallback (PresentCompletionKey);
extern void RenderCancelPresentation (RenderTarget);
extern DrmFormat *RenderGetDrmFormats (int *);
extern dev_t RenderGetRenderDevice (Bool *);
@ -571,6 +585,7 @@ extern void RenderCancelIdleCallback (IdleCallbackKey);
extern Bool RenderIsBufferIdle (RenderBuffer, RenderTarget);
extern void RenderWaitForIdle (RenderBuffer, RenderTarget);
extern void RenderSetNeedWaitForIdle (RenderTarget);
extern Bool RenderIsBufferOpaque (RenderBuffer);
/* Defined in run.c. */
@ -1760,8 +1775,11 @@ extern int ProcessPoll (struct pollfd *, nfds_t, struct timespec *);
typedef struct _Fence Fence;
extern Fence *GetFence (void);
extern Fence *GetLooseFence (void);
extern void FenceTrigger (Fence *);
extern void FenceRetain (Fence *);
extern void FenceAwait (Fence *);
extern void FenceRelease (Fence *);
extern XSyncFence FenceToXFence (Fence *);
/* Utility functions that don't belong in a specific file. */

3
egl.c
View file

@ -35,7 +35,8 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include "linux-dmabuf-unstable-v1.h"
/* TODO: implement buffer transforms. */
/* TODO: implement buffer transforms. This renderer is currently
broken. */
/* These are flags for the DrmFormats. */

View file

@ -28,28 +28,19 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
#include <xcb/dri3.h>
#define FenceFree (1U << 31)
struct _Fence
{
/* The next and last fences on this list. */
Fence *next;
/* The xshmfence. */
struct xshmfence *fence;
/* The sync fence. High bit is a flag meaning that the fence is on
the free list. */
/* The sync fence. */
XSyncFence fence_id;
/* The number of references to this fence. Incremented by
FenceRetain, decremented by FenceAwait. */
FenceRetain, decremented by FenceRelease. */
int refcount;
};
/* Chain of all free fences. */
static Fence *all_fences;
Fence *
GetFence (void)
{
@ -59,22 +50,7 @@ GetFence (void)
drawable = DefaultRootWindow (compositor.display);
/* Get one free fence. */
for (fence = all_fences; fence; fence = fence->next)
{
/* Unlink this fence. */
all_fences = fence->next;
fence->next = NULL;
/* Mark the fence as used. */
fence->fence_id &= ~FenceFree;
/* Return it. */
return fence;
}
/* Otherwise, allocate a new fence. */
/* Allocate a new fence. */
fence = XLCalloc (1, sizeof *fence);
fd = xshmfence_alloc_shm ();
@ -103,6 +79,9 @@ GetFence (void)
xcb_dri3_fence_from_fd (compositor.conn, drawable,
fence->fence_id, 0, fd);
/* Retain the fence. */
FenceRetain (fence);
/* Return the fence. */
return fence;
}
@ -110,26 +89,27 @@ GetFence (void)
void
FenceAwait (Fence *fence)
{
XLAssert (fence->refcount);
fence->refcount -= 1;
/* Wait for the fence to be triggered. */
xshmfence_await (fence->fence);
if (!(fence->fence_id & FenceFree))
{
/* Wait for the fence to be triggered. */
xshmfence_await (fence->fence);
/* Reset the fence. */
xshmfence_reset (fence->fence);
}
/* Reset the fence. */
xshmfence_reset (fence->fence);
fence->fence_id |= FenceFree;
}
if (fence->refcount)
void
FenceRelease (Fence *fence)
{
if (--fence->refcount)
return;
/* Now that the fence is no longer referenced, it can be put back on
the list of free fences. */
fence->next = all_fences;
all_fences = fence;
/* Unmap the fence. */
xshmfence_unmap_shm (fence->fence);
/* Destroy the fence. */
XSyncDestroyFence (compositor.display, fence->fence_id);
/* Free the fence. */
XLFree (fence);
}
void
@ -141,5 +121,5 @@ FenceRetain (Fence *fence)
XSyncFence
FenceToXFence (Fence *fence)
{
return fence->fence_id & ~FenceFree;
return fence->fence_id;
}

View file

@ -476,7 +476,12 @@ EndFrame (FrameClock *clock)
/* Signal to the compositor that the frame is now complete. When
the compositor finishes drawing the frame, a callback will be
received. */
clock->next_frame_id += 1;
if (clock->next_frame_id % 4 == 3)
clock->next_frame_id += 1;
else
clock->next_frame_id += 3;
clock->finished_frame_id = clock->next_frame_id;
/* The frame has ended. Freeze the frame clock if there is a
@ -488,8 +493,7 @@ EndFrame (FrameClock *clock)
if (!frame_sync_supported)
return;
SetSyncCounter (clock->secondary_counter,
clock->next_frame_id);
SetSyncCounter (clock->secondary_counter, clock->next_frame_id);
}
static void

File diff suppressed because it is too large Load diff

View file

@ -145,11 +145,20 @@ RenderComposite (RenderBuffer source, RenderTarget target, Operation op,
width, height, draw_params);
}
void
RenderFinishRender (RenderTarget target, pixman_region32_t *damage)
RenderCompletionKey
RenderFinishRender (RenderTarget target, pixman_region32_t *damage,
RenderCompletionFunc function, void *data)
{
if (render_funcs.finish_render)
render_funcs.finish_render (target, damage);
return render_funcs.finish_render (target, damage, function, data);
return NULL;
}
void
RenderCancelCompletionCallback (RenderCompletionKey key)
{
return render_funcs.cancel_completion_callback (key);
}
int
@ -206,15 +215,6 @@ RenderCancelPresentationCallback (PresentCompletionKey key)
render_funcs.cancel_presentation_callback (key);
}
void
RenderCancelPresentation (RenderTarget target)
{
if (!render_funcs.cancel_presentation)
return;
render_funcs.cancel_presentation (target);
}
DrmFormat *
RenderGetDrmFormats (int *n_formats)
{
@ -344,6 +344,12 @@ RenderSetNeedWaitForIdle (RenderTarget target)
buffer_funcs.set_need_wait_for_idle (target);
}
Bool
RenderIsBufferOpaque (RenderBuffer buffer)
{
return buffer_funcs.is_buffer_opaque (buffer);
}
void
RegisterStaticRenderer (const char *name,
RenderFuncs *render_funcs,

2
seat.c
View file

@ -3648,6 +3648,8 @@ InterpolateAxes (Surface *surface, DeviceInfo *info,
/* Multiply the deltas by 15 if no device was found. */
*x_out = movement_x * 15;
*y_out = movement_y * 15;
return;
}
/* Multiply these deltas by the scrolling pixel distance to obtain

File diff suppressed because it is too large Load diff

12
time.c
View file

@ -303,12 +303,6 @@ InitTime (void)
supported = XSyncInitialize (compositor.display,
&xsync_major, &xsync_minor);
if (xsync_major < 3 || (xsync_major == 3 && xsync_minor < 1))
{
fprintf (stderr, "Sync fences are not supported by this X server\n");
exit (1);
}
if (!supported)
{
fprintf (stderr, "A compatible version of the synchronization"
@ -316,6 +310,12 @@ InitTime (void)
exit (1);
}
if (xsync_major < 3 || (xsync_major == 3 && xsync_minor < 1))
{
fprintf (stderr, "Sync fences are not supported by this X server\n");
exit (1);
}
/* Initialize server timestamp tracking. In order for server time
accounting to be absolutely reliable, we must receive an event
detailing each change every time it reaches HalfMonth and 0. Set

View file

@ -345,6 +345,7 @@ TransformBox (pixman_box32_t *box, BufferTransform transform,
switch (transform)
{
case Normal:
default:
work = *box;
break;