diff options
author | Pierre Ossman <ossman@cendio.se> | 2024-02-21 17:07:36 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2024-06-20 14:41:48 +0200 |
commit | 50048184a08f12cdf66064a5606fee2e981db9e8 (patch) | |
tree | 5c57d8a736495ac00ddf1abc5da3e4cf544dbfca /unix/xserver | |
parent | c30370df0878b823bd520a31567a69763259d5a5 (diff) | |
download | tigervnc-50048184a08f12cdf66064a5606fee2e981db9e8.tar.gz tigervnc-50048184a08f12cdf66064a5606fee2e981db9e8.zip |
Add basic DRI3 support
This provides buffer sync with the primary render node of the system (if
available). By doing so, OpenGL and Vulkan can use the render node for
acceleration.
This first implementation is extremely pessimistic and synchronises
buffers whenever there's even a slight chance they will be used.
Diffstat (limited to 'unix/xserver')
-rw-r--r-- | unix/xserver/hw/vnc/Makefile.am | 10 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3.c | 494 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3.h | 41 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncDRI3Draw.c | 785 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/xvnc.c | 7 |
5 files changed, 1337 insertions, 0 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/vncDRI3.c b/unix/xserver/hw/vnc/vncDRI3.c new file mode 100644 index 00000000..3d261667 --- /dev/null +++ b/unix/xserver/hw/vnc/vncDRI3.c @@ -0,0 +1,494 @@ +/* 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 <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 + +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 + + 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); + + screenPriv->devicePath = "/dev/dri/renderD128"; + + 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..636171ba --- /dev/null +++ b/unix/xserver/hw/vnc/vncDRI3.h @@ -0,0 +1,41 @@ +/* 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> + +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/xvnc.c b/unix/xserver/hw/vnc/xvnc.c index 4ee1cd1b..b77f469a 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" @@ -1088,6 +1089,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 */ |