aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/packages/deb/ubuntu-focal/debian/rules2
-rw-r--r--contrib/packages/deb/ubuntu-jammy/debian/rules4
-rw-r--r--contrib/packages/deb/ubuntu-noble/debian/rules4
-rw-r--r--contrib/packages/rpm/el7/SPECS/tigervnc.spec4
-rw-r--r--contrib/packages/rpm/el8/SPECS/tigervnc.spec4
-rw-r--r--contrib/packages/rpm/el9/SPECS/tigervnc.spec4
-rw-r--r--unix/vncconfig/vncExt.h2
-rw-r--r--unix/xserver/hw/vnc/Makefile.am10
-rw-r--r--unix/xserver/hw/vnc/Xvnc.man6
-rw-r--r--unix/xserver/hw/vnc/vncDRI3.c537
-rw-r--r--unix/xserver/hw/vnc/vncDRI3.h43
-rw-r--r--unix/xserver/hw/vnc/vncDRI3Draw.c785
-rw-r--r--unix/xserver/hw/vnc/vncHooks.c69
-rw-r--r--unix/xserver/hw/vnc/xvnc.c21
-rw-r--r--unix/xserver120.patch132
-rw-r--r--unix/xserver21.1.1.patch38
-rw-r--r--unix/xserver21.patch67
17 files changed, 1634 insertions, 98 deletions
diff --git a/contrib/packages/deb/ubuntu-focal/debian/rules b/contrib/packages/deb/ubuntu-focal/debian/rules
index afb7830a..0245a065 100644
--- a/contrib/packages/deb/ubuntu-focal/debian/rules
+++ b/contrib/packages/deb/ubuntu-focal/debian/rules
@@ -102,7 +102,7 @@ config-stamp: xorg-source-stamp
--enable-xdmcp \
--enable-xdm-auth-1 \
--enable-glx \
- --disable-dri --enable-dri2 --disable-dri3 \
+ --disable-dri --enable-dri2 --enable-dri3 \
--enable-xinerama \
--enable-xf86vidmode \
--enable-xace \
diff --git a/contrib/packages/deb/ubuntu-jammy/debian/rules b/contrib/packages/deb/ubuntu-jammy/debian/rules
index 02e798c9..1b4fd6f8 100644
--- a/contrib/packages/deb/ubuntu-jammy/debian/rules
+++ b/contrib/packages/deb/ubuntu-jammy/debian/rules
@@ -45,7 +45,7 @@ XORG_SOURCE_ARCHIVE = /usr/src/xorg-server.tar.xz
xorg-source-stamp: $(XORG_SOURCE_ARCHIVE)
tar -C unix/xserver -axf $(XORG_SOURCE_ARCHIVE) --strip-components=1
- cd unix/xserver && patch -p1 < ../xserver21.1.1.patch
+ cd unix/xserver && patch -p1 < ../xserver21.patch
patch -p1 < debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch
touch xorg-source-stamp
@@ -102,7 +102,7 @@ config-stamp: xorg-source-stamp
--enable-xdmcp \
--enable-xdm-auth-1 \
--enable-glx \
- --disable-dri --enable-dri2 --disable-dri3 \
+ --disable-dri --enable-dri2 --enable-dri3 \
--enable-xinerama \
--enable-xf86vidmode \
--enable-xace \
diff --git a/contrib/packages/deb/ubuntu-noble/debian/rules b/contrib/packages/deb/ubuntu-noble/debian/rules
index 02e798c9..1b4fd6f8 100644
--- a/contrib/packages/deb/ubuntu-noble/debian/rules
+++ b/contrib/packages/deb/ubuntu-noble/debian/rules
@@ -45,7 +45,7 @@ XORG_SOURCE_ARCHIVE = /usr/src/xorg-server.tar.xz
xorg-source-stamp: $(XORG_SOURCE_ARCHIVE)
tar -C unix/xserver -axf $(XORG_SOURCE_ARCHIVE) --strip-components=1
- cd unix/xserver && patch -p1 < ../xserver21.1.1.patch
+ cd unix/xserver && patch -p1 < ../xserver21.patch
patch -p1 < debian/xorg-source-patches/516_tigervnc-xorg-manpages.patch
touch xorg-source-stamp
@@ -102,7 +102,7 @@ config-stamp: xorg-source-stamp
--enable-xdmcp \
--enable-xdm-auth-1 \
--enable-glx \
- --disable-dri --enable-dri2 --disable-dri3 \
+ --disable-dri --enable-dri2 --enable-dri3 \
--enable-xinerama \
--enable-xf86vidmode \
--enable-xace \
diff --git a/contrib/packages/rpm/el7/SPECS/tigervnc.spec b/contrib/packages/rpm/el7/SPECS/tigervnc.spec
index 38a5c49b..ee3baed8 100644
--- a/contrib/packages/rpm/el7/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el7/SPECS/tigervnc.spec
@@ -27,7 +27,7 @@ BuildRequires: xorg-x11-server-source
BuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel
BuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel
BuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel
-BuildRequires: pixman-devel, libdrm-devel,
+BuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel
BuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel
BuildRequires: xorg-x11-font-utils
BuildRequires: libXfont2-devel
@@ -159,7 +159,7 @@ autoreconf -fiv
--with-pic --disable-static \
--with-default-font-path="catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins" \
--with-xkb-output=%{_localstatedir}/lib/xkb \
- --enable-glx --disable-dri --enable-dri2 --disable-dri3 \
+ --enable-glx --disable-dri --enable-dri2 --enable-dri3 \
--disable-unit-tests \
--disable-config-hal \
--disable-config-udev \
diff --git a/contrib/packages/rpm/el8/SPECS/tigervnc.spec b/contrib/packages/rpm/el8/SPECS/tigervnc.spec
index 619ad414..307e26f6 100644
--- a/contrib/packages/rpm/el8/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el8/SPECS/tigervnc.spec
@@ -28,7 +28,7 @@ BuildRequires: xorg-x11-server-source
BuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel
BuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel
BuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel
-BuildRequires: pixman-devel, libdrm-devel,
+BuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel
BuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel
BuildRequires: xorg-x11-font-utils
BuildRequires: libXfont2-devel
@@ -152,7 +152,7 @@ autoreconf -fiv
--with-pic --disable-static \
--with-default-font-path="catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins" \
--with-xkb-output=%{_localstatedir}/lib/xkb \
- --enable-glx --disable-dri --enable-dri2 --disable-dri3 \
+ --enable-glx --disable-dri --enable-dri2 --enable-dri3 \
--disable-unit-tests \
--disable-config-hal \
--disable-config-udev \
diff --git a/contrib/packages/rpm/el9/SPECS/tigervnc.spec b/contrib/packages/rpm/el9/SPECS/tigervnc.spec
index 88d82dc4..5d120bc0 100644
--- a/contrib/packages/rpm/el9/SPECS/tigervnc.spec
+++ b/contrib/packages/rpm/el9/SPECS/tigervnc.spec
@@ -28,7 +28,7 @@ BuildRequires: xorg-x11-server-source
BuildRequires: libXext-devel, libX11-devel, libXi-devel, libXfixes-devel
BuildRequires: libXdamage-devel, libXrandr-devel, libXt-devel, libXdmcp-devel
BuildRequires: libXinerama-devel, mesa-libGL-devel, libxshmfence-devel
-BuildRequires: pixman-devel, libdrm-devel,
+BuildRequires: pixman-devel, libdrm-devel, mesa-libgbm-devel
BuildRequires: xorg-x11-util-macros, xorg-x11-xtrans-devel, libXtst-devel
BuildRequires: libXfont2-devel
# SELinux
@@ -151,7 +151,7 @@ autoreconf -fiv
--with-pic --disable-static \
--with-default-font-path="catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins" \
--with-xkb-output=%{_localstatedir}/lib/xkb \
- --enable-glx --disable-dri --enable-dri2 --disable-dri3 \
+ --enable-glx --disable-dri --enable-dri2 --enable-dri3 \
--disable-unit-tests \
--disable-config-hal \
--disable-config-udev \
diff --git a/unix/vncconfig/vncExt.h b/unix/vncconfig/vncExt.h
index 4383248c..5de1685d 100644
--- a/unix/vncconfig/vncExt.h
+++ b/unix/vncconfig/vncExt.h
@@ -64,7 +64,7 @@ typedef struct {
#ifdef _VNCEXT_PROTO_
-#define VNCEXTNAME "VNC-EXTENSION"
+#define VNCEXTNAME "TIGERVNC"
typedef struct {
CARD8 reqType; /* always VncExtReqCode */
diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am
index f9ed19d9..f9372183 100644
--- a/unix/xserver/hw/vnc/Makefile.am
+++ b/unix/xserver/hw/vnc/Makefile.am
@@ -42,6 +42,8 @@ Xvnc_SOURCES = xvnc.c \
# recommendation for coaxing automake.
nodist_EXTRA_Xvnc_SOURCES = dummy.cxx
+Xvnc_CPPFLAGS = $(AM_CPPFLAGS)
+
LOCAL_LIBS = \
$(XVNC_LIBS) \
$(XSERVER_LIBS) \
@@ -53,6 +55,14 @@ Xvnc_LDADD = $(LOCAL_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS)
Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
+if DRI3
+Xvnc_SOURCES += vncDRI3.h vncDRI3.c vncDRI3Draw.c
+Xvnc_CPPFLAGS += \
+ -I$(top_srcdir)/dri3 \
+ $(GBM_CFLAGS)
+Xvnc_LDADD += $(GBM_LIBS)
+endif
+
libvnc_la_LTLIBRARIES = libvnc.la
libvnc_ladir = $(moduledir)/extensions
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
index e43ba150..b9c429f7 100644
--- a/unix/xserver/hw/vnc/Xvnc.man
+++ b/unix/xserver/hw/vnc/Xvnc.man
@@ -46,6 +46,12 @@ Specify pixel format for server to use (BGRnnn or RGBnnn). The default for
depth 16 is RGB565 and for depth 24 and 32 is RGB888.
.
.TP
+.B \-rendernode \fIpath\fP
+DRM render node to use for DRI3 GPU acceleration. Specify an empty path to
+disable DRI3. Default is \fBauto\fP which makes \fBXvnc\fP pick a suitable
+available render node.
+.
+.TP
.B \-interface \fIIP address\fP
Listen on interface. By default Xvnc listens on all available interfaces.
.
diff --git a/unix/xserver/hw/vnc/vncDRI3.c b/unix/xserver/hw/vnc/vncDRI3.c
new file mode 100644
index 00000000..79b56f10
--- /dev/null
+++ b/unix/xserver/hw/vnc/vncDRI3.c
@@ -0,0 +1,537 @@
+/* Copyright 2024 Pierre Ossman for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <unistd.h>
+
+#ifdef HAVE_GBM
+#include <gbm.h>
+#endif
+
+#include "vncDRI3.h"
+#include <dri3.h>
+#include <fb.h>
+#include <misyncshm.h>
+
+#ifdef FB_ACCESS_WRAPPER
+#error "This code is not compatible with accessors"
+#endif
+
+const char *renderNode = "auto";
+
+static DevPrivateKeyRec vncDRI3ScreenPrivateKey;
+static DevPrivateKeyRec vncDRI3PixmapPrivateKey;
+
+typedef struct vncDRI3ScreenPrivate {
+ CloseScreenProcPtr CloseScreen;
+
+ DestroyPixmapProcPtr DestroyPixmap;
+
+#ifdef HAVE_GBM
+ const char *devicePath;
+ struct gbm_device *device;
+ int fd;
+#endif
+} vncDRI3ScreenPrivateRec, *vncDRI3ScreenPrivatePtr;
+
+typedef struct vncDRI3PixmapPrivate {
+#ifdef HAVE_GBM
+ struct gbm_bo *bo;
+#endif
+} vncDRI3PixmapPrivateRec, *vncDRI3PixmapPrivatePtr;
+
+#define wrap(priv, real, mem, func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->mem; \
+}
+
+static inline vncDRI3ScreenPrivatePtr vncDRI3ScreenPrivate(ScreenPtr screen)
+{
+ return (vncDRI3ScreenPrivatePtr)dixLookupPrivate(&(screen)->devPrivates, &vncDRI3ScreenPrivateKey);
+}
+
+static inline vncDRI3PixmapPrivatePtr vncDRI3PixmapPrivate(PixmapPtr pixmap)
+{
+ return (vncDRI3PixmapPrivatePtr)dixLookupPrivate(&(pixmap)->devPrivates, &vncDRI3PixmapPrivateKey);
+}
+
+static int vncDRI3Open(ScreenPtr screen, RRProviderPtr provider,
+ int *fd)
+{
+#ifdef HAVE_GBM
+ vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);
+
+ *fd = open(screenPriv->devicePath, O_RDWR|O_CLOEXEC);
+ if (*fd < 0)
+ return BadAlloc;
+
+ return Success;
+#else
+ return BadAlloc;
+#endif
+}
+
+/* Taken from glamor */
+#ifdef HAVE_GBM
+static uint32_t gbm_format_for_depth(CARD8 depth)
+{
+ switch (depth) {
+ case 16:
+ return GBM_FORMAT_RGB565;
+ case 24:
+ return GBM_FORMAT_XRGB8888;
+ case 30:
+ return GBM_FORMAT_ARGB2101010;
+ default:
+ ErrorF("unexpected depth: %d\n", depth);
+ case 32:
+ return GBM_FORMAT_ARGB8888;
+ }
+}
+#endif
+
+static PixmapPtr vncPixmapFromFd(ScreenPtr screen, int fd,
+ CARD16 width, CARD16 height,
+ CARD16 stride, CARD8 depth,
+ CARD8 bpp)
+{
+#ifdef HAVE_GBM
+ vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);
+ vncDRI3PixmapPrivatePtr pixmapPriv;
+
+ struct gbm_import_fd_data data;
+ struct gbm_bo *bo;
+ PixmapPtr pixmap;
+
+ if (bpp != sizeof(FbBits)*8) {
+ ErrorF("Incompatible bits per pixel given for GPU buffer\n");
+ return NULL;
+ }
+
+ if ((stride % sizeof(FbBits)) != 0) {
+ ErrorF("Incompatible stride given for GPU buffer\n");
+ return NULL;
+ }
+
+ data.fd = fd;
+ data.width = width;
+ data.height = height;
+ data.stride = stride;
+ data.format = gbm_format_for_depth(depth);
+
+ bo = gbm_bo_import(screenPriv->device, GBM_BO_IMPORT_FD, &data,
+ GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
+ if (bo == NULL)
+ return NULL;
+
+ pixmap = screen->CreatePixmap(screen, width, height, depth, 0);
+
+ pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+ pixmapPriv->bo = bo;
+
+ vncDRI3SyncPixmapFromGPU(pixmap);
+
+ return pixmap;
+#else
+ return NULL;
+#endif
+}
+
+static Bool vncDRI3DestroyPixmap(PixmapPtr pixmap)
+{
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);
+ Bool ret;
+
+#ifdef HAVE_GBM
+ if (pixmap->refcnt == 1) {
+ vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+
+ if (pixmapPriv->bo != NULL) {
+ gbm_bo_destroy(pixmapPriv->bo);
+ pixmapPriv->bo = NULL;
+ }
+ }
+#endif
+
+ unwrap(screenPriv, screen, DestroyPixmap);
+ ret = screen->DestroyPixmap(pixmap);
+ wrap(screenPriv, screen, DestroyPixmap, vncDRI3DestroyPixmap);
+
+ return ret;
+}
+
+#ifdef HAVE_GBM
+static int vncDRI3FdFromPixmapVisitWindow(WindowPtr window, void *data)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ PixmapPtr pixmap = data;
+
+ if ((*screen->GetWindowPixmap)(window) == pixmap)
+ window->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ return WT_WALKCHILDREN;
+}
+#endif
+
+static int vncFdFromPixmap(ScreenPtr screen, PixmapPtr pixmap,
+ CARD16 *stride, CARD32 *size)
+{
+#ifdef HAVE_GBM
+ vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);
+ vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+
+ if (pixmap->drawable.bitsPerPixel != sizeof(FbBits)*8) {
+ ErrorF("Incompatible bits per pixel given for pixmap\n");
+ return -1;
+ }
+
+ if (pixmapPriv->bo == NULL) {
+ /* GBM_BO_USE_LINEAR ? */
+ pixmapPriv->bo = gbm_bo_create(screenPriv->device,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ gbm_format_for_depth(pixmap->drawable.depth),
+ GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR);
+ if (pixmapPriv->bo == NULL) {
+ ErrorF("Failed to create GPU buffer: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if ((gbm_bo_get_stride(pixmapPriv->bo) % sizeof(FbBits)) != 0) {
+ ErrorF("Incompatible stride for created GPU buffer\n");
+ gbm_bo_destroy(pixmapPriv->bo);
+ pixmapPriv->bo = NULL;
+ return -1;
+ }
+
+ /* Force re-validation of any gc:s */
+ pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ WalkTree(screen, vncDRI3FdFromPixmapVisitWindow, pixmap);
+ }
+
+ vncDRI3SyncPixmapToGPU(pixmap);
+
+ *stride = gbm_bo_get_stride(pixmapPriv->bo);
+ /* FIXME */
+ *size = *stride * gbm_bo_get_height(pixmapPriv->bo);
+
+ return gbm_bo_get_fd(pixmapPriv->bo);
+#else
+ return -1;
+#endif
+}
+
+Bool vncDRI3IsHardwarePixmap(PixmapPtr pixmap)
+{
+#ifdef HAVE_GBM
+ vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+ return pixmapPriv->bo != NULL;
+#else
+ return FALSE;
+#endif
+}
+
+Bool vncDRI3IsHardwareDrawable(DrawablePtr drawable)
+{
+ PixmapPtr pixmap;
+ int xoff, yoff;
+
+ fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);
+ (void)xoff;
+ (void)yoff;
+
+ return vncDRI3IsHardwarePixmap(pixmap);
+}
+
+Bool vncDRI3SyncPixmapToGPU(PixmapPtr pixmap)
+{
+#ifdef HAVE_GBM
+ vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+
+ int width, height;
+
+ FbBits *bo_data;
+ uint32_t bo_stride;
+ void *map_data;
+ uint32_t bo_bpp;
+
+ FbBits *pixmap_data;
+ int pixmap_stride;
+ int pixmap_bpp;
+
+ pixman_bool_t ret;
+
+ if (pixmapPriv->bo == NULL)
+ return TRUE;
+
+ width = gbm_bo_get_width(pixmapPriv->bo);
+ height = gbm_bo_get_height(pixmapPriv->bo);
+
+ map_data = NULL;
+ bo_data = gbm_bo_map(pixmapPriv->bo, 0, 0, width, height,
+ GBM_BO_TRANSFER_WRITE, &bo_stride, &map_data);
+ if (bo_data == NULL) {
+ ErrorF("Could not map GPU buffer: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ bo_bpp = gbm_bo_get_bpp(pixmapPriv->bo);
+ assert(bo_bpp == sizeof(FbBits)*8);
+ assert((bo_stride % (bo_bpp/8)) == 0);
+
+ fbGetPixmapBitsData(pixmap, pixmap_data,
+ pixmap_stride, pixmap_bpp);
+ assert(pixmap_data != NULL);
+ assert(pixmap_bpp == sizeof(FbBits)*8);
+
+ assert(bo_bpp == pixmap_bpp);
+
+ /* Try accelerated copy first */
+ ret = pixman_blt((uint32_t*)pixmap_data, (uint32_t*)bo_data,
+ pixmap_stride, bo_stride / (bo_bpp/8),
+ pixmap_bpp, bo_bpp, 0, 0, 0, 0, width, height);
+ if (!ret) {
+ /* Fall back to slow pure C version */
+ fbBlt(pixmap_data, pixmap_stride, 0,
+ bo_data, bo_stride / (bo_bpp/8), 0,
+ width * bo_bpp, height,
+ GXcopy, FB_ALLONES, bo_bpp, FALSE, FALSE);
+ }
+
+ gbm_bo_unmap(pixmapPriv->bo, map_data);
+#endif
+
+ return TRUE;
+}
+
+Bool vncDRI3SyncPixmapFromGPU(PixmapPtr pixmap)
+{
+#ifdef HAVE_GBM
+ vncDRI3PixmapPrivatePtr pixmapPriv = vncDRI3PixmapPrivate(pixmap);
+
+ int width, height;
+
+ FbBits *bo_data;
+ uint32_t bo_stride;
+ void *map_data;
+ uint32_t bo_bpp;
+
+ FbBits *pixmap_data;
+ int pixmap_stride;
+ int pixmap_bpp;
+
+ pixman_bool_t ret;
+
+ if (pixmapPriv->bo == NULL)
+ return TRUE;
+
+ width = gbm_bo_get_width(pixmapPriv->bo);
+ height = gbm_bo_get_height(pixmapPriv->bo);
+
+ map_data = NULL;
+ bo_data = gbm_bo_map(pixmapPriv->bo, 0, 0, width, height,
+ GBM_BO_TRANSFER_READ, &bo_stride, &map_data);
+ if (bo_data == NULL) {
+ ErrorF("Could not map GPU buffer: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ bo_bpp = gbm_bo_get_bpp(pixmapPriv->bo);
+ assert(bo_bpp == sizeof(FbBits)*8);
+ assert((bo_stride % (bo_bpp/8)) == 0);
+
+ fbGetPixmapBitsData(pixmap, pixmap_data,
+ pixmap_stride, pixmap_bpp);
+ assert(pixmap_data != NULL);
+ assert(pixmap_bpp == sizeof(FbBits)*8);
+
+ assert(bo_bpp == pixmap_bpp);
+
+ /* Try accelerated copy first */
+ ret = pixman_blt((uint32_t*)bo_data, (uint32_t*)pixmap_data,
+ bo_stride / (bo_bpp/8), pixmap_stride,
+ bo_bpp, pixmap_bpp, 0, 0, 0, 0, width, height);
+ if (!ret) {
+ /* Fall back to slow pure C version */
+ fbBlt(bo_data, bo_stride / (bo_bpp/8), 0,
+ pixmap_data, pixmap_stride, 0,
+ width * bo_bpp, height,
+ GXcopy, FB_ALLONES, bo_bpp, FALSE, FALSE);
+ }
+
+ gbm_bo_unmap(pixmapPriv->bo, map_data);
+#endif
+
+ return TRUE;
+}
+
+Bool vncDRI3SyncDrawableToGPU(DrawablePtr drawable)
+{
+ PixmapPtr pixmap;
+ int xoff, yoff;
+
+ fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);
+ (void)xoff;
+ (void)yoff;
+
+ return vncDRI3SyncPixmapToGPU(pixmap);
+}
+
+Bool vncDRI3SyncDrawableFromGPU(DrawablePtr drawable)
+{
+ PixmapPtr pixmap;
+ int xoff, yoff;
+
+ fbGetDrawablePixmap(drawable, pixmap, xoff, yoff);
+ (void)xoff;
+ (void)yoff;
+
+ return vncDRI3SyncPixmapFromGPU(pixmap);
+}
+
+static const dri3_screen_info_rec vncDRI3ScreenInfo = {
+ .version = 1,
+
+ .open = vncDRI3Open,
+ .pixmap_from_fd = vncPixmapFromFd,
+ .fd_from_pixmap = vncFdFromPixmap,
+};
+
+static Bool vncDRI3CloseScreen(ScreenPtr screen)
+{
+ vncDRI3ScreenPrivatePtr screenPriv = vncDRI3ScreenPrivate(screen);
+
+ unwrap(screenPriv, screen, CloseScreen);
+
+ unwrap(screenPriv, screen, DestroyPixmap);
+
+#ifdef HAVE_GBM
+ gbm_device_destroy(screenPriv->device);
+ screenPriv->device = NULL;
+
+ close(screenPriv->fd);
+ screenPriv->fd = -1;
+#endif
+
+ return (*screen->CloseScreen)(screen);
+}
+
+Bool vncDRI3Init(ScreenPtr screen)
+{
+ vncDRI3ScreenPrivatePtr screenPriv;
+
+ /*
+ * We don't queue any gbm operations, so we don't have to do anything
+ * more than simply activate this extension.
+ */
+#ifdef HAVE_XSHMFENCE
+ if (!miSyncShmScreenInit(screen))
+ return FALSE;
+#endif
+
+ /* Empty render node is interpreted as disabling DRI3 */
+ if (renderNode[0] == '\0')
+ return TRUE;
+
+ if ((renderNode[0] != '/') &&
+ (strcasecmp(renderNode, "auto") != 0)) {
+ ErrorF("Invalid render node path \"%s\"\n", renderNode);
+ return FALSE;
+ }
+
+ if (!dixRegisterPrivateKey(&vncDRI3ScreenPrivateKey, PRIVATE_SCREEN,
+ sizeof(vncDRI3ScreenPrivateRec)))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&vncDRI3PixmapPrivateKey, PRIVATE_PIXMAP,
+ sizeof(vncDRI3PixmapPrivateRec)))
+ return FALSE;
+
+ if (!vncDRI3DrawInit(screen))
+ return FALSE;
+
+#ifdef HAVE_GBM
+ screenPriv = vncDRI3ScreenPrivate(screen);
+
+ if (strcasecmp(renderNode, "auto") == 0) {
+ glob_t globbuf;
+ int ret;
+
+ ret = glob("/dev/dri/renderD*", 0, NULL, &globbuf);
+ if (ret == GLOB_NOMATCH) {
+ ErrorF("Could not find any render nodes\n");
+ return FALSE;
+ }
+ if (ret != 0) {
+ ErrorF("Failure enumerating render nodes\n");
+ return FALSE;
+ }
+
+ screenPriv->devicePath = NULL;
+ for (size_t i = 0;i < globbuf.gl_pathc;i++) {
+ if (access(globbuf.gl_pathv[i], R_OK|W_OK) == 0) {
+ screenPriv->devicePath = strdup(globbuf.gl_pathv[i]);
+ break;
+ }
+ }
+
+ globfree(&globbuf);
+
+ if (screenPriv->devicePath == NULL) {
+ ErrorF("Could not find any available render nodes\n");
+ return FALSE;
+ }
+ } else {
+ screenPriv->devicePath = renderNode;
+ }
+
+ screenPriv->fd = open(screenPriv->devicePath, O_RDWR|O_CLOEXEC);
+ if (screenPriv->fd < 0) {
+ ErrorF("Failed to open \"%s\": %s\n",
+ screenPriv->devicePath, strerror(errno));
+ return FALSE;
+ }
+
+ screenPriv->device = gbm_create_device(screenPriv->fd);
+ if (screenPriv->device == NULL) {
+ close(screenPriv->fd);
+ screenPriv->fd = -1;
+ ErrorF("Could create GPU render device\n");
+ return FALSE;
+ }
+#else
+ ErrorF("Built without GBM support\n");
+ return FALSE;
+#endif
+
+ wrap(screenPriv, screen, CloseScreen, vncDRI3CloseScreen);
+
+ wrap(screenPriv, screen, DestroyPixmap, vncDRI3DestroyPixmap);
+
+ return dri3_screen_init(screen, &vncDRI3ScreenInfo);
+}
diff --git a/unix/xserver/hw/vnc/vncDRI3.h b/unix/xserver/hw/vnc/vncDRI3.h
new file mode 100644
index 00000000..4f89a25a
--- /dev/null
+++ b/unix/xserver/hw/vnc/vncDRI3.h
@@ -0,0 +1,43 @@
+/* Copyright 2024 Pierre Ossman for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __VNCDRI3_H__
+#define __VNCDRI3_H__
+
+#ifdef DRI3
+
+#include <dix.h>
+
+extern const char *renderNode;
+
+Bool vncDRI3Init(ScreenPtr screen);
+
+Bool vncDRI3IsHardwarePixmap(PixmapPtr pixmap);
+Bool vncDRI3IsHardwareDrawable(DrawablePtr drawable);
+
+Bool vncDRI3SyncPixmapToGPU(PixmapPtr pixmap);
+Bool vncDRI3SyncPixmapFromGPU(PixmapPtr pixmap);
+
+Bool vncDRI3SyncDrawableToGPU(DrawablePtr drawable);
+Bool vncDRI3SyncDrawableFromGPU(DrawablePtr drawable);
+
+Bool vncDRI3DrawInit(ScreenPtr screen);
+
+#endif
+
+#endif
diff --git a/unix/xserver/hw/vnc/vncDRI3Draw.c b/unix/xserver/hw/vnc/vncDRI3Draw.c
new file mode 100644
index 00000000..8aa6625d
--- /dev/null
+++ b/unix/xserver/hw/vnc/vncDRI3Draw.c
@@ -0,0 +1,785 @@
+/* Copyright 2024 Pierre Ossman for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "vncDRI3.h"
+
+#include <fb.h>
+#include <gcstruct.h>
+#include <pixmapstr.h>
+
+static DevPrivateKeyRec vncDRI3DrawScreenPrivateKey;
+static DevPrivateKeyRec vncDRI3GCPrivateKey;
+
+typedef struct vncDRI3DrawScreenPrivateRec {
+ CloseScreenProcPtr CloseScreen;
+
+ CreateGCProcPtr CreateGC;
+ SourceValidateProcPtr SourceValidate;
+
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+ CompositeRectsProcPtr CompositeRects;
+ TrapezoidsProcPtr Trapezoids;
+ TrianglesProcPtr Triangles;
+ TriStripProcPtr TriStrip;
+ TriFanProcPtr TriFan;
+} vncDRI3DrawScreenPrivateRec, *vncDRI3DrawScreenPrivatePtr;
+
+typedef struct vncDRI3GCPrivateRec {
+ const GCFuncs *funcs;
+ const GCOps *ops;
+} vncDRI3GCPrivateRec, *vncDRI3GCPrivatePtr;
+
+#define wrap(priv, real, mem, func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->mem; \
+}
+
+static inline vncDRI3DrawScreenPrivatePtr vncDRI3DrawScreenPrivate(ScreenPtr screen)
+{
+ return (vncDRI3DrawScreenPrivatePtr)dixLookupPrivate(&(screen)->devPrivates, &vncDRI3DrawScreenPrivateKey);
+}
+
+static inline vncDRI3GCPrivatePtr vncDRI3GCPrivate(GCPtr gc)
+{
+ return (vncDRI3GCPrivatePtr)dixLookupPrivate(&(gc)->devPrivates, &vncDRI3GCPrivateKey);
+}
+
+static GCFuncs vncDRI3GCFuncs;
+static GCOps vncDRI3GCOps;
+
+/* GC functions */
+
+static void vncDRI3ValidateGC(GCPtr gc, unsigned long changes,
+ DrawablePtr drawable)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ unwrap(gcPriv, gc, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, gc, ops);
+
+ (*gc->funcs->ValidateGC)(gc, changes, drawable);
+
+ if (vncDRI3IsHardwareDrawable(drawable)) {
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ } else {
+ gcPriv->ops = NULL;
+ }
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3ChangeGC(GCPtr gc, unsigned long mask)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ unwrap(gcPriv, gc, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, gc, ops);
+ (*gc->funcs->ChangeGC)(gc, mask);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3CopyGC(GCPtr src, unsigned long mask, GCPtr dst)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(dst);
+ unwrap(gcPriv, dst, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, dst, ops);
+ (*dst->funcs->CopyGC)(src, mask, dst);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, dst, ops, &vncDRI3GCOps);
+ wrap(gcPriv, dst, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3DestroyGC(GCPtr gc)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ unwrap(gcPriv, gc, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, gc, ops);
+ (*gc->funcs->DestroyGC)(gc);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3ChangeClip(GCPtr gc, int type, void *value, int nrects)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ unwrap(gcPriv, gc, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, gc, ops);
+ (*gc->funcs->ChangeClip)(gc, type, value, nrects);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3DestroyClip(GCPtr gc)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ unwrap(gcPriv, gc, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, gc, ops);
+ (*gc->funcs->DestroyClip)(gc);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+}
+
+static void vncDRI3CopyClip(GCPtr dst, GCPtr src)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(dst);
+ unwrap(gcPriv, dst, funcs);
+ if (gcPriv->ops != NULL)
+ unwrap(gcPriv, dst, ops);
+ (*dst->funcs->CopyClip)(dst, src);
+ if (gcPriv->ops != NULL)
+ wrap(gcPriv, dst, ops, &vncDRI3GCOps);
+ wrap(gcPriv, dst, funcs, &vncDRI3GCFuncs);
+}
+
+/* GC operations */
+
+static void vncDRI3FillSpans(DrawablePtr drawable, GCPtr gc, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int fSorted)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->FillSpans)(drawable, gc, nInit, pptInit, pwidthInit, fSorted);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3SetSpans(DrawablePtr drawable, GCPtr gc, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans,
+ int fSorted)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->SetSpans)(drawable, gc, psrc, ppt, pwidth, nspans, fSorted);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PutImage(DrawablePtr drawable, GCPtr gc, int depth,
+ int x, int y, int w, int h, int leftPad,
+ int format, char *pBits)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PutImage)(drawable, gc, depth, x, y, w, h, leftPad, format, pBits);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static RegionPtr vncDRI3CopyArea(DrawablePtr src, DrawablePtr dst,
+ GCPtr gc, int srcx, int srcy,
+ int w, int h, int dstx, int dsty)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ RegionPtr ret;
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(dst);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ ret = (*gc->ops->CopyArea)(src, dst, gc, srcx, srcy, w, h, dstx, dsty);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(dst);
+
+ return ret;
+}
+
+static RegionPtr vncDRI3CopyPlane(DrawablePtr src, DrawablePtr dst,
+ GCPtr gc, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ RegionPtr ret;
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(dst);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ ret = (*gc->ops->CopyPlane)(src, dst, gc, srcx, srcy, w, h, dstx, dsty, plane);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(dst);
+
+ return ret;
+}
+
+static void vncDRI3PolyPoint(DrawablePtr drawable, GCPtr gc, int mode,
+ int npt, xPoint *pts)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyPoint)(drawable, gc, mode, npt, pts);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3Polylines(DrawablePtr drawable, GCPtr gc, int mode,
+ int npt, DDXPointPtr ppts)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->Polylines)(drawable, gc, mode, npt, ppts);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolySegment(DrawablePtr drawable, GCPtr gc, int nseg,
+ xSegment *segs)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolySegment)(drawable, gc, nseg, segs);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolyRectangle(DrawablePtr drawable, GCPtr gc,
+ int nrects, xRectangle *rects)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyRectangle)(drawable, gc, nrects, rects);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolyArc(DrawablePtr drawable, GCPtr gc, int narcs,
+ xArc *arcs)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyArc)(drawable, gc, narcs, arcs);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3FillPolygon(DrawablePtr drawable, GCPtr gc,
+ int shape, int mode, int count,
+ DDXPointPtr pts)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->FillPolygon)(drawable, gc, shape, mode, count, pts);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolyFillRect(DrawablePtr drawable, GCPtr gc,
+ int nrects, xRectangle *rects)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyFillRect)(drawable, gc, nrects, rects);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolyFillArc(DrawablePtr drawable, GCPtr gc,
+ int narcs, xArc *arcs)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyFillArc)(drawable, gc, narcs, arcs);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static int vncDRI3PolyText8(DrawablePtr drawable, GCPtr gc,
+ int x, int y, int count, char *chars)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ int ret;
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ ret = (*gc->ops->PolyText8)(drawable, gc, x, y, count, chars);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+
+ return ret;
+}
+
+static int vncDRI3PolyText16(DrawablePtr drawable, GCPtr gc,
+ int x, int y, int count,
+ unsigned short *chars)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+ int ret;
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ ret = (*gc->ops->PolyText16)(drawable, gc, x, y, count, chars);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+
+ return ret;
+}
+
+static void vncDRI3ImageText8(DrawablePtr drawable, GCPtr gc,
+ int x, int y, int count, char *chars)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->ImageText8)(drawable, gc, x, y, count, chars);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3ImageText16(DrawablePtr drawable, GCPtr gc,
+ int x, int y, int count,
+ unsigned short *chars)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->ImageText16)(drawable, gc, x, y, count, chars);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3ImageGlyphBlt(DrawablePtr drawable, GCPtr gc, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, void * pglyphBase)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->ImageGlyphBlt)(drawable, gc, x, y, nglyph, ppci, pglyphBase);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PolyGlyphBlt(DrawablePtr drawable, GCPtr gc, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, void * pglyphBase)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PolyGlyphBlt)(drawable, gc, x, y, nglyph, ppci, pglyphBase);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static void vncDRI3PushPixels(GCPtr gc, PixmapPtr pBitMap,
+ DrawablePtr drawable,
+ int w, int h, int x, int y)
+{
+ vncDRI3GCPrivatePtr gcPriv = vncDRI3GCPrivate(gc);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(gcPriv, gc, funcs);
+ unwrap(gcPriv, gc, ops);
+ (*gc->ops->PushPixels)(gc, pBitMap, drawable, w, h, x, y);
+ wrap(gcPriv, gc, ops, &vncDRI3GCOps);
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ vncDRI3SyncDrawableToGPU(drawable);
+}
+
+static GCFuncs vncDRI3GCFuncs = {
+ .ValidateGC = vncDRI3ValidateGC,
+ .ChangeGC = vncDRI3ChangeGC,
+ .CopyGC = vncDRI3CopyGC,
+ .DestroyGC = vncDRI3DestroyGC,
+ .ChangeClip = vncDRI3ChangeClip,
+ .DestroyClip = vncDRI3DestroyClip,
+ .CopyClip = vncDRI3CopyClip,
+};
+
+static GCOps vncDRI3GCOps = {
+ .FillSpans = vncDRI3FillSpans,
+ .SetSpans = vncDRI3SetSpans,
+ .PutImage = vncDRI3PutImage,
+ .CopyArea = vncDRI3CopyArea,
+ .CopyPlane = vncDRI3CopyPlane,
+ .PolyPoint = vncDRI3PolyPoint,
+ .Polylines = vncDRI3Polylines,
+ .PolySegment = vncDRI3PolySegment,
+ .PolyRectangle = vncDRI3PolyRectangle,
+ .PolyArc = vncDRI3PolyArc,
+ .FillPolygon = vncDRI3FillPolygon,
+ .PolyFillRect = vncDRI3PolyFillRect,
+ .PolyFillArc = vncDRI3PolyFillArc,
+ .PolyText8 = vncDRI3PolyText8,
+ .PolyText16 = vncDRI3PolyText16,
+ .ImageText8 = vncDRI3ImageText8,
+ .ImageText16 = vncDRI3ImageText16,
+ .ImageGlyphBlt = vncDRI3ImageGlyphBlt,
+ .PolyGlyphBlt = vncDRI3PolyGlyphBlt,
+ .PushPixels = vncDRI3PushPixels,
+};
+
+static Bool vncDRI3CreateGC(GCPtr gc)
+{
+ ScreenPtr screen = gc->pScreen;
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+ vncDRI3GCPrivatePtr gcPriv;
+ Bool ret;
+
+ unwrap(screenPriv, screen, CreateGC);
+ ret = (*screen->CreateGC)(gc);
+ wrap(screenPriv, screen, CreateGC, vncDRI3CreateGC);
+
+ gcPriv = vncDRI3GCPrivate(gc);
+
+ wrap(gcPriv, gc, funcs, &vncDRI3GCFuncs);
+
+ return ret;
+}
+
+static void vncDRI3SourceValidate(DrawablePtr drawable,
+ int x, int y,
+ int width, int height,
+ unsigned int subWindowMode)
+{
+ ScreenPtr screen = drawable->pScreen;
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ /* FIXME: Compute what we need to sync */
+ vncDRI3SyncDrawableFromGPU(drawable);
+
+ unwrap(screenPriv, screen, SourceValidate);
+ screen->SourceValidate(drawable, x, y, width, height, subWindowMode);
+ wrap(screenPriv, screen, SourceValidate, vncDRI3SourceValidate);
+}
+
+static void vncDRI3Composite(CARD8 op, PicturePtr pSrc,
+ PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, Composite);
+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ wrap(screenPriv, ps, Composite, vncDRI3Composite);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3Glyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc, int nlists,
+ GlyphListPtr lists, GlyphPtr * glyphs)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, Glyphs);
+ (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ nlists, lists, glyphs);
+ wrap(screenPriv, ps, Glyphs, vncDRI3Glyphs);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3CompositeRects(CARD8 op, PicturePtr pDst,
+ xRenderColor * color, int nRect, xRectangle *rects)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, CompositeRects);
+ (*ps->CompositeRects)(op, pDst, color, nRect, rects);
+ wrap(screenPriv, ps, CompositeRects, vncDRI3CompositeRects);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3Trapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid * traps)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ /* FIXME: Rarely used, so we just sync everything */
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, Trapezoids);
+ (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ ntrap, traps);
+ wrap(screenPriv, ps, Trapezoids, vncDRI3Trapezoids);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3Triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle * tris)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ /* FIXME: Rarely used, so we just sync everything */
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, Triangles);
+ (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
+ wrap(screenPriv, ps, Triangles, vncDRI3Triangles);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3TriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed * points)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ /* FIXME: Rarely used, so we just sync everything */
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, TriStrip);
+ (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ npoint, points);
+ wrap(screenPriv, ps, TriStrip, vncDRI3TriStrip)
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static void vncDRI3TriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed * points)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(screen);
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ /* FIXME: Rarely used, so we just sync everything */
+ vncDRI3SyncDrawableFromGPU(pDst->pDrawable);
+
+ unwrap(screenPriv, ps, TriFan);
+ (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);
+ wrap(screenPriv, ps, TriFan, vncDRI3TriFan);
+
+ vncDRI3SyncDrawableToGPU(pDst->pDrawable);
+}
+
+static Bool vncDRI3DrawCloseScreen(ScreenPtr screen)
+{
+ vncDRI3DrawScreenPrivatePtr screenPriv = vncDRI3DrawScreenPrivate(screen);
+ PictureScreenPtr ps;
+
+ unwrap(screenPriv, screen, CloseScreen);
+
+ unwrap(screenPriv, screen, CreateGC);
+ unwrap(screenPriv, screen, SourceValidate);
+
+ ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ unwrap(screenPriv, ps, Composite);
+ unwrap(screenPriv, ps, Glyphs);
+ unwrap(screenPriv, ps, CompositeRects);
+ unwrap(screenPriv, ps, Trapezoids);
+ unwrap(screenPriv, ps, Triangles);
+ unwrap(screenPriv, ps, TriStrip);
+ unwrap(screenPriv, ps, TriFan);
+ }
+
+ return (*screen->CloseScreen)(screen);
+}
+
+Bool vncDRI3DrawInit(ScreenPtr screen)
+{
+ vncDRI3DrawScreenPrivatePtr screenPriv;
+ PictureScreenPtr ps;
+
+ if (!dixRegisterPrivateKey(&vncDRI3DrawScreenPrivateKey,
+ PRIVATE_SCREEN,
+ sizeof(vncDRI3DrawScreenPrivateRec)))
+ return FALSE;
+ if (!dixRegisterPrivateKey(&vncDRI3GCPrivateKey, PRIVATE_GC,
+ sizeof(vncDRI3GCPrivateRec)))
+ return FALSE;
+
+ screenPriv = vncDRI3DrawScreenPrivate(screen);
+
+ wrap(screenPriv, screen, CloseScreen, vncDRI3DrawCloseScreen);
+
+ wrap(screenPriv, screen, CreateGC, vncDRI3CreateGC);
+ wrap(screenPriv, screen, SourceValidate, vncDRI3SourceValidate);
+
+ ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ wrap(screenPriv, ps, Composite, vncDRI3Composite);
+ wrap(screenPriv, ps, Glyphs, vncDRI3Glyphs);
+ wrap(screenPriv, ps, CompositeRects, vncDRI3CompositeRects);
+ wrap(screenPriv, ps, Trapezoids, vncDRI3Trapezoids);
+ wrap(screenPriv, ps, Triangles, vncDRI3Triangles);
+ wrap(screenPriv, ps, TriStrip, vncDRI3TriStrip);
+ wrap(screenPriv, ps, TriFan, vncDRI3TriFan);
+ }
+
+ return TRUE;
+} \ No newline at end of file
diff --git a/unix/xserver/hw/vnc/vncHooks.c b/unix/xserver/hw/vnc/vncHooks.c
index 3838c10d..7fe35ada 100644
--- a/unix/xserver/hw/vnc/vncHooks.c
+++ b/unix/xserver/hw/vnc/vncHooks.c
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2017 Pierre Ossman for Cendio AB
+ * Copyright 2009-2024 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -469,39 +469,47 @@ static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr pOldRegion)
{
int dx, dy;
- BoxRec screen_box;
- RegionRec copied, screen_rgn;
+ RegionRec copied;
SCREEN_PROLOGUE(pWin->drawable.pScreen, CopyWindow);
- RegionNull(&copied);
- RegionCopy(&copied, pOldRegion);
+ if (is_visible(&pWin->drawable)) {
+ BoxRec screen_box;
+ RegionRec screen_rgn;
- screen_box.x1 = 0;
- screen_box.y1 = 0;
- screen_box.x2 = pScreen->width;
- screen_box.y2 = pScreen->height;
+ RegionNull(&copied);
+ RegionCopy(&copied, pOldRegion);
- RegionInitBoxes(&screen_rgn, &screen_box, 1);
+ screen_box.x1 = 0;
+ screen_box.y1 = 0;
+ screen_box.x2 = pScreen->width;
+ screen_box.y2 = pScreen->height;
- dx = pWin->drawable.x - ptOldOrg.x;
- dy = pWin->drawable.y - ptOldOrg.y;
+ RegionInitBoxes(&screen_rgn, &screen_box, 1);
- // RFB tracks copies in terms of destination rectangle, not source.
- // We also need to copy with changes to the Window's clipping region.
- // Finally, make sure we don't get copies to or from regions outside
- // the framebuffer.
- RegionIntersect(&copied, &copied, &screen_rgn);
- RegionTranslate(&copied, dx, dy);
- RegionIntersect(&copied, &copied, &screen_rgn);
- RegionIntersect(&copied, &copied, &pWin->borderClip);
+ dx = pWin->drawable.x - ptOldOrg.x;
+ dy = pWin->drawable.y - ptOldOrg.y;
+
+ // RFB tracks copies in terms of destination rectangle, not source.
+ // We also need to copy with changes to the Window's clipping region.
+ // Finally, make sure we don't get copies to or from regions outside
+ // the framebuffer.
+ RegionIntersect(&copied, &copied, &screen_rgn);
+ RegionTranslate(&copied, dx, dy);
+ RegionIntersect(&copied, &copied, &screen_rgn);
+ RegionIntersect(&copied, &copied, &pWin->borderClip);
+
+ RegionUninit(&screen_rgn);
+ } else {
+ RegionNull(&copied);
+ dx = dy = 0;
+ }
(*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
add_copied(pScreen, &copied, dx, dy);
RegionUninit(&copied);
- RegionUninit(&screen_rgn);
SCREEN_EPILOGUE(CopyWindow);
}
@@ -512,18 +520,23 @@ static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
int h, Bool generateExposures)
{
- BoxRec box;
RegionRec reg;
SCREEN_PROLOGUE(pWin->drawable.pScreen, ClearToBackground);
- box.x1 = x + pWin->drawable.x;
- box.y1 = y + pWin->drawable.y;
- box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
- box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
+ if (is_visible(&pWin->drawable)) {
+ BoxRec box;
- RegionInitBoxes(&reg, &box, 1);
- RegionIntersect(&reg, &reg, &pWin->clipList);
+ box.x1 = x + pWin->drawable.x;
+ box.y1 = y + pWin->drawable.y;
+ box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
+ box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
+
+ RegionInitBoxes(&reg, &box, 1);
+ RegionIntersect(&reg, &reg, &pWin->clipList);
+ } else {
+ RegionNull(&reg);
+ }
(*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c
index 4ee1cd1b..45da17fb 100644
--- a/unix/xserver/hw/vnc/xvnc.c
+++ b/unix/xserver/hw/vnc/xvnc.c
@@ -36,6 +36,7 @@ from the X Consortium.
#include "RFBGlue.h"
#include "XorgGlue.h"
#include "RandrGlue.h"
+#include "vncDRI3.h"
#include "vncPresent.h"
#include "xorg-version.h"
@@ -222,6 +223,9 @@ ddxUseMsg(void)
ErrorF("-inetd has been launched from inetd\n");
ErrorF
("-noclipboard disable clipboard settings modification via vncconfig utility\n");
+#ifdef DRI3
+ ErrorF("-rendernode PATH DRM render node to use for DRI3\n");
+#endif
ErrorF("-verbose [n] verbose startup messages\n");
ErrorF("-quiet minimal startup messages\n");
ErrorF("-version show the server version\n");
@@ -404,6 +408,15 @@ ddxProcessArgument(int argc, char *argv[], int i)
return 1;
}
+#ifdef DRI3
+ if (strcmp(argv[i], "-rendernode") == 0) {
+ CHECK_FOR_REQUIRED_ARGUMENTS(1);
+ ++i;
+ renderNode = argv[i];
+ return 2;
+ }
+#endif
+
if (!strcmp(argv[i], "-verbose")) {
if (++i < argc && argv[i]) {
char *end;
@@ -1088,6 +1101,12 @@ vncScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!ret)
ErrorF("Failed to initialize Present extension\n");
+#ifdef DRI3
+ ret = vncDRI3Init(pScreen);
+ if (!ret)
+ ErrorF("Failed to initialize DRI3 extension\n");
+#endif
+
return TRUE;
} /* end vncScreenInit */
@@ -1110,7 +1129,7 @@ extern void GlxExtensionInit(void);
#endif
static const ExtensionModule vncExtensions[] = {
- {vncExtensionInit, "VNC-EXTENSION", NULL},
+ {vncExtensionInit, "TIGERVNC", NULL},
#ifdef GLXEXT
#if XORG_OLDER_THAN(1, 20, 0)
{ GlxExtensionInit, "GLX", &noGlxExtension },
diff --git a/unix/xserver120.patch b/unix/xserver120.patch
index 2f555eeb..9bc51822 100644
--- a/unix/xserver120.patch
+++ b/unix/xserver120.patch
@@ -1,7 +1,7 @@
-Index: xserver/configure.ac
-===================================================================
---- xserver.orig/configure.ac
-+++ xserver/configure.ac
+diff --git a/configure.ac b/configure.ac
+index 0909cc5b4..c01873200 100644
+--- a/configure.ac
++++ b/configure.ac
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
AC_CONFIG_HEADERS(include/version-config.h)
@@ -10,17 +10,30 @@ Index: xserver/configure.ac
AC_PROG_LN_S
LT_PREREQ([2.2])
LT_INIT([disable-static win32-dll])
-@@ -1777,6 +1778,9 @@ if test "x$XVFB" = xyes; then
+@@ -1735,6 +1736,14 @@ if test "x$XVFB" = xyes; then
AC_SUBST([XVFB_SYS_LIBS])
fi
+dnl Xvnc DDX
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
++
++PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
++if test "x$GBM" = xyes; then
++ AC_DEFINE(HAVE_GBM, 1, [Have GBM support])
++fi
dnl Xnest DDX
-@@ -2565,6 +2571,7 @@ hw/dmx/Makefile
+@@ -2058,7 +2067,6 @@ if test "x$GLAMOR" = xyes; then
+ [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])],
+ [])
+
+- PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+ if test "x$GBM" = xyes; then
+ AC_DEFINE(GLAMOR_HAS_GBM, 1,
+ [Build glamor with GBM-based EGL support])
+@@ -2523,6 +2531,7 @@ hw/dmx/Makefile
hw/dmx/man/Makefile
hw/vfb/Makefile
hw/vfb/man/Makefile
@@ -28,17 +41,98 @@ Index: xserver/configure.ac
hw/xnest/Makefile
hw/xnest/man/Makefile
hw/xwin/Makefile
-Index: xserver/hw/Makefile.am
-===================================================================
---- xserver.orig/hw/Makefile.am
-+++ xserver/hw/Makefile.am
-@@ -38,7 +38,8 @@ SUBDIRS = \
- $(DMX_SUBDIRS) \
- $(KDRIVE_SUBDIRS) \
- $(XQUARTZ_SUBDIRS) \
-- $(XWAYLAND_SUBDIRS)
-+ $(XWAYLAND_SUBDIRS) \
-+ vnc
-
- DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
+diff --git a/dri3/Makefile.am b/dri3/Makefile.am
+index e47a734e0..99c3718a5 100644
+--- a/dri3/Makefile.am
++++ b/dri3/Makefile.am
+@@ -1,7 +1,7 @@
+ noinst_LTLIBRARIES = libdri3.la
+ AM_CFLAGS = \
+- -DHAVE_XORG_CONFIG_H \
+- @DIX_CFLAGS@ @XORG_CFLAGS@
++ @DIX_CFLAGS@ \
++ @LIBDRM_CFLAGS@
+
+ libdri3_la_SOURCES = \
+ dri3.h \
+diff --git a/dri3/dri3.c b/dri3/dri3.c
+index ba32facd7..191252969 100644
+--- a/dri3/dri3.c
++++ b/dri3/dri3.c
+@@ -20,10 +20,6 @@
+ * OF THIS SOFTWARE.
+ */
+
+-#ifdef HAVE_XORG_CONFIG_H
+-#include <xorg-config.h>
+-#endif
+-
+ #include "dri3_priv.h"
+
+ #include <drm_fourcc.h>
+diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
+index b087a9529..f319d1770 100644
+--- a/dri3/dri3_priv.h
++++ b/dri3/dri3_priv.h
+@@ -23,6 +23,7 @@
+ #ifndef _DRI3PRIV_H_
+ #define _DRI3PRIV_H_
+
++#include "dix-config.h"
+ #include <X11/X.h>
+ #include "scrnintstr.h"
+ #include "misc.h"
+diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
+index 958877efa..687168930 100644
+--- a/dri3/dri3_request.c
++++ b/dri3/dri3_request.c
+@@ -20,10 +20,6 @@
+ * OF THIS SOFTWARE.
+ */
+
+-#ifdef HAVE_XORG_CONFIG_H
+-#include <xorg-config.h>
+-#endif
+-
+ #include "dri3_priv.h"
+ #include <syncsrv.h>
+ #include <unistd.h>
+diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
+index b98259753..3c7e5bf60 100644
+--- a/dri3/dri3_screen.c
++++ b/dri3/dri3_screen.c
+@@ -20,10 +20,6 @@
+ * OF THIS SOFTWARE.
+ */
+
+-#ifdef HAVE_XORG_CONFIG_H
+-#include <xorg-config.h>
+-#endif
+-
+ #include "dri3_priv.h"
+ #include <syncsdk.h>
+ #include <misync.h>
+diff --git a/hw/Makefile.am b/hw/Makefile.am
+index 19895dc77..3ecfa8b7a 100644
+--- a/hw/Makefile.am
++++ b/hw/Makefile.am
+@@ -44,3 +44,5 @@ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
+
+ relink:
+ $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
++
++SUBDIRS += vnc
+diff --git a/include/dix-config.h.in b/include/dix-config.h.in
+index f8fc67067..d53c4e72f 100644
+--- a/include/dix-config.h.in
++++ b/include/dix-config.h.in
+@@ -83,6 +83,9 @@
+ /* Define to 1 if you have the <fcntl.h> header file. */
+ #undef HAVE_FCNTL_H
+
++/* Have GBM support */
++#undef HAVE_GBM
++
+ /* Define to 1 if you have the `getdtablesize' function. */
+ #undef HAVE_GETDTABLESIZE
diff --git a/unix/xserver21.1.1.patch b/unix/xserver21.1.1.patch
deleted file mode 100644
index 3fbaae51..00000000
--- a/unix/xserver21.1.1.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-diff -urpN xorg-server-1.20.0/configure.ac xorg-server-1.20.0/configure.ac
---- xorg-server-1.20.0/configure.ac 2018-05-10 09:32:34.000000000 -0700
-+++ xorg-server-1.20.0/configure.ac 2018-06-13 19:04:47.536413626 -0700
-@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
- AC_CONFIG_HEADERS(include/version-config.h)
-
- AM_PROG_AS
-+AC_PROG_CXX
- AC_PROG_LN_S
- LT_PREREQ([2.2])
- LT_INIT([disable-static win32-dll])
-@@ -1777,6 +1778,9 @@ if test "x$XVFB" = xyes; then
- AC_SUBST([XVFB_SYS_LIBS])
- fi
-
-+dnl Xvnc DDX
-+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
-+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
-
- dnl Xnest DDX
-
-@@ -2565,6 +2571,7 @@ hw/dmx/Makefile
- hw/dmx/man/Makefile
- hw/vfb/Makefile
- hw/vfb/man/Makefile
-+hw/vnc/Makefile
- hw/xnest/Makefile
- hw/xnest/man/Makefile
- hw/xwin/Makefile
-diff -urpN xorg-server-1.20.0/hw/Makefile.am xorg-server-1.20.0/hw/Makefile.am
---- xorg-server-1.20.0/hw/Makefile.am 2018-05-10 09:32:34.000000000 -0700
-+++ xorg-server-1.20.0/hw/Makefile.am 2018-06-13 19:04:47.536413626 -0700
-@@ -44,3 +44,5 @@
-
- relink:
- $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
-+
-+SUBDIRS += vnc
diff --git a/unix/xserver21.patch b/unix/xserver21.patch
new file mode 100644
index 00000000..7f1e8d4f
--- /dev/null
+++ b/unix/xserver21.patch
@@ -0,0 +1,67 @@
+diff --git a/configure.ac b/configure.ac
+index fad7b5769..2c167de3d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -72,6 +72,7 @@ dnl forcing an entire recompile.x
+ AC_CONFIG_HEADERS(include/version-config.h)
+
+ AM_PROG_AS
++AC_PROG_CXX
+ AC_PROG_LN_S
+ LT_PREREQ([2.2])
+ LT_INIT([disable-static win32-dll])
+@@ -1720,6 +1721,14 @@ if test "x$XVFB" = xyes; then
+ AC_SUBST([XVFB_SYS_LIBS])
+ fi
+
++dnl Xvnc DDX
++AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
++AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
++
++PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
++if test "x$GBM" = xyes; then
++ AC_DEFINE(HAVE_GBM, 1, [Have GBM support])
++fi
+
+ dnl Xnest DDX
+
+@@ -2038,7 +2047,6 @@ if test "x$GLAMOR" = xyes; then
+ [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DRIVER, 1, [Have GLAMOR_HAS_EGL_QUERY_DRIVER])],
+ [])
+
+- PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+ if test "x$GBM" = xyes; then
+ AC_DEFINE(GLAMOR_HAS_GBM, 1,
+ [Build glamor with GBM-based EGL support])
+@@ -2346,6 +2354,7 @@ hw/xfree86/utils/man/Makefile
+ hw/xfree86/utils/gtf/Makefile
+ hw/vfb/Makefile
+ hw/vfb/man/Makefile
++hw/vnc/Makefile
+ hw/xnest/Makefile
+ hw/xnest/man/Makefile
+ hw/xwin/Makefile
+diff --git a/hw/Makefile.am b/hw/Makefile.am
+index 1749018fa..1172cd59b 100644
+--- a/hw/Makefile.am
++++ b/hw/Makefile.am
+@@ -34,3 +34,5 @@ DIST_SUBDIRS = xfree86 vfb xnest xwin xquartz kdrive
+
+ relink:
+ $(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
++
++SUBDIRS += vnc
+diff --git a/include/dix-config.h.in b/include/dix-config.h.in
+index 382d70609..04a4fd263 100644
+--- a/include/dix-config.h.in
++++ b/include/dix-config.h.in
+@@ -77,6 +77,9 @@
+ /* Define to 1 if you have the <fcntl.h> header file. */
+ #undef HAVE_FCNTL_H
+
++/* Have GBM support */
++#undef HAVE_GBM
++
+ /* Define to 1 if you have the `getdtablesize' function. */
+ #undef HAVE_GETDTABLESIZE
+