12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432 |
- /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2009-2017 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 <stdio.h>
-
- #include "vncHooks.h"
- #include "vncExtInit.h"
-
- #include "xorg-version.h"
-
- #include "scrnintstr.h"
- #include "windowstr.h"
- #include "cursorstr.h"
- #include "gcstruct.h"
- #include "regionstr.h"
- #include "dixfontstr.h"
- #include "colormapst.h"
- #ifdef RENDER
- #include "picturestr.h"
- #endif
- #include "randrstr.h"
-
- #define DBGPRINT(x) //(fprintf x)
-
- // MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
- // operations like Polylines and PolySegment. If the operation is more complex
- // than this, we simply use the bounding box. Ideally it would be a
- // command-line option, but that would involve an extra malloc each time, so we
- // fix it here.
- #define MAX_RECTS_PER_OP 5
-
- // vncHooksScreenRec and vncHooksGCRec contain pointers to the original
- // functions which we "wrap" in order to hook the screen changes. The screen
- // functions are each wrapped individually, while the GC "funcs" and "ops" are
- // wrapped as a unit.
-
- typedef struct _vncHooksScreenRec {
- int ignoreHooks;
-
- CloseScreenProcPtr CloseScreen;
- CreateGCProcPtr CreateGC;
- CopyWindowProcPtr CopyWindow;
- ClearToBackgroundProcPtr ClearToBackground;
- #if XORG < 110
- RestoreAreasProcPtr RestoreAreas;
- #endif
- DisplayCursorProcPtr DisplayCursor;
- ScreenBlockHandlerProcPtr BlockHandler;
- #ifdef RENDER
- CompositeProcPtr Composite;
- GlyphsProcPtr Glyphs;
- CompositeRectsProcPtr CompositeRects;
- TrapezoidsProcPtr Trapezoids;
- TrianglesProcPtr Triangles;
- #if PICTURE_SCREEN_VERSION >= 2
- TriStripProcPtr TriStrip;
- TriFanProcPtr TriFan;
- #endif
- #endif
- RRSetConfigProcPtr rrSetConfig;
- RRScreenSetSizeProcPtr rrScreenSetSize;
- RRCrtcSetProcPtr rrCrtcSet;
- } vncHooksScreenRec, *vncHooksScreenPtr;
-
- typedef struct _vncHooksGCRec {
- #if XORG >= 116
- const GCFuncs *funcs;
- const GCOps *ops;
- #else
- GCFuncs *funcs;
- GCOps *ops;
- #endif
- } vncHooksGCRec, *vncHooksGCPtr;
-
- #define wrap(priv, real, mem, func) {\
- priv->mem = real->mem; \
- real->mem = func; \
- }
-
- #define unwrap(priv, real, mem) {\
- real->mem = priv->mem; \
- }
-
- #if XORG < 19
- static int vncHooksScreenPrivateKeyIndex;
- static int vncHooksGCPrivateKeyIndex;
- static DevPrivateKey vncHooksScreenPrivateKey = &vncHooksScreenPrivateKeyIndex;
- static DevPrivateKey vncHooksGCPrivateKey = &vncHooksGCPrivateKeyIndex;
- #else
- static DevPrivateKeyRec vncHooksScreenKeyRec;
- static DevPrivateKeyRec vncHooksGCKeyRec;
- #define vncHooksScreenPrivateKey (&vncHooksScreenKeyRec)
- #define vncHooksGCPrivateKey (&vncHooksGCKeyRec)
- #endif
-
- #define vncHooksScreenPrivate(pScreen) \
- (vncHooksScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates, \
- vncHooksScreenPrivateKey)
- #define vncHooksGCPrivate(pGC) \
- (vncHooksGCPtr) dixLookupPrivate(&(pGC)->devPrivates, \
- vncHooksGCPrivateKey)
-
- // screen functions
-
- #if XORG <= 112
- static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
- #else
- static Bool vncHooksCloseScreen(ScreenPtr pScreen);
- #endif
- static Bool vncHooksCreateGC(GCPtr pGC);
- static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion);
- static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
- int h, Bool generateExposures);
- #if XORG < 110
- static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
- #endif
- static Bool vncHooksDisplayCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen, CursorPtr cursor);
- #if XORG <= 112
- static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask);
- #elif XORG <= 118
- static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout,
- void * pReadmask);
- #else
- static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout);
- #endif
- #ifdef RENDER
- 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);
- static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
- GlyphListPtr lists, GlyphPtr * glyphs);
- static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,
- xRenderColor * color, int nRect, xRectangle *rects);
- static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int ntrap, xTrapezoid * traps);
- static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int ntri, xTriangle * tris);
- #if PICTURE_SCREEN_VERSION >= 2
- static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed * points);
- static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed * points);
- #endif
- #endif
- static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
- int rate, RRScreenSizePtr pSize);
- static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
- CARD16 width, CARD16 height,
- CARD32 mmWidth, CARD32 mmHeight);
- static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
- RRModePtr mode, int x, int y,
- Rotation rotation, int numOutputs,
- RROutputPtr *outputs);
-
- // GC "funcs"
-
- static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable);
- static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
- static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
- static void vncHooksDestroyGC(GCPtr pGC);
- static void vncHooksChangeClip(GCPtr pGC, int type, void * pValue,int nrects);
- static void vncHooksDestroyClip(GCPtr pGC);
- static void vncHooksCopyClip(GCPtr dst, GCPtr src);
-
- static GCFuncs vncHooksGCFuncs = {
- vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
- vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
- };
-
- // GC "ops"
-
- static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted);
- static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted);
- static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits);
- static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty);
- static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane);
- static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts);
- static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts);
- static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs);
- static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
- static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
- static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts);
- static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
- static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
- static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
- static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
- static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
- static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
- static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, void * pglyphBase);
- static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, void * pglyphBase);
- static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y);
-
- static GCOps vncHooksGCOps = {
- vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
- vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
- vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
- vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
- vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
- vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
- };
-
-
-
- /////////////////////////////////////////////////////////////////////////////
- // vncHooksInit() is called at initialisation time and every time the server
- // resets. It is called once for each screen, but the indexes are only
- // allocated once for each server generation.
-
- int vncHooksInit(int scrIdx)
- {
- ScreenPtr pScreen;
- vncHooksScreenPtr vncHooksScreen;
-
- #ifdef RENDER
- PictureScreenPtr ps;
- #endif
- rrScrPrivPtr rp;
-
- pScreen = screenInfo.screens[scrIdx];
-
- if (sizeof(BoxRec) != sizeof(struct UpdateRect)) {
- ErrorF("vncHooksInit: Incompatible BoxRec size\n");
- return FALSE;
- }
-
- #if XORG < 19
- if (!dixRequestPrivate(vncHooksScreenPrivateKey, sizeof(vncHooksScreenRec))) {
- ErrorF("vncHooksInit: Allocation of vncHooksScreen failed\n");
- return FALSE;
- }
- if (!dixRequestPrivate(vncHooksGCPrivateKey, sizeof(vncHooksGCRec))) {
- ErrorF("vncHooksInit: Allocation of vncHooksGCRec failed\n");
- return FALSE;
- }
-
- #else
- if (!dixRegisterPrivateKey(&vncHooksScreenKeyRec, PRIVATE_SCREEN,
- sizeof(vncHooksScreenRec))) {
- ErrorF("vncHooksInit: Allocation of vncHooksScreen failed\n");
- return FALSE;
- }
- if (!dixRegisterPrivateKey(&vncHooksGCKeyRec, PRIVATE_GC,
- sizeof(vncHooksGCRec))) {
- ErrorF("vncHooksInit: Allocation of vncHooksGCRec failed\n");
- return FALSE;
- }
-
- #endif
-
- vncHooksScreen = vncHooksScreenPrivate(pScreen);
-
- vncHooksScreen->ignoreHooks = 0;
-
- wrap(vncHooksScreen, pScreen, CloseScreen, vncHooksCloseScreen);
- wrap(vncHooksScreen, pScreen, CreateGC, vncHooksCreateGC);
- wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow);
- wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground);
- #if XORG < 110
- wrap(vncHooksScreen, pScreen, RestoreAreas, vncHooksRestoreAreas);
- #endif
- wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor);
- wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler);
- #ifdef RENDER
- ps = GetPictureScreenIfSet(pScreen);
- if (ps) {
- wrap(vncHooksScreen, ps, Composite, vncHooksComposite);
- wrap(vncHooksScreen, ps, Glyphs, vncHooksGlyphs);
- wrap(vncHooksScreen, ps, CompositeRects, vncHooksCompositeRects);
- wrap(vncHooksScreen, ps, Trapezoids, vncHooksTrapezoids);
- wrap(vncHooksScreen, ps, Triangles, vncHooksTriangles);
- #if PICTURE_SCREEN_VERSION >= 2
- wrap(vncHooksScreen, ps, TriStrip, vncHooksTriStrip);
- wrap(vncHooksScreen, ps, TriFan, vncHooksTriFan);
- #endif
- }
- #endif
- rp = rrGetScrPriv(pScreen);
- if (rp) {
- /* Some RandR callbacks are optional */
- if (rp->rrSetConfig)
- wrap(vncHooksScreen, rp, rrSetConfig, vncHooksRandRSetConfig);
- if (rp->rrScreenSetSize)
- wrap(vncHooksScreen, rp, rrScreenSetSize, vncHooksRandRScreenSetSize);
- if (rp->rrCrtcSet)
- wrap(vncHooksScreen, rp, rrCrtcSet, vncHooksRandRCrtcSet);
- }
-
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // vncGetScreenImage() grabs a chunk of data from the main screen into the
- // provided buffer. It lives here rather than in XorgGlue.c because it
- // temporarily pauses the hooks.
-
- void vncGetScreenImage(int scrIdx, int x, int y, int width, int height,
- char *buffer, int strideBytes)
- {
- ScreenPtr pScreen = screenInfo.screens[scrIdx];
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
-
- int i;
-
- vncHooksScreen->ignoreHooks++;
-
- // We do one line at a time since GetImage() cannot handle stride
- for (i = y; i < y + height; i++) {
- DrawablePtr pDrawable;
- #if XORG < 19
- pDrawable = (DrawablePtr) WindowTable[scrIdx];
- #else
- pDrawable = (DrawablePtr) pScreen->root;
- #endif
-
- (*pScreen->GetImage) (pDrawable, x, i, width, 1,
- ZPixmap, (unsigned long)~0L, buffer);
-
- buffer += strideBytes;
- }
-
- vncHooksScreen->ignoreHooks--;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // Helper functions
- //
-
- static inline void add_changed(ScreenPtr pScreen, RegionPtr reg)
- {
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
- if (vncHooksScreen->ignoreHooks)
- return;
- vncAddChanged(pScreen->myNum,
- (const struct UpdateRect*)REGION_EXTENTS(pScreen, reg),
- REGION_NUM_RECTS(reg),
- (const struct UpdateRect*)REGION_RECTS(reg));
- }
-
- static inline void add_copied(ScreenPtr pScreen, RegionPtr dst,
- int dx, int dy)
- {
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
- if (vncHooksScreen->ignoreHooks)
- return;
- vncAddCopied(pScreen->myNum,
- (const struct UpdateRect*)REGION_EXTENTS(pScreen, dst),
- REGION_NUM_RECTS(dst),
- (const struct UpdateRect*)REGION_RECTS(dst), dx, dy);
- }
-
- static inline Bool is_visible(DrawablePtr drawable)
- {
- PixmapPtr scrPixmap;
-
- scrPixmap = drawable->pScreen->GetScreenPixmap(drawable->pScreen);
-
- if (drawable->type == DRAWABLE_WINDOW) {
- WindowPtr window;
- PixmapPtr winPixmap;
-
- window = (WindowPtr)drawable;
- winPixmap = drawable->pScreen->GetWindowPixmap(window);
-
- if (!window->viewable)
- return FALSE;
-
- if (winPixmap != scrPixmap)
- return FALSE;
-
- return TRUE;
- }
-
- if (drawable != &scrPixmap->drawable)
- return FALSE;
-
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // screen functions
- //
-
- // Unwrap and rewrap helpers
-
- #define SCREEN_PROLOGUE(scrn,field) \
- ScreenPtr pScreen = scrn; \
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
- unwrap(vncHooksScreen, pScreen, field); \
- DBGPRINT((stderr,"vncHooks" #field " called\n"));
-
- #define SCREEN_EPILOGUE(field) \
- wrap(vncHooksScreen, pScreen, field, vncHooks##field); \
-
-
- // CloseScreen - unwrap the screen functions and call the original CloseScreen
- // function
-
- #if XORG <= 112
- static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
- #else
- static Bool vncHooksCloseScreen(ScreenPtr pScreen_)
- #endif
- {
- #ifdef RENDER
- PictureScreenPtr ps;
- #endif
- rrScrPrivPtr rp;
-
- SCREEN_PROLOGUE(pScreen_, CloseScreen);
-
- unwrap(vncHooksScreen, pScreen, CreateGC);
- unwrap(vncHooksScreen, pScreen, CopyWindow);
- unwrap(vncHooksScreen, pScreen, ClearToBackground);
- #if XORG < 110
- unwrap(vncHooksScreen, pScreen, RestoreAreas);
- #endif
- unwrap(vncHooksScreen, pScreen, DisplayCursor);
- unwrap(vncHooksScreen, pScreen, BlockHandler);
- #ifdef RENDER
- ps = GetPictureScreenIfSet(pScreen);
- if (ps) {
- unwrap(vncHooksScreen, ps, Composite);
- unwrap(vncHooksScreen, ps, Glyphs);
- unwrap(vncHooksScreen, ps, CompositeRects);
- unwrap(vncHooksScreen, ps, Trapezoids);
- unwrap(vncHooksScreen, ps, Triangles);
- #if PICTURE_SCREEN_VERSION >= 2
- unwrap(vncHooksScreen, ps, TriStrip);
- unwrap(vncHooksScreen, ps, TriFan);
- #endif
- }
- #endif
- rp = rrGetScrPriv(pScreen);
- if (rp) {
- unwrap(vncHooksScreen, rp, rrSetConfig);
- unwrap(vncHooksScreen, rp, rrScreenSetSize);
- unwrap(vncHooksScreen, rp, rrCrtcSet);
- }
-
- DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
-
- #if XORG <= 112
- return (*pScreen->CloseScreen)(i, pScreen);
- #else
- return (*pScreen->CloseScreen)(pScreen);
- #endif
- }
-
- // CreateGC - wrap the "GC funcs"
-
- static Bool vncHooksCreateGC(GCPtr pGC)
- {
- vncHooksGCPtr vncHooksGC = vncHooksGCPrivate(pGC);
- Bool ret;
-
- SCREEN_PROLOGUE(pGC->pScreen, CreateGC);
-
- ret = (*pScreen->CreateGC) (pGC);
-
- vncHooksGC->ops = NULL;
- vncHooksGC->funcs = pGC->funcs;
- pGC->funcs = &vncHooksGCFuncs;
-
- SCREEN_EPILOGUE(CreateGC);
-
- return ret;
- }
-
- // CopyWindow - destination of the copy is the old region, clipped by
- // borderClip, translated by the delta. This call only does the copy - it
- // doesn't affect any other bits.
-
- static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion)
- {
- int dx, dy;
- BoxRec screen_box;
- RegionRec copied, screen_rgn;
-
- SCREEN_PROLOGUE(pWin->drawable.pScreen, CopyWindow);
-
- REGION_NULL(pScreen, &copied);
- REGION_COPY(pScreen, &copied, pOldRegion);
-
- screen_box.x1 = 0;
- screen_box.y1 = 0;
- screen_box.x2 = pScreen->width;
- screen_box.y2 = pScreen->height;
-
- REGION_INIT(pScreen, &screen_rgn, &screen_box, 1);
-
- 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.
- REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn);
- REGION_TRANSLATE(pScreen, &copied, dx, dy);
- REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn);
- REGION_INTERSECT(pScreen, &copied, &copied, &pWin->borderClip);
-
- (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
-
- if (REGION_NOTEMPTY(pScreen, &copied))
- add_copied(pScreen, &copied, dx, dy);
-
- REGION_UNINIT(pScreen, &copied);
- REGION_UNINIT(pScreen, &screen_rgn);
-
- SCREEN_EPILOGUE(CopyWindow);
- }
-
- // ClearToBackground - changed region is the given rectangle, clipped by
- // clipList, but only if generateExposures is false.
-
- 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);
-
- REGION_INIT(pScreen, ®, &box, 0);
- REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList);
-
- (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
-
- if (!generateExposures) {
- add_changed(pScreen, ®);
- }
-
- REGION_UNINIT(pScreen, ®);
-
- SCREEN_EPILOGUE(ClearToBackground);
- }
-
- #if XORG < 110
- // RestoreAreas - changed region is the given region
-
- static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
- {
- RegionRec reg;
-
- SCREEN_PROLOGUE(pWin->drawable.pScreen, RestoreAreas);
-
- REGION_NULL(pScreen, ®);
- REGION_COPY(pScreen, ®, pRegion);
-
- RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
-
- add_changed(pScreen, ®);
-
- REGION_UNINIT(pScreen, ®);
-
- SCREEN_EPILOGUE(RestoreAreas);
-
- return result;
- }
- #endif
-
- // DisplayCursor - get the cursor shape
-
- static Bool vncHooksDisplayCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen_, CursorPtr cursor)
- {
- Bool ret;
-
- SCREEN_PROLOGUE(pScreen_, DisplayCursor);
-
- ret = (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
-
- /*
- * XXX DIX calls this function with NULL argument to remove cursor sprite from
- * screen. Should we handle this in setCursor as well?
- */
- if (cursor != NullCursor) {
- int width, height;
- int hotX, hotY;
-
- unsigned char *rgbaData;
-
- width = cursor->bits->width;
- height = cursor->bits->height;
-
- hotX = cursor->bits->xhot;
- hotY = cursor->bits->yhot;
-
- rgbaData = malloc(width * height * 4);
- if (rgbaData == NULL)
- goto out;
-
- #ifdef ARGB_CURSOR
- if (cursor->bits->argb) {
- unsigned char *out;
- CARD32 *in;
- int i;
-
- in = cursor->bits->argb;
- out = rgbaData;
- for (i = 0; i < width*height; i++) {
- out[0] = (*in >> 16) & 0xff;
- out[1] = (*in >> 8) & 0xff;
- out[2] = (*in >> 0) & 0xff;
- out[3] = (*in >> 24) & 0xff;
- out += 4;
- in++;
- }
- } else {
- #endif
- unsigned char *out;
- int xMaskBytesPerRow;
-
- xMaskBytesPerRow = BitmapBytePad(width);
-
- out = rgbaData;
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- int byte = y * xMaskBytesPerRow + x / 8;
- #if (BITMAP_BIT_ORDER == MSBFirst)
- int bit = 7 - x % 8;
- #else
- int bit = x % 8;
- #endif
-
- if (cursor->bits->source[byte] & (1 << bit)) {
- out[0] = cursor->foreRed;
- out[1] = cursor->foreGreen;
- out[2] = cursor->foreBlue;
- } else {
- out[0] = cursor->backRed;
- out[1] = cursor->backGreen;
- out[2] = cursor->backBlue;
- }
-
- if (cursor->bits->mask[byte] & (1 << bit))
- out[3] = 0xff;
- else
- out[3] = 0x00;
-
- out += 4;
- }
- }
- #ifdef ARGB_CURSOR
- }
- #endif
-
- vncSetCursor(width, height, hotX, hotY, rgbaData);
-
- free(rgbaData);
- }
-
- out:
- SCREEN_EPILOGUE(DisplayCursor);
-
- return ret;
- }
-
- // BlockHandler - ignore any changes during the block handler - it's likely
- // these are just drawing the cursor.
-
- #if XORG <= 112
- static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask)
- #elif XORG <= 118
- static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout,
- void * pReadmask)
- #else
- static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout)
- #endif
- {
- #if XORG <= 112
- SCREEN_PROLOGUE(screenInfo.screens[i], BlockHandler);
- #else
- SCREEN_PROLOGUE(pScreen_, BlockHandler);
- #endif
-
- vncHooksScreen->ignoreHooks++;
-
- #if XORG <= 112
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
- #elif XORG <= 118
- (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
- #else
- (*pScreen->BlockHandler) (pScreen, pTimeout);
- #endif
-
- vncHooksScreen->ignoreHooks--;
-
- SCREEN_EPILOGUE(BlockHandler);
- }
-
- #ifdef RENDER
-
- // Unwrap and rewrap helpers
-
- #define RENDER_PROLOGUE(scrn,field) \
- ScreenPtr pScreen = scrn; \
- PictureScreenPtr ps = GetPictureScreen(pScreen); \
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
- unwrap(vncHooksScreen, ps, field); \
- DBGPRINT((stderr,"vncHooks" #field " called\n"));
-
- #define RENDER_EPILOGUE(field) \
- wrap(vncHooksScreen, ps, field, vncHooks##field); \
-
- // Composite - The core of XRENDER
-
- 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)
- {
- RegionRec changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, Composite);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec box;
- RegionRec fbreg;
-
- box.x1 = max(pDst->pDrawable->x + xDst, 0);
- box.y1 = max(pDst->pDrawable->y + yDst, 0);
- box.x2 = box.x1 + width;
- box.y2 = box.y1 + height;
- REGION_INIT(pScreen, &changed, &box, 0);
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &box, 0);
-
- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- REGION_NULL(pScreen, &changed);
- }
-
-
- (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst, width, height);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pScreen, &changed);
-
- REGION_UNINIT(pScreen, &changed);
-
- RENDER_EPILOGUE(Composite);
- }
-
- static int
- GlyphCount(int nlist, GlyphListPtr list, GlyphPtr * glyphs)
- {
- int count;
-
- count = 0;
- while (nlist--) {
- count += list->len;
- list++;
- }
-
- return count;
- }
-
- static RegionPtr
- GlyphsToRegion(ScreenPtr pScreen, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
- {
- int n;
- GlyphPtr glyph;
- int x, y;
-
- int nrects = GlyphCount(nlist, list, glyphs);
- xRectangle rects[nrects];
- xRectanglePtr rect;
-
- x = 0;
- y = 0;
- rect = &rects[0];
- while (nlist--) {
- x += list->xOff;
- y += list->yOff;
- n = list->len;
- list++;
- while (n--) {
- glyph = *glyphs++;
- rect->x = x - glyph->info.x;
- rect->y = y - glyph->info.y;
- rect->width = glyph->info.width;
- rect->height = glyph->info.height;
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- rect++;
- }
- }
-
- return RECTS_TO_REGION(pScreen, nrects, rects, CT_NONE);
- }
-
- // Glyphs - Glyph specific version of Composite (caches and whatnot)
-
- static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
- GlyphListPtr lists, GlyphPtr * glyphs)
- {
- RegionPtr changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, Glyphs);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec fbbox;
- RegionRec fbreg;
-
- changed = GlyphsToRegion(pScreen, nlists, lists, glyphs);
- REGION_TRANSLATE(pScreen, changed,
- pDst->pDrawable->x, pDst->pDrawable->y);
-
- fbbox.x1 = 0;
- fbbox.y1 = 0;
- fbbox.x2 = pScreen->width;
- fbbox.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &fbbox, 0);
-
- REGION_INTERSECT(pScreen, changed, changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- changed = REGION_CREATE(pScreen, NullBox, 0);
- }
-
- (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs);
-
- if (REGION_NOTEMPTY(pScreen, changed))
- add_changed(pScreen, changed);
-
- REGION_DESTROY(pScreen, changed);
-
- RENDER_EPILOGUE(Glyphs);
- }
-
- static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,
- xRenderColor * color, int nRect, xRectangle *rects)
- {
- RegionPtr changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, CompositeRects);
-
- if (is_visible(pDst->pDrawable)) {
- changed = RECTS_TO_REGION(pScreen, nRect, rects, CT_NONE);
- } else {
- changed = REGION_CREATE(pScreen, NullBox, 0);
- }
-
- (*ps->CompositeRects)(op, pDst, color, nRect, rects);
-
- if (REGION_NOTEMPTY(pScreen, changed))
- add_changed(pScreen, changed);
-
- REGION_DESTROY(pScreen, changed);
-
- RENDER_EPILOGUE(CompositeRects);
- }
-
- static inline short FixedToShort(xFixed fixed)
- {
- return (fixed + 0x8000) >> 16;
- }
-
- static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int ntrap, xTrapezoid * traps)
- {
- RegionRec changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, Trapezoids);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec box;
- RegionRec fbreg;
-
- // FIXME: We do a very crude bounding box around everything.
- // Might not be worth optimizing since this call is rarely
- // used.
- box.x1 = SHRT_MAX;
- box.y1 = SHRT_MAX;
- box.x2 = 0;
- box.y2 = 0;
- for (int i = 0;i < ntrap;i++) {
- if (FixedToShort(traps[i].left.p1.x) < box.x1)
- box.x1 = FixedToShort(traps[i].left.p1.x);
- if (FixedToShort(traps[i].left.p2.x) < box.x1)
- box.x1 = FixedToShort(traps[i].left.p2.x);
- if (FixedToShort(traps[i].top) < box.y1)
- box.y1 = FixedToShort(traps[i].top);
- if (FixedToShort(traps[i].right.p1.x) > box.x2)
- box.x2 = FixedToShort(traps[i].right.p1.x);
- if (FixedToShort(traps[i].right.p2.x) > box.x2)
- box.x2 = FixedToShort(traps[i].right.p2.x);
- if (FixedToShort(traps[i].bottom) > box.y2)
- box.y2 = FixedToShort(traps[i].bottom);
- }
-
- box.x1 += pDst->pDrawable->x;
- box.y1 += pDst->pDrawable->y;
- box.x2 += pDst->pDrawable->x;
- box.y2 += pDst->pDrawable->y;
- REGION_INIT(pScreen, &changed, &box, 0);
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &box, 0);
-
- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- REGION_NULL(pScreen, &changed);
- }
-
- (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pScreen, &changed);
-
- REGION_UNINIT(pScreen, &changed);
-
- RENDER_EPILOGUE(Trapezoids);
- }
-
- static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int ntri, xTriangle * tris)
- {
- RegionRec changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, Triangles);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec box;
- RegionRec fbreg;
-
- // FIXME: We do a very crude bounding box around everything.
- // Might not be worth optimizing since this call is rarely
- // used.
- box.x1 = SHRT_MAX;
- box.y1 = SHRT_MAX;
- box.x2 = 0;
- box.y2 = 0;
- for (int i = 0;i < ntri;i++) {
- xFixed left, right, top, bottom;
-
- left = min(min(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);
- right = max(max(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);
- top = min(min(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);
- bottom = max(max(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);
-
- if (FixedToShort(left) < box.x1)
- box.x1 = FixedToShort(left);
- if (FixedToShort(top) < box.y1)
- box.y1 = FixedToShort(top);
- if (FixedToShort(right) > box.x2)
- box.x2 = FixedToShort(right);
- if (FixedToShort(bottom) > box.y2)
- box.y2 = FixedToShort(bottom);
- }
-
- box.x1 += pDst->pDrawable->x;
- box.y1 += pDst->pDrawable->y;
- box.x2 += pDst->pDrawable->x;
- box.y2 += pDst->pDrawable->y;
- REGION_INIT(pScreen, &changed, &box, 0);
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &box, 0);
-
- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- REGION_NULL(pScreen, &changed);
- }
-
- (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pScreen, &changed);
-
- REGION_UNINIT(pScreen, &changed);
-
- RENDER_EPILOGUE(Triangles);
- }
-
- #if PICTURE_SCREEN_VERSION >= 2
-
- static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed * points)
- {
- RegionRec changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriStrip);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec box;
- RegionRec fbreg;
-
- // FIXME: We do a very crude bounding box around everything.
- // Might not be worth optimizing since this call is rarely
- // used.
- box.x1 = SHRT_MAX;
- box.y1 = SHRT_MAX;
- box.x2 = 0;
- box.y2 = 0;
- for (int i = 0;i < npoint;i++) {
- if (FixedToShort(points[i].x) < box.x1)
- box.x1 = FixedToShort(points[i].x);
- if (FixedToShort(points[i].y) < box.y1)
- box.y1 = FixedToShort(points[i].y);
- if (FixedToShort(points[i].x) > box.x2)
- box.x2 = FixedToShort(points[i].x);
- if (FixedToShort(points[i].y) > box.y2)
- box.y2 = FixedToShort(points[i].y);
- }
-
- box.x1 += pDst->pDrawable->x;
- box.y1 += pDst->pDrawable->y;
- box.x2 += pDst->pDrawable->x;
- box.y2 += pDst->pDrawable->y;
- REGION_INIT(pScreen, &changed, &box, 0);
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &box, 0);
-
- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- REGION_NULL(pScreen, &changed);
- }
-
- (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pScreen, &changed);
-
- REGION_UNINIT(pScreen, &changed);
-
- RENDER_EPILOGUE(TriStrip);
- }
-
- static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed * points)
- {
- RegionRec changed;
-
- RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriFan);
-
- if (is_visible(pDst->pDrawable)) {
- BoxRec box;
- RegionRec fbreg;
-
- // FIXME: We do a very crude bounding box around everything.
- // Might not be worth optimizing since this call is rarely
- // used.
- box.x1 = SHRT_MAX;
- box.y1 = SHRT_MAX;
- box.x2 = 0;
- box.y2 = 0;
- for (int i = 0;i < npoint;i++) {
- if (FixedToShort(points[i].x) < box.x1)
- box.x1 = FixedToShort(points[i].x);
- if (FixedToShort(points[i].y) < box.y1)
- box.y1 = FixedToShort(points[i].y);
- if (FixedToShort(points[i].x) > box.x2)
- box.x2 = FixedToShort(points[i].x);
- if (FixedToShort(points[i].y) > box.y2)
- box.y2 = FixedToShort(points[i].y);
- }
-
- box.x1 += pDst->pDrawable->x;
- box.y1 += pDst->pDrawable->y;
- box.x2 += pDst->pDrawable->x;
- box.y2 += pDst->pDrawable->y;
- REGION_INIT(pScreen, &changed, &box, 0);
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pScreen->width;
- box.y2 = pScreen->height;
- REGION_INIT(pScreen, &fbreg, &box, 0);
-
- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
-
- REGION_UNINIT(pScreen, &fbreg);
- } else {
- REGION_NULL(pScreen, &changed);
- }
-
- (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pScreen, &changed);
-
- REGION_UNINIT(pScreen, &changed);
-
- RENDER_EPILOGUE(TriFan);
- }
-
- #endif /* PICTURE_SCREEN_VERSION */
-
- #endif /* RENDER */
-
- // Unwrap and rewrap helpers
-
- #define RANDR_PROLOGUE(field) \
- rrScrPrivPtr rp = rrGetScrPriv(pScreen); \
- vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
- unwrap(vncHooksScreen, rp, rr##field); \
- DBGPRINT((stderr,"vncHooksRandR" #field " called\n"));
-
- #define RANDR_EPILOGUE(field) \
- wrap(vncHooksScreen, rp, rr##field, vncHooksRandR##field); \
-
- // RandRSetConfig - follow any framebuffer changes
-
- static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
- int rate, RRScreenSizePtr pSize)
- {
- Bool ret;
-
- RANDR_PROLOGUE(SetConfig);
-
- vncPreScreenResize(pScreen->myNum);
- ret = (*rp->rrSetConfig)(pScreen, rotation, rate, pSize);
- vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);
-
- RANDR_EPILOGUE(SetConfig);
-
- if (!ret)
- return FALSE;
-
- return TRUE;
- }
-
- static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
- CARD16 width, CARD16 height,
- CARD32 mmWidth, CARD32 mmHeight)
- {
- Bool ret;
-
- RANDR_PROLOGUE(ScreenSetSize);
-
- vncPreScreenResize(pScreen->myNum);
- ret = (*rp->rrScreenSetSize)(pScreen, width, height, mmWidth, mmHeight);
- vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);
-
- RANDR_EPILOGUE(ScreenSetSize);
-
- if (!ret)
- return FALSE;
-
- return TRUE;
- }
-
- static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
- RRModePtr mode, int x, int y,
- Rotation rotation, int num_outputs,
- RROutputPtr *outputs)
- {
- Bool ret;
-
- RANDR_PROLOGUE(CrtcSet);
-
- ret = (*rp->rrCrtcSet)(pScreen, crtc, mode, x, y, rotation,
- num_outputs, outputs);
-
- RANDR_EPILOGUE(CrtcSet);
-
- if (!ret)
- return FALSE;
-
- vncRefreshScreenLayout(pScreen->myNum);
-
- return TRUE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GC "funcs"
- //
-
- // Unwrap and rewrap helpers
-
- #define GC_FUNC_PROLOGUE(pGC, name)\
- vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
- unwrap(pGCPriv, pGC, funcs);\
- if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)\
- DBGPRINT((stderr,"vncHooks" #name " called\n"))
-
- #define GC_FUNC_EPILOGUE(pGC)\
- wrap(pGCPriv, pGC, funcs, &vncHooksGCFuncs);\
- if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &vncHooksGCOps)
-
- // ValidateGC - wrap the "ops" if the drawable is on screen
-
- static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable)
- {
- GC_FUNC_PROLOGUE(pGC, ValidateGC);
- (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
- if (is_visible(pDrawable)) {
- pGCPriv->ops = pGC->ops;
- DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
- } else {
- pGCPriv->ops = NULL;
- }
- GC_FUNC_EPILOGUE(pGC);
- }
-
- // Other GC funcs - just unwrap and call on
-
- static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
- GC_FUNC_PROLOGUE(pGC, ChangeGC);
- (*pGC->funcs->ChangeGC) (pGC, mask);
- GC_FUNC_EPILOGUE(pGC);
- }
- static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
- GC_FUNC_PROLOGUE(dst, CopyGC);
- (*dst->funcs->CopyGC) (src, mask, dst);
- GC_FUNC_EPILOGUE(dst);
- }
- static void vncHooksDestroyGC(GCPtr pGC) {
- GC_FUNC_PROLOGUE(pGC, DestroyGC);
- (*pGC->funcs->DestroyGC) (pGC);
- GC_FUNC_EPILOGUE(pGC);
- }
- static void vncHooksChangeClip(GCPtr pGC, int type, void * pValue, int nrects)
- {
- GC_FUNC_PROLOGUE(pGC, ChangeClip);
- (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
- GC_FUNC_EPILOGUE(pGC);
- }
- static void vncHooksDestroyClip(GCPtr pGC) {
- GC_FUNC_PROLOGUE(pGC, DestroyClip);
- (*pGC->funcs->DestroyClip) (pGC);
- GC_FUNC_EPILOGUE(pGC);
- }
- static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
- GC_FUNC_PROLOGUE(dst, CopyClip);
- (*dst->funcs->CopyClip) (dst, src);
- GC_FUNC_EPILOGUE(dst);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- //
- // GC "ops"
- //
-
- // Unwrap and rewrap helpers
-
- #if XORG >= 116
- #define GC_OP_PROLOGUE(pGC, name)\
- vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
- const GCFuncs *oldFuncs = pGC->funcs;\
- unwrap(pGCPriv, pGC, funcs);\
- unwrap(pGCPriv, pGC, ops);\
- DBGPRINT((stderr,"vncHooks" #name " called\n"))
- #else
- #define GC_OP_PROLOGUE(pGC, name)\
- vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
- GCFuncs *oldFuncs = pGC->funcs;\
- unwrap(pGCPriv, pGC, funcs);\
- unwrap(pGCPriv, pGC, ops);\
- DBGPRINT((stderr,"vncHooks" #name " called\n"))
- #endif
-
- #define GC_OP_EPILOGUE(pGC)\
- wrap(pGCPriv, pGC, funcs, oldFuncs); \
- wrap(pGCPriv, pGC, ops, &vncHooksGCOps)
-
- // FillSpans - assume the entire clip region is damaged. This is pessimistic,
- // but I believe this function is rarely used so it doesn't matter.
-
- static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted)
- {
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, FillSpans);
-
- REGION_NULL(pGC->pScreen, ®);
- REGION_COPY(pGC->pScreen, ®, pGC->pCompositeClip);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- REGION_INTERSECT(pScreen, ®, ®, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- GC_OP_EPILOGUE(pGC);
- }
-
- // SetSpans - assume the entire clip region is damaged. This is pessimistic,
- // but I believe this function is rarely used so it doesn't matter.
-
- static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted)
- {
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, SetSpans);
-
- REGION_NULL(pGC->pScreen, ®);
- REGION_COPY(pGC->pScreen, ®, pGC->pCompositeClip);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- REGION_INTERSECT(pScreen, ®, ®, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- GC_OP_EPILOGUE(pGC);
- }
-
- // PutImage - changed region is the given rectangle, clipped by pCompositeClip
-
- static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PutImage);
-
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
- pBits);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- GC_OP_EPILOGUE(pGC);
- }
-
- // CopyArea - destination of the copy is the dest rectangle, clipped by
- // pCompositeClip. Any parts of the destination which cannot be copied from
- // the source (could be all of it) go into the changed region.
-
- static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty)
- {
- RegionRec dst, src, changed;
-
- RegionPtr ret;
-
- GC_OP_PROLOGUE(pGC, CopyArea);
-
- // Apparently this happens now and then...
- if ((w == 0) || (h == 0))
- REGION_NULL(pGC->pScreen, &dst);
- else {
- BoxRec box;
-
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- REGION_INIT(pGC->pScreen, &dst, &box, 0);
- }
-
- REGION_INTERSECT(pGC->pScreen, &dst, &dst, pGC->pCompositeClip);
-
- // The source of the data has to be something that's on screen.
- if (is_visible(pSrc)) {
- BoxRec box;
-
- box.x1 = srcx + pSrc->x;
- box.y1 = srcy + pSrc->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- REGION_INIT(pGC->pScreen, &src, &box, 0);
-
- if ((pSrc->type == DRAWABLE_WINDOW) &&
- REGION_NOTEMPTY(pScreen, &((WindowPtr)pSrc)->clipList)) {
- REGION_INTERSECT(pScreen, &src, &src, &((WindowPtr)pSrc)->clipList);
- }
-
- REGION_TRANSLATE(pScreen, &src,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
- } else {
- REGION_NULL(pGC->pScreen, &src);
- }
-
- REGION_NULL(pGC->pScreen, &changed);
-
- REGION_SUBTRACT(pScreen, &changed, &dst, &src);
- REGION_INTERSECT(pScreen, &dst, &dst, &src);
-
- ret = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
-
- if (REGION_NOTEMPTY(pScreen, &dst))
- add_copied(pGC->pScreen, &dst,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
-
- if (REGION_NOTEMPTY(pScreen, &changed))
- add_changed(pGC->pScreen, &changed);
-
- REGION_UNINIT(pGC->pScreen, &dst);
- REGION_UNINIT(pGC->pScreen, &src);
- REGION_UNINIT(pGC->pScreen, &changed);
-
- GC_OP_EPILOGUE(pGC);
-
- return ret;
- }
-
-
- // CopyPlane - changed region is the destination rectangle, clipped by
- // pCompositeClip
-
- static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane)
- {
- BoxRec box;
- RegionRec reg;
-
- RegionPtr ret;
-
- GC_OP_PROLOGUE(pGC, CopyPlane);
-
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- ret = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- GC_OP_EPILOGUE(pGC);
-
- return ret;
- }
-
- // PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
-
- static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts)
- {
- int minX, minY, maxX, maxY;
- int i;
-
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PolyPoint);
-
- if (npt == 0) {
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
- goto out;
- }
-
- minX = pts[0].x;
- maxX = pts[0].x;
- minY = pts[0].y;
- maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (i = 1; i < npt; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- } else {
- for (i = 1; i < npt; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // Polylines - changed region is the union of the bounding rects of each line,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines,
- // just use the bounding rect of all the lines.
-
- static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts)
- {
- int nRegRects;
- xRectangle regRects[MAX_RECTS_PER_OP];
-
- int lw;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, Polylines);
-
- if (npt == 0) {
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
- goto out;
- }
-
- nRegRects = npt - 1;
-
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
-
- if (npt == 1)
- {
- // a single point
- nRegRects = 1;
- regRects[0].x = pDrawable->x + ppts[0].x - lw;
- regRects[0].y = pDrawable->y + ppts[0].y - lw;
- regRects[0].width = 2*lw;
- regRects[0].height = 2*lw;
- }
- else
- {
- /*
- * mitered joins can project quite a way from
- * the line end; the 11 degree miter limit limits
- * this extension to lw / (2 * tan(11/2)), rounded up
- * and converted to int yields 6 * lw
- */
-
- int extra;
-
- int prevX, prevY, curX, curY;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- int i;
-
- extra = lw / 2;
- if (pGC->joinStyle == JoinMiter) {
- extra = 6 * lw;
- }
-
- prevX = ppts[0].x + pDrawable->x;
- prevY = ppts[0].y + pDrawable->y;
- minX = maxX = prevX;
- minY = maxY = prevY;
-
- for (i = 0; i < nRegRects; i++) {
- if (mode == CoordModeOrigin) {
- curX = pDrawable->x + ppts[i+1].x;
- curY = pDrawable->y + ppts[i+1].y;
- } else {
- curX = prevX + ppts[i+1].x;
- curY = prevY + ppts[i+1].y;
- }
-
- if (prevX > curX) {
- rectX1 = curX - extra;
- rectX2 = prevX + extra + 1;
- } else {
- rectX1 = prevX - extra;
- rectX2 = curX + extra + 1;
- }
-
- if (prevY > curY) {
- rectY1 = curY - extra;
- rectY2 = prevY + extra + 1;
- } else {
- rectY1 = prevY - extra;
- rectY2 = curY + extra + 1;
- }
-
- if (nRegRects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
-
- prevX = curX;
- prevY = curY;
- }
-
- if (nRegRects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolySegment - changed region is the union of the bounding rects of each
- // segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
- // segments, just use the bounding rect of all the segments.
-
- static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs)
- {
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects;
-
- int lw, extra;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- int i;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, PolySegment);
-
- if (nseg == 0) {
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
- goto out;
- }
-
- nRegRects = nseg;
-
- lw = pGC->lineWidth;
- extra = lw / 2;
-
- minX = maxX = segs[0].x1;
- minY = maxY = segs[0].y1;
-
- for (i = 0; i < nseg; i++) {
- if (segs[i].x1 > segs[i].x2) {
- rectX1 = pDrawable->x + segs[i].x2 - extra;
- rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
- } else {
- rectX1 = pDrawable->x + segs[i].x1 - extra;
- rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
- }
-
- if (segs[i].y1 > segs[i].y2) {
- rectY1 = pDrawable->y + segs[i].y2 - extra;
- rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
- } else {
- rectY1 = pDrawable->y + segs[i].y1 - extra;
- rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
- }
-
- if (nseg <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nseg > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolyRectangle - changed region is the union of the bounding rects around
- // each side of the outline rectangles, clipped by pCompositeClip. If there
- // are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
- // the rectangles.
-
- static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
- {
- xRectangle regRects[MAX_RECTS_PER_OP*4];
- int nRegRects;
-
- int lw, extra;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- int i;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, PolyRectangle);
-
- if (nrects == 0) {
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
- goto out;
- }
-
- nRegRects = nrects * 4;
-
- lw = pGC->lineWidth;
- extra = lw / 2;
-
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i*4].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4].height = 1 + 2 * extra;
-
- regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+1].width = 1 + 2 * extra;
- regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;
- regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+2].width = 1 + 2 * extra;
- regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;
- regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4+3].height = 1 + 2 * extra;
- } else {
- rectX1 = pDrawable->x + rects[i].x - extra;
- rectY1 = pDrawable->y + rects[i].y - extra;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolyArc - changed region is the union of bounding rects around each arc,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
- // arcs, just use the bounding rect of all the arcs.
-
- static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
- {
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects;
-
- int lw, extra;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- int i;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, PolyArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
- goto out;
- }
-
- nRegRects = narcs;
-
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
- extra = lw / 2;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
-
- // FillPolygon - changed region is the bounding rect around the polygon,
- // clipped by pCompositeClip
-
- static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts)
- {
- int minX, minY, maxX, maxY;
- int i;
-
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, FillPolygon);
-
- if (count == 0) {
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
- goto out;
- }
-
- minX = pts[0].x;
- maxX = pts[0].x;
- minY = pts[0].y;
- maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (i = 1; i < count; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- } else {
- for (i = 1; i < count; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolyFillRect - changed region is the union of the rectangles, clipped by
- // pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just
- // use the bounding rect of all the rectangles.
-
- static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
- {
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- int i;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, PolyFillRect);
-
- if (nrects == 0) {
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
- goto out;
- }
-
- nRegRects = nrects;
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rects[i].x + pDrawable->x;
- regRects[i].y = rects[i].y + pDrawable->y;
- regRects[i].width = rects[i].width;
- regRects[i].height = rects[i].height;
- } else {
- rectX1 = pDrawable->x + rects[i].x;
- rectY1 = pDrawable->y + rects[i].y;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolyFillArc - changed region is the union of bounding rects around each arc,
- // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs,
- // just use the bounding rect of all the arcs.
-
- static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
- {
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects;
-
- int lw, extra;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- int i;
-
- RegionPtr reg;
-
- GC_OP_PROLOGUE(pGC, PolyFillArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
- goto out;
- }
-
- nRegRects = narcs;
-
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
- extra = lw / 2;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
-
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-
- add_changed(pGC->pScreen, reg);
-
- REGION_DESTROY(pGC->pScreen, reg);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // GetTextBoundingRect - calculate a bounding rectangle around n chars of a
- // font. Not particularly accurate, but good enough.
-
- static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
- int y, int nchars, BoxPtr box)
- {
- int ascent = max(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
- int descent = max(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
- int charWidth = max(FONTMAXBOUNDS(font,rightSideBearing),
- FONTMAXBOUNDS(font,characterWidth));
-
- box->x1 = pDrawable->x + x;
- box->y1 = pDrawable->y + y - ascent;
- box->x2 = box->x1 + charWidth * nchars;
- box->y2 = box->y1 + ascent + descent;
-
- if (FONTMINBOUNDS(font,leftSideBearing) < 0)
- box->x1 += FONTMINBOUNDS(font,leftSideBearing);
- }
-
- // PolyText8 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
- {
- int ret;
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PolyText8);
-
- if (count == 0) {
- ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
-
- return ret;
- }
-
- // PolyText16 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
- {
- int ret;
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PolyText16);
-
- if (count == 0) {
- ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
-
- return ret;
- }
-
- // ImageText8 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, ImageText8);
-
- if (count == 0) {
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // ImageText16 - changed region is bounding rect around count chars, clipped by
- // pCompositeClip
-
- static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, ImageText16);
-
- if (count == 0) {
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
- // by pCompositeClip
-
- static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, void * pglyphBase)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, ImageGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
- // by pCompositeClip
-
- static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, void * pglyphBase)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PolyGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- goto out;
- }
-
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- out:
- GC_OP_EPILOGUE(pGC);
- }
-
- // PushPixels - changed region is the given rectangle, clipped by
- // pCompositeClip
-
- static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y)
- {
- BoxRec box;
- RegionRec reg;
-
- GC_OP_PROLOGUE(pGC, PushPixels);
-
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- REGION_INIT(pGC->pScreen, ®, &box, 0);
- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip);
-
- (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
-
- add_changed(pGC->pScreen, ®);
-
- REGION_UNINIT(pGC->pScreen, ®);
-
- GC_OP_EPILOGUE(pGC);
- }
|