xwayland/glamor/gbm: Copy explicit sync code to GLAMOR/GBM

Copy the code to deal with synchronization objects from the window
buffers to the GLAMOR/GBM code.

The idea is to deal with synchronizations for all pixmaps, even when
there is no window buffer involved.

This is still preparation work for the following commits, no functional
change intended at this point.

v2: Use a "xwl_window_buffer *" instead of a "void *data" (Michel)
v3: Bail early if there's no xwl_window_buffer (Michel)
v4: Rename xwl_window_submit_pixmap() to
    xwl_glamor_gbm_wait_release_fence() (Michel)

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1571>
This commit is contained in:
Olivier Fourdan 2024-06-18 11:11:34 +02:00 committed by Marge Bot
parent b5082073b0
commit cc021aca99
2 changed files with 152 additions and 0 deletions

View File

@ -32,6 +32,8 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <poll.h>
#include <sys/eventfd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <drm_fourcc.h> #include <drm_fourcc.h>
@ -55,6 +57,7 @@
#include "xwayland-glamor-gbm.h" #include "xwayland-glamor-gbm.h"
#include "xwayland-pixmap.h" #include "xwayland-pixmap.h"
#include "xwayland-screen.h" #include "xwayland-screen.h"
#include "xwayland-window-buffers.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "linux-drm-syncobj-v1-client-protocol.h" #include "linux-drm-syncobj-v1-client-protocol.h"
@ -82,6 +85,12 @@ struct xwl_pixmap {
unsigned int texture; unsigned int texture;
struct gbm_bo *bo; struct gbm_bo *bo;
Bool implicit_modifier; Bool implicit_modifier;
#ifdef DRI3
struct dri3_syncobj *syncobj;
uint64_t timeline_point;
int efd;
struct xwl_window_buffer *xwl_window_buffer;
#endif /* DRI3 */
}; };
static DevPrivateKeyRec xwl_gbm_private_key; static DevPrivateKeyRec xwl_gbm_private_key;
@ -225,6 +234,9 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
xwl_pixmap->bo = bo; xwl_pixmap->bo = bo;
xwl_pixmap->buffer = NULL; xwl_pixmap->buffer = NULL;
xwl_pixmap->implicit_modifier = implicit_modifier; xwl_pixmap->implicit_modifier = implicit_modifier;
#ifdef XWL_HAS_GLAMOR
xwl_pixmap->efd = -1;
#endif /* XWL_HAS_GLAMOR */
#ifdef GBM_BO_FD_FOR_PLANE #ifdef GBM_BO_FD_FOR_PLANE
if (xwl_gbm->dmabuf_capable) { if (xwl_gbm->dmabuf_capable) {
@ -445,6 +457,7 @@ xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
if (xwl_pixmap->bo) if (xwl_pixmap->bo)
gbm_bo_destroy(xwl_pixmap->bo); gbm_bo_destroy(xwl_pixmap->bo);
xwl_glamor_gbm_dispose_syncpts(pixmap);
free(xwl_pixmap); free(xwl_pixmap);
} }
@ -1388,6 +1401,21 @@ xwl_glamor_gbm_has_egl_extension(void)
epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm")); epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm"));
} }
#ifdef DRI3
static void
xwl_glamor_gbm_release_fence_avail(int fd, int xevents, void *data)
{
struct xwl_pixmap *xwl_pixmap = data;
struct xwl_window_buffer *xwl_window_buffer = xwl_pixmap->xwl_window_buffer;
SetNotifyFd(fd, NULL, 0, NULL);
close(fd);
xwl_pixmap->efd = -1;
xwl_window_buffer_release(xwl_window_buffer);
}
#endif /* DRI3 */
Bool Bool
xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen) xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen)
{ {
@ -1403,6 +1431,122 @@ xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen)
xwl_gbm_get(xwl_screen)->supports_syncobjs; xwl_gbm_get(xwl_screen)->supports_syncobjs;
} }
Bool
xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap)
{
#ifdef DRI3
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
uint64_t acquire_point;
uint64_t release_point;
int fence_fd;
if (!xwl_screen->glamor)
return FALSE;
if (!xwl_pixmap) {
ErrorF("XWAYLAND: Failed to set synchronization point, no backing xwl_pixmap!\n");
return FALSE;
}
acquire_point = ++xwl_pixmap->timeline_point;
release_point = ++xwl_pixmap->timeline_point;
if (!xwl_pixmap->syncobj) {
struct dri3_syncobj *syncobj = xwl_glamor_dri3_syncobj_create(xwl_screen);
if (!syncobj)
goto fail;
xwl_pixmap->syncobj = syncobj;
}
fence_fd = xwl_glamor_get_fence(xwl_screen);
if (fence_fd >= 0)
xwl_pixmap->syncobj->import_fence(xwl_pixmap->syncobj, acquire_point, fence_fd);
else
goto fail;
xwl_glamor_dri3_syncobj_passthrough(xwl_window,
xwl_pixmap->syncobj,
xwl_pixmap->syncobj,
acquire_point,
release_point);
return TRUE;
fail:
/* can't use explicit sync, we will do a glFinish() before presenting */
if (xwl_pixmap->syncobj) {
xwl_pixmap->syncobj->free(xwl_pixmap->syncobj);
xwl_pixmap->syncobj = NULL;
}
#endif /* DRI3 */
return FALSE;
}
void
xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap)
{
#ifdef DRI3
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
if (!xwl_screen->glamor || !xwl_pixmap)
return;
if (xwl_pixmap->syncobj) {
xwl_pixmap->syncobj->free(xwl_pixmap->syncobj);
xwl_pixmap->syncobj = NULL;
}
if (xwl_pixmap->efd >= 0) {
SetNotifyFd(xwl_pixmap->efd, NULL, 0, NULL);
close(xwl_pixmap->efd);
}
#endif /* DRI3 */
}
void
xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap)
{
#ifdef DRI3
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
int fence_fd;
if (!xwl_screen->glamor || !xwl_pixmap)
return;
if (xwl_pixmap->syncobj) {
fence_fd = xwl_pixmap->syncobj->export_fence(xwl_pixmap->syncobj,
xwl_pixmap->timeline_point);
xwl_glamor_wait_fence(xwl_screen, fence_fd);
close(fence_fd);
}
#endif /* DRI3 */
}
void
xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window,
PixmapPtr pixmap,
struct xwl_window_buffer *xwl_window_buffer)
{
#ifdef DRI3
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
if (!xwl_screen->glamor || !xwl_pixmap || !xwl_window_buffer)
return;
xwl_pixmap->xwl_window_buffer = xwl_window_buffer;
/* wait until the release fence is available before re-using this buffer */
xwl_pixmap->efd = eventfd(0, EFD_CLOEXEC);
SetNotifyFd(xwl_pixmap->efd, xwl_glamor_gbm_release_fence_avail, X_NOTIFY_READ,
xwl_pixmap);
xwl_pixmap->syncobj->submitted_eventfd(xwl_pixmap->syncobj,
xwl_pixmap->timeline_point,
xwl_pixmap->efd);
#endif /* DRI3 */
}
static Bool static Bool
xwl_glamor_try_to_make_context_current(struct xwl_screen *xwl_screen) xwl_glamor_try_to_make_context_current(struct xwl_screen *xwl_screen)
{ {

View File

@ -42,4 +42,12 @@ Bool xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen);
Bool xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen); Bool xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen);
drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen); drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen);
/* Explicit buffer synchronization points */
Bool xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap);
void xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap);
void xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap);
void xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window,
PixmapPtr pixmap,
struct xwl_window_buffer *xwl_window_buffer);
#endif /* XWAYLAND_GLAMOR_GBM_H */ #endif /* XWAYLAND_GLAMOR_GBM_H */