diff options
Diffstat (limited to 'unix/xserver/hw/vnc')
-rw-r--r-- | unix/xserver/hw/vnc/Makefile.am | 10 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/Xvnc.man | 6 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3.c | 537 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3.h | 43 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3Draw.c | 785 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncHooks.c | 69 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/xvnc.c | 21 |
7 files changed, 1442 insertions, 29 deletions
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(®, &box, 1); - RegionIntersect(®, ®, &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(®, &box, 1); + RegionIntersect(®, ®, &pWin->clipList); + } else { + RegionNull(®); + } (*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 }, |