Here's a patch that implements RandR on the server. It's based on George Wright's work, but I've rewritten large portions of it to handle dynamic allocation of the framebuffer.
I've tested it with Xvnc properly where it works nicely. I need someone to have a go with vnc.so though. Rgds -- Pierre Ossman OpenSource-based Thin Client Technology System Developer Telephone: +46-13-21 46 00 Cendio AB Web: http://www.cendio.com
Index: hw/vnc/vncExtInit.cc =================================================================== --- hw/vnc/vncExtInit.cc (revision 3687) +++ hw/vnc/vncExtInit.cc (working copy) @@ -80,6 +80,7 @@ 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 @@ 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) { Index: hw/vnc/vncExtInit.h =================================================================== --- hw/vnc/vncExtInit.h (revision 3687) +++ hw/vnc/vncExtInit.h (working copy) @@ -30,6 +30,7 @@ extern void vncClientGone(int fd); extern void vncBell(); extern void* vncFbptr[]; +extern int vncFbstride[]; extern int vncInetdSock; extern rfb::StringParameter httpDir; Index: hw/vnc/xvnc.cc =================================================================== --- hw/vnc/xvnc.cc (revision 3687) +++ hw/vnc/xvnc.cc (working copy) @@ -75,6 +75,9 @@ #include "dix.h" #include "miline.h" #include "inputstr.h" +#ifdef RANDR +#include "randrstr.h" +#endif /* RANDR */ #include <X11/keysym.h> extern char buildtime[]; #undef class @@ -794,6 +797,263 @@ miPointerWarpCursor }; +#ifdef RANDR + +static Bool vncRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) +{ + vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum]; + Bool gotCurrent = FALSE; + int i; + + const int widths[] = { 1920, 1600, 1680, 1400, 1280, 1280, 1280, 1024, 800, 640 }; + const int heights[] = { 1200, 1200, 1050, 1050, 1024, 960, 800, 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 @@ pbits = vfbAllocateFramebufferMemory(&pvfb->fb); if (!pbits) return FALSE; vncFbptr[index] = pbits; + vncFbstride[index] = pvfb->fb.paddedWidth; miSetPixmapDepths(); @@ -920,14 +1181,27 @@ } 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 */ Index: hw/vnc/XserverDesktop.cc =================================================================== --- hw/vnc/XserverDesktop.cc (revision 3687) +++ hw/vnc/XserverDesktop.cc (working copy) @@ -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 @@ 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 @@ 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 @@ cmap = (ColormapPtr) retval; } +void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride) +{ + width_ = w; + height_ = h; + + if (directFbptr) { + delete [] data; + directFbptr = false; + } + + if (!fbptr) { + fbptr = new rdr::U8[w * h * (format.bpp/8)]; + stride = w; + directFbptr = true; + } + + data = (rdr::U8*)fbptr; + stride_ = stride; + + server->setPixelBuffer(this); +} + char* XserverDesktop::substitute(const char* varName) { if (strcmp(varName, "$$") == 0) { @@ -839,6 +856,11 @@ 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) { Index: hw/vnc/XserverDesktop.h =================================================================== --- hw/vnc/XserverDesktop.h (revision 3687) +++ hw/vnc/XserverDesktop.h (working copy) @@ -62,11 +62,12 @@ 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(); @@ -82,6 +83,7 @@ void addClient(network::Socket* sock, bool reverse); void disconnectClients(); + // QueryConnect methods called from X server code // getQueryTimeout() // Returns the timeout associated with a particular @@ -106,6 +108,7 @@ // 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 +133,7 @@ network::TcpListener* listener; network::TcpListener* httpListener; ColormapPtr cmap; + int stride_; bool deferredUpdateTimerSet; bool grabbing; bool ignoreHooks_; Index: hw/vnc/vncHooks.cc =================================================================== --- hw/vnc/vncHooks.cc (revision 3687) +++ hw/vnc/vncHooks.cc (working copy) @@ -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 <stdio.h> #include "XserverDesktop.h" #include "vncHooks.h" +#include "vncExtInit.h" extern "C" { #define class c_class @@ -37,6 +39,9 @@ #ifdef RENDER #include "picturestr.h" #endif +#ifdef RANDR +#include "randrstr.h" +#endif #undef class #undef private @@ -74,6 +79,9 @@ #ifdef RENDER CompositeProcPtr Composite; #endif +#ifdef RANDR + RRSetConfigProcPtr RandRSetConfig; +#endif } vncHooksScreenRec, *vncHooksScreenPtr; typedef struct { @@ -122,6 +130,10 @@ 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 @@ 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 @@ ps->Composite = vncHooksComposite; } #endif +#ifdef RANDR + if (rp) { + rp->rrSetConfig = vncHooksRandRSetConfig; + } +#endif return TRUE; } @@ -294,6 +318,13 @@ 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,7 +529,44 @@ #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]); + + 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 */ + ///////////////////////////////////////////////////////////////////////////// // // GC "funcs" @@ -1492,3 +1560,4 @@ vncHooksScreen->desktop->add_changed(changed.reg); } +
signature.asc
Description: PGP signature
------------------------------------------------------------------------------ Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are powering Web 2.0 with engaging, cross-platform capabilities. Quickly and easily build your RIAs with Flex Builder, the Eclipse(TM)based development software that enables intelligent coding and step-through debugging. Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________ Tigervnc-devel mailing list Tigervnc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tigervnc-devel