From ef27ba18353159b4e1a363e09162c04ddf9091a7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 18 Mar 2009 17:22:30 +0000 Subject: [PATCH] Support for RandR on the server. Based on patch by George Wright but heavily rewritten in order to dynamically reallocate the framebuffer, allowing any resize. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3688 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- unix/xserver/hw/vnc/XserverDesktop.cc | 40 +++- unix/xserver/hw/vnc/XserverDesktop.h | 5 +- unix/xserver/hw/vnc/vncExtInit.cc | 4 +- unix/xserver/hw/vnc/vncExtInit.h | 1 + unix/xserver/hw/vnc/vncHooks.cc | 69 +++++++ unix/xserver/hw/vnc/xvnc.cc | 276 +++++++++++++++++++++++++- unix/xserver11.patch | 2 +- unix/xserver15.patch | 2 +- unix/xserver16.patch | 2 +- 9 files changed, 386 insertions(+), 15 deletions(-) diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index fa4172ed..cb57a6d1 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2009 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 @@ -168,12 +169,12 @@ public: XserverDesktop::XserverDesktop(ScreenPtr pScreen_, network::TcpListener* listener_, network::TcpListener* httpListener_, - const char* name, void* fbptr) + const char* name, void* fbptr, int stride) : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0), server(0), httpServer(0), listener(listener_), httpListener(httpListener_), cmap(0), deferredUpdateTimerSet(false), - grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0), + grabbing(false), ignoreHooks_(false), directFbptr(true), oldButtonMask(0), queryConnectId(0) { @@ -212,18 +213,12 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, format.greenMax = vis->greenMask >> format.greenShift; format.blueMax = vis->blueMask >> format.blueShift; - width_ = pScreen->width; - height_ = pScreen->height; - if (fbptr) - data = (rdr::U8*)fbptr; - else - data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)]; colourmap = this; serverReset(pScreen); server = new VNCServerST(name, this); - server->setPixelBuffer(this); + setFramebuffer(pScreen->width, pScreen->height, fbptr, stride); server->setQueryConnectionHandler(this); if (httpListener) @@ -288,6 +283,28 @@ void XserverDesktop::serverReset(ScreenPtr pScreen_) cmap = (ColormapPtr) retval; } +void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride) +{ + width_ = w; + height_ = h; + + if (!directFbptr) { + delete [] data; + directFbptr = true; + } + + if (!fbptr) { + fbptr = new rdr::U8[w * h * (format.bpp/8)]; + stride = w; + directFbptr = false; + } + + data = (rdr::U8*)fbptr; + stride_ = stride; + + server->setPixelBuffer(this); +} + char* XserverDesktop::substitute(const char* varName) { if (strcmp(varName, "$$") == 0) { @@ -839,6 +856,11 @@ void XserverDesktop::grabRegion(const rfb::Region& region) grabbing = false; } +int XserverDesktop::getStride() const +{ + return stride_; +} + void XserverDesktop::lookup(int index, int* r, int* g, int* b) { if ((cmap->c_class | DynamicClass) == DirectColor) { diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index fb758470..50b7d935 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -62,11 +62,12 @@ public: XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener, network::TcpListener* httpListener_, - const char* name, void* fbptr); + const char* name, void* fbptr, int stride); virtual ~XserverDesktop(); // methods called from X server code void serverReset(ScreenPtr pScreen); + void setFramebuffer(int w, int h, void* fbptr, int stride); void setColormap(ColormapPtr cmap); void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef); void bell(); @@ -106,6 +107,7 @@ public: // rfb::PixelBuffer callbacks virtual void grabRegion(const rfb::Region& r); + virtual int getStride() const; // rfb::ColourMap callbacks virtual void lookup(int index, int* r, int* g, int* b); @@ -130,6 +132,7 @@ private: network::TcpListener* listener; network::TcpListener* httpListener; ColormapPtr cmap; + int stride_; bool deferredUpdateTimerSet; bool grabbing; bool ignoreHooks_; diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index b4040d44..54e92f9a 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -80,6 +80,7 @@ static unsigned long vncExtGeneration = 0; static bool initialised = false; static XserverDesktop* desktop[MAXSCREENS] = { 0, }; void* vncFbptr[MAXSCREENS] = { 0, }; +int vncFbstride[MAXSCREENS]; static char* clientCutText = 0; static int clientCutTextLen = 0; @@ -188,7 +189,8 @@ void vncExtensionInit() desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener, httpListener, desktopNameStr.buf, - vncFbptr[scr]); + vncFbptr[scr], + vncFbstride[scr]); vlog.info("created VNC server for screen %d", scr); if (scr == 0 && vncInetdSock != -1 && !listener) { diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h index 606666bb..af9b2ea6 100644 --- a/unix/xserver/hw/vnc/vncExtInit.h +++ b/unix/xserver/hw/vnc/vncExtInit.h @@ -30,6 +30,7 @@ extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId); extern void vncClientGone(int fd); extern void vncBell(); extern void* vncFbptr[]; +extern int vncFbstride[]; extern int vncInetdSock; extern rfb::StringParameter httpDir; diff --git a/unix/xserver/hw/vnc/vncHooks.cc b/unix/xserver/hw/vnc/vncHooks.cc index 9eee2458..1ec55de5 100644 --- a/unix/xserver/hw/vnc/vncHooks.cc +++ b/unix/xserver/hw/vnc/vncHooks.cc @@ -1,4 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2009 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 @@ -23,6 +24,7 @@ #include #include "XserverDesktop.h" #include "vncHooks.h" +#include "vncExtInit.h" extern "C" { #define class c_class @@ -37,6 +39,9 @@ extern "C" { #ifdef RENDER #include "picturestr.h" #endif +#ifdef RANDR +#include "randrstr.h" +#endif #undef class #undef private @@ -74,6 +79,9 @@ typedef struct { #ifdef RENDER CompositeProcPtr Composite; #endif +#ifdef RANDR + RRSetConfigProcPtr RandRSetConfig; +#endif } vncHooksScreenRec, *vncHooksScreenPtr; typedef struct { @@ -122,6 +130,10 @@ static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height); #endif +#ifdef RANDR +static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize); +#endif // GC "funcs" @@ -239,6 +251,13 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop) vncHooksScreen->Composite = ps->Composite; } #endif +#ifdef RANDR + rrScrPrivPtr rp; + rp = rrGetScrPriv(pScreen); + if (rp) { + vncHooksScreen->RandRSetConfig = rp->rrSetConfig; + } +#endif pScreen->CloseScreen = vncHooksCloseScreen; pScreen->CreateGC = vncHooksCreateGC; @@ -254,6 +273,11 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop) ps->Composite = vncHooksComposite; } #endif +#ifdef RANDR + if (rp) { + rp->rrSetConfig = vncHooksRandRSetConfig; + } +#endif return TRUE; } @@ -294,6 +318,13 @@ static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_) pScreen->StoreColors = vncHooksScreen->StoreColors; pScreen->DisplayCursor = vncHooksScreen->DisplayCursor; pScreen->BlockHandler = vncHooksScreen->BlockHandler; +#ifdef RANDR + rrScrPrivPtr rp; + rp = rrGetScrPriv(pScreen); + if (rp) { + rp->rrSetConfig = vncHooksScreen->RandRSetConfig; + } +#endif DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n")); @@ -498,6 +529,44 @@ void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, #endif /* RENDER */ +// RandRSetConfig - follow any framebuffer changes + +#ifdef RANDR + +static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize) +{ + vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + Bool ret; + RegionRec reg; + BoxRec box; + + rp->rrSetConfig = vncHooksScreen->RandRSetConfig; + ret = (*rp->rrSetConfig)(pScreen, rotation, rate, pSize); + rp->rrSetConfig = vncHooksRandRSetConfig; + + if (!ret) + return FALSE; + + // Let the RFB core know of the new dimensions and framebuffer + vncHooksScreen->desktop->setFramebuffer(pScreen->width, pScreen->height, + vncFbptr[pScreen->myNum], + vncFbstride[pScreen->myNum]); + + // Mark entire screen as changed + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT(pScreen, ®, &box, 1); + + vncHooksScreen->desktop->add_changed(®); + + return TRUE; +} + +#endif /* RANDR */ ///////////////////////////////////////////////////////////////////////////// // diff --git a/unix/xserver/hw/vnc/xvnc.cc b/unix/xserver/hw/vnc/xvnc.cc index 3349103e..514ebf7d 100644 --- a/unix/xserver/hw/vnc/xvnc.cc +++ b/unix/xserver/hw/vnc/xvnc.cc @@ -75,6 +75,9 @@ extern "C" { #include "dix.h" #include "miline.h" #include "inputstr.h" +#ifdef RANDR +#include "randrstr.h" +#endif /* RANDR */ #include extern char buildtime[]; #undef class @@ -794,6 +797,263 @@ static miPointerScreenFuncRec vfbPointerCursorFuncs = { miPointerWarpCursor }; +#ifdef RANDR + +static Bool vncRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + Bool gotCurrent = FALSE; + int i; + + const int widths[] = { 1920, 1920, 1600, 1680, 1400, 1360, 1280, 1280, 1280, 1280, 1024, 800, 640 }; + const int heights[] = { 1200, 1080, 1200, 1050, 1050, 768, 1024, 960, 800, 720, 768, 600, 480 }; + + for (i = 0;i < sizeof(widths)/sizeof(*widths);i++) { + RRScreenSizePtr pSize; + + pSize = RRRegisterSize(pScreen, widths[i], heights[i], + pScreen->mmWidth, pScreen->mmHeight); + if (!pSize) + return FALSE; + + RRRegisterRate(pScreen, pSize, 60); + + if ((widths[i] == pScreen->width) && (heights[i] == pScreen->height)) { + RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize); + gotCurrent = TRUE; + } + } + + if (!gotCurrent) { + RRScreenSizePtr pSize; + + pSize = RRRegisterSize(pScreen, pScreen->width, pScreen->height, + pScreen->mmWidth, pScreen->mmHeight); + if (!pSize) + return FALSE; + + RRRegisterRate(pScreen, pSize, 60); + + RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize); + } + + *rotations = RR_Rotate_0; + + return TRUE; +} + +/* from hw/xfree86/common/xf86Helper.c */ + +#include "mivalidate.h" +static void +xf86SetRootClip (ScreenPtr pScreen, Bool enable) +{ + WindowPtr pWin = WindowTable[pScreen->myNum]; + WindowPtr pChild; + Bool WasViewable = (Bool)(pWin->viewable); + Bool anyMarked = FALSE; + RegionPtr pOldClip = NULL, bsExposed; +#ifdef DO_SAVE_UNDERS + Bool dosave = FALSE; +#endif + WindowPtr pLayerWin; + BoxRec box; + + if (WasViewable) + { + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + (void) (*pScreen->MarkOverlappedWindows)(pChild, + pChild, + &pLayerWin); + } + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + if (pWin->valdata) + { + if (HasBorder (pWin)) + { + RegionPtr borderVisible; + + borderVisible = REGION_CREATE(pScreen, NullBox, 1); + REGION_SUBTRACT(pScreen, borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } + pWin->valdata->before.resized = TRUE; + } + } + + /* + * Use REGION_BREAK to avoid optimizations in ValidateTree + * that assume the root borderClip can't change well, normally + * it doesn't...) + */ + if (enable) + { + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; + REGION_INIT (pScreen, &pWin->winSize, &box, 1); + REGION_INIT (pScreen, &pWin->borderSize, &box, 1); + if (WasViewable) + REGION_RESET(pScreen, &pWin->borderClip, &box); + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + else + { + REGION_EMPTY(pScreen, &pWin->borderClip); + REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); + + if (WasViewable) + { + if (pWin->backStorage) + { + pOldClip = REGION_CREATE(pScreen, NullBox, 1); + REGION_COPY(pScreen, pOldClip, &pWin->clipList); + } + + if (pWin->firstChild) + { + anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild, + pWin->firstChild, + (WindowPtr *)NULL); + } + else + { + (*pScreen->MarkWindow) (pWin); + anyMarked = TRUE; + } + +#ifdef DO_SAVE_UNDERS + if (DO_SAVE_UNDERS(pWin)) + { + dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin); + } +#endif /* DO_SAVE_UNDERS */ + + if (anyMarked) + (*pScreen->ValidateTree)(pWin, NullWindow, VTOther); + } + + if (pWin->backStorage && + ((pWin->backingStore == Always) || WasViewable)) + { + if (!WasViewable) + pOldClip = &pWin->clipList; /* a convenient empty region */ + bsExposed = (*pScreen->TranslateBackingStore) + (pWin, 0, 0, pOldClip, + pWin->drawable.x, pWin->drawable.y); + if (WasViewable) + REGION_DESTROY(pScreen, pOldClip); + if (bsExposed) + { + RegionPtr valExposed = NullRegion; + + if (pWin->valdata) + valExposed = &pWin->valdata->after.exposed; + (*pScreen->WindowExposures) (pWin, valExposed, bsExposed); + if (valExposed) + REGION_EMPTY(pScreen, valExposed); + REGION_DESTROY(pScreen, bsExposed); + } + } + if (WasViewable) + { + if (anyMarked) + (*pScreen->HandleExposures)(pWin); +#ifdef DO_SAVE_UNDERS + if (dosave) + (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin); +#endif /* DO_SAVE_UNDERS */ + if (anyMarked && pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther); + } + if (pWin->realized) + WindowsRestructured (); + FlushAllOutput (); +} + +static Bool vncRandRSetConfig (ScreenPtr pScreen, Rotation rotation, + int rate, RRScreenSizePtr pSize) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + vfbFramebufferInfo fb; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + void *pbits; + Bool ret; + int oldwidth, oldheight, oldmmWidth, oldmmHeight; + + /* Prevent updates while we fiddle */ + xf86SetRootClip(pScreen, FALSE); + + /* Store current state in case we fail */ + oldwidth = pScreen->width; + oldheight = pScreen->height; + oldmmWidth = pScreen->mmWidth; + oldmmHeight = pScreen->mmHeight; + + /* Then set the new dimensions */ + pScreen->width = pSize->width; + pScreen->height = pSize->height; + pScreen->mmWidth = pSize->mmWidth; + pScreen->mmHeight = pSize->mmHeight; + + /* Allocate a new framebuffer */ + memset(&fb, 0, sizeof(vfbFramebufferInfo)); + + fb.width = pScreen->width; + fb.height = pScreen->height; + fb.depth = pvfb->fb.depth; + + pbits = vfbAllocateFramebufferMemory(&fb); + if (!pbits) { + /* Allocation failed. Restore old state */ + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + + return FALSE; + } + + /* Update root pixmap with the new dimensions and buffer */ + ret = pScreen->ModifyPixmapHeader(rootPixmap, fb.width, fb.height, + -1, -1, fb.paddedBytesWidth, pbits); + if (!ret) { + /* Update failed. Free the new framebuffer and restore old state */ + vfbFreeFramebufferMemory(&fb); + + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmWidth; + pScreen->mmHeight = oldmmHeight; + + return FALSE; + } + + /* Free the old framebuffer and keep the info about the new one */ + vfbFreeFramebufferMemory(&pvfb->fb); + memcpy(&pvfb->fb, &fb, sizeof(vfbFramebufferInfo)); + + /* Let VNC get the new framebuffer (actual update is in vncHooks.cc) */ + vncFbptr[pScreen->myNum] = pbits; + vncFbstride[pScreen->myNum] = fb.paddedWidth; + + /* Restore ability to update screen, now with new dimensions */ + xf86SetRootClip(pScreen, TRUE); + + return TRUE; +} + +#endif + static Bool vfbCloseScreen(int index, ScreenPtr pScreen) { @@ -825,6 +1085,7 @@ vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) pbits = vfbAllocateFramebufferMemory(&pvfb->fb); if (!pbits) return FALSE; vncFbptr[index] = pbits; + vncFbstride[index] = pvfb->fb.paddedWidth; miSetPixmapDepths(); @@ -920,13 +1181,26 @@ vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv) } ret = fbCreateDefColormap(pScreen); + if (!ret) return FALSE; miSetZeroLineBias(pScreen, pvfb->lineBias); pvfb->closeScreen = pScreen->CloseScreen; pScreen->CloseScreen = vfbCloseScreen; - return ret; +#ifdef RANDR + rrScrPrivPtr rp; + + ret = RRScreenInit(pScreen); + if (!ret) return FALSE; + + rp = rrGetScrPriv(pScreen); + rp->rrGetInfo = vncRandRGetInfo; + rp->rrSetConfig = vncRandRSetConfig; +#endif + + + return TRUE; } /* end vfbScreenInit */ diff --git a/unix/xserver11.patch b/unix/xserver11.patch index bae1bd3d..8bcb4002 100644 --- a/unix/xserver11.patch +++ b/unix/xserver11.patch @@ -24,7 +24,7 @@ diff -up xserver/configure.ac.vnc xserver/configure.ac + dnl Xvnc DDX + -+ AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC"]) ++ AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"]) + AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB"]) + + diff --git a/unix/xserver15.patch b/unix/xserver15.patch index 2c2831e6..ee7f4fe2 100644 --- a/unix/xserver15.patch +++ b/unix/xserver15.patch @@ -22,7 +22,7 @@ diff -up xserver/configure.ac.vnc xserver/configure.ac fi +dnl Xvnc DDX -+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC"]) ++AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"]) +AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB"]) dnl Xnest DDX diff --git a/unix/xserver16.patch b/unix/xserver16.patch index 63c54322..0a3a93f8 100644 --- a/unix/xserver16.patch +++ b/unix/xserver16.patch @@ -22,7 +22,7 @@ diff -up xserver/configure.ac.vnc xserver/configure.ac fi +dnl Xvnc DDX -+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC"]) ++AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"]) +AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"]) dnl Xnest DDX -- 2.39.5