You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vncHooks.c 68KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2009-2017 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_DIX_CONFIG_H
  20. #include <dix-config.h>
  21. #endif
  22. #include <stdio.h>
  23. #include "vncHooks.h"
  24. #include "vncExtInit.h"
  25. #include "xorg-version.h"
  26. #include "scrnintstr.h"
  27. #include "windowstr.h"
  28. #include "cursorstr.h"
  29. #include "gcstruct.h"
  30. #include "regionstr.h"
  31. #include "dixfontstr.h"
  32. #include "colormapst.h"
  33. #ifdef RENDER
  34. #include "picturestr.h"
  35. #endif
  36. #include "randrstr.h"
  37. #define DBGPRINT(x) //(fprintf x)
  38. // MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
  39. // operations like Polylines and PolySegment. If the operation is more complex
  40. // than this, we simply use the bounding box. Ideally it would be a
  41. // command-line option, but that would involve an extra malloc each time, so we
  42. // fix it here.
  43. #define MAX_RECTS_PER_OP 5
  44. // vncHooksScreenRec and vncHooksGCRec contain pointers to the original
  45. // functions which we "wrap" in order to hook the screen changes. The screen
  46. // functions are each wrapped individually, while the GC "funcs" and "ops" are
  47. // wrapped as a unit.
  48. typedef struct _vncHooksScreenRec {
  49. int ignoreHooks;
  50. CloseScreenProcPtr CloseScreen;
  51. CreateGCProcPtr CreateGC;
  52. CopyWindowProcPtr CopyWindow;
  53. ClearToBackgroundProcPtr ClearToBackground;
  54. #if XORG < 110
  55. RestoreAreasProcPtr RestoreAreas;
  56. #endif
  57. DisplayCursorProcPtr DisplayCursor;
  58. ScreenBlockHandlerProcPtr BlockHandler;
  59. #ifdef RENDER
  60. CompositeProcPtr Composite;
  61. GlyphsProcPtr Glyphs;
  62. CompositeRectsProcPtr CompositeRects;
  63. TrapezoidsProcPtr Trapezoids;
  64. TrianglesProcPtr Triangles;
  65. #if PICTURE_SCREEN_VERSION >= 2
  66. TriStripProcPtr TriStrip;
  67. TriFanProcPtr TriFan;
  68. #endif
  69. #endif
  70. RRSetConfigProcPtr rrSetConfig;
  71. RRScreenSetSizeProcPtr rrScreenSetSize;
  72. RRCrtcSetProcPtr rrCrtcSet;
  73. } vncHooksScreenRec, *vncHooksScreenPtr;
  74. typedef struct _vncHooksGCRec {
  75. #if XORG >= 116
  76. const GCFuncs *funcs;
  77. const GCOps *ops;
  78. #else
  79. GCFuncs *funcs;
  80. GCOps *ops;
  81. #endif
  82. } vncHooksGCRec, *vncHooksGCPtr;
  83. #define wrap(priv, real, mem, func) {\
  84. priv->mem = real->mem; \
  85. real->mem = func; \
  86. }
  87. #define unwrap(priv, real, mem) {\
  88. real->mem = priv->mem; \
  89. }
  90. #if XORG < 19
  91. static int vncHooksScreenPrivateKeyIndex;
  92. static int vncHooksGCPrivateKeyIndex;
  93. static DevPrivateKey vncHooksScreenPrivateKey = &vncHooksScreenPrivateKeyIndex;
  94. static DevPrivateKey vncHooksGCPrivateKey = &vncHooksGCPrivateKeyIndex;
  95. #else
  96. static DevPrivateKeyRec vncHooksScreenKeyRec;
  97. static DevPrivateKeyRec vncHooksGCKeyRec;
  98. #define vncHooksScreenPrivateKey (&vncHooksScreenKeyRec)
  99. #define vncHooksGCPrivateKey (&vncHooksGCKeyRec)
  100. #endif
  101. #define vncHooksScreenPrivate(pScreen) \
  102. (vncHooksScreenPtr) dixLookupPrivate(&(pScreen)->devPrivates, \
  103. vncHooksScreenPrivateKey)
  104. #define vncHooksGCPrivate(pGC) \
  105. (vncHooksGCPtr) dixLookupPrivate(&(pGC)->devPrivates, \
  106. vncHooksGCPrivateKey)
  107. // screen functions
  108. #if XORG <= 112
  109. static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
  110. #else
  111. static Bool vncHooksCloseScreen(ScreenPtr pScreen);
  112. #endif
  113. static Bool vncHooksCreateGC(GCPtr pGC);
  114. static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
  115. RegionPtr pOldRegion);
  116. static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
  117. int h, Bool generateExposures);
  118. #if XORG < 110
  119. static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
  120. #endif
  121. static Bool vncHooksDisplayCursor(DeviceIntPtr pDev,
  122. ScreenPtr pScreen, CursorPtr cursor);
  123. #if XORG <= 112
  124. static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
  125. pointer pReadmask);
  126. #elif XORG <= 118
  127. static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout,
  128. void * pReadmask);
  129. #else
  130. static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout);
  131. #endif
  132. #ifdef RENDER
  133. static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
  134. PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
  135. INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
  136. static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  137. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
  138. GlyphListPtr lists, GlyphPtr * glyphs);
  139. static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,
  140. xRenderColor * color, int nRect, xRectangle *rects);
  141. static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  142. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  143. int ntrap, xTrapezoid * traps);
  144. static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  145. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  146. int ntri, xTriangle * tris);
  147. #if PICTURE_SCREEN_VERSION >= 2
  148. static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  149. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  150. int npoint, xPointFixed * points);
  151. static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  152. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  153. int npoint, xPointFixed * points);
  154. #endif
  155. #endif
  156. static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
  157. int rate, RRScreenSizePtr pSize);
  158. static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
  159. CARD16 width, CARD16 height,
  160. CARD32 mmWidth, CARD32 mmHeight);
  161. static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
  162. RRModePtr mode, int x, int y,
  163. Rotation rotation, int numOutputs,
  164. RROutputPtr *outputs);
  165. // GC "funcs"
  166. static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
  167. DrawablePtr pDrawable);
  168. static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
  169. static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
  170. static void vncHooksDestroyGC(GCPtr pGC);
  171. static void vncHooksChangeClip(GCPtr pGC, int type, void * pValue,int nrects);
  172. static void vncHooksDestroyClip(GCPtr pGC);
  173. static void vncHooksCopyClip(GCPtr dst, GCPtr src);
  174. static GCFuncs vncHooksGCFuncs = {
  175. vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
  176. vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
  177. };
  178. // GC "ops"
  179. static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
  180. DDXPointPtr pptInit, int *pwidthInit,
  181. int fSorted);
  182. static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
  183. DDXPointPtr ppt, int *pwidth, int nspans,
  184. int fSorted);
  185. static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
  186. int x, int y, int w, int h, int leftPad,
  187. int format, char *pBits);
  188. static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
  189. GCPtr pGC, int srcx, int srcy, int w, int h,
  190. int dstx, int dsty);
  191. static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
  192. GCPtr pGC, int srcx, int srcy, int w, int h,
  193. int dstx, int dsty, unsigned long plane);
  194. static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
  195. int npt, xPoint *pts);
  196. static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
  197. int npt, DDXPointPtr ppts);
  198. static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
  199. xSegment *segs);
  200. static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
  201. xRectangle *rects);
  202. static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
  203. xArc *arcs);
  204. static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
  205. int mode, int count, DDXPointPtr pts);
  206. static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
  207. xRectangle *rects);
  208. static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
  209. xArc *arcs);
  210. static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  211. int count, char *chars);
  212. static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  213. int count, unsigned short *chars);
  214. static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  215. int count, char *chars);
  216. static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  217. int count, unsigned short *chars);
  218. static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
  219. int y, unsigned int nglyph,
  220. CharInfoPtr *ppci, void * pglyphBase);
  221. static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
  222. int y, unsigned int nglyph,
  223. CharInfoPtr *ppci, void * pglyphBase);
  224. static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
  225. DrawablePtr pDrawable, int w, int h, int x,
  226. int y);
  227. static GCOps vncHooksGCOps = {
  228. vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
  229. vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
  230. vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
  231. vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
  232. vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
  233. vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
  234. };
  235. /////////////////////////////////////////////////////////////////////////////
  236. // vncHooksInit() is called at initialisation time and every time the server
  237. // resets. It is called once for each screen, but the indexes are only
  238. // allocated once for each server generation.
  239. int vncHooksInit(int scrIdx)
  240. {
  241. ScreenPtr pScreen;
  242. vncHooksScreenPtr vncHooksScreen;
  243. #ifdef RENDER
  244. PictureScreenPtr ps;
  245. #endif
  246. rrScrPrivPtr rp;
  247. pScreen = screenInfo.screens[scrIdx];
  248. if (sizeof(BoxRec) != sizeof(struct UpdateRect)) {
  249. ErrorF("vncHooksInit: Incompatible BoxRec size\n");
  250. return FALSE;
  251. }
  252. #if XORG < 19
  253. if (!dixRequestPrivate(vncHooksScreenPrivateKey, sizeof(vncHooksScreenRec))) {
  254. ErrorF("vncHooksInit: Allocation of vncHooksScreen failed\n");
  255. return FALSE;
  256. }
  257. if (!dixRequestPrivate(vncHooksGCPrivateKey, sizeof(vncHooksGCRec))) {
  258. ErrorF("vncHooksInit: Allocation of vncHooksGCRec failed\n");
  259. return FALSE;
  260. }
  261. #else
  262. if (!dixRegisterPrivateKey(&vncHooksScreenKeyRec, PRIVATE_SCREEN,
  263. sizeof(vncHooksScreenRec))) {
  264. ErrorF("vncHooksInit: Allocation of vncHooksScreen failed\n");
  265. return FALSE;
  266. }
  267. if (!dixRegisterPrivateKey(&vncHooksGCKeyRec, PRIVATE_GC,
  268. sizeof(vncHooksGCRec))) {
  269. ErrorF("vncHooksInit: Allocation of vncHooksGCRec failed\n");
  270. return FALSE;
  271. }
  272. #endif
  273. vncHooksScreen = vncHooksScreenPrivate(pScreen);
  274. vncHooksScreen->ignoreHooks = 0;
  275. wrap(vncHooksScreen, pScreen, CloseScreen, vncHooksCloseScreen);
  276. wrap(vncHooksScreen, pScreen, CreateGC, vncHooksCreateGC);
  277. wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow);
  278. wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground);
  279. #if XORG < 110
  280. wrap(vncHooksScreen, pScreen, RestoreAreas, vncHooksRestoreAreas);
  281. #endif
  282. wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor);
  283. wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler);
  284. #ifdef RENDER
  285. ps = GetPictureScreenIfSet(pScreen);
  286. if (ps) {
  287. wrap(vncHooksScreen, ps, Composite, vncHooksComposite);
  288. wrap(vncHooksScreen, ps, Glyphs, vncHooksGlyphs);
  289. wrap(vncHooksScreen, ps, CompositeRects, vncHooksCompositeRects);
  290. wrap(vncHooksScreen, ps, Trapezoids, vncHooksTrapezoids);
  291. wrap(vncHooksScreen, ps, Triangles, vncHooksTriangles);
  292. #if PICTURE_SCREEN_VERSION >= 2
  293. wrap(vncHooksScreen, ps, TriStrip, vncHooksTriStrip);
  294. wrap(vncHooksScreen, ps, TriFan, vncHooksTriFan);
  295. #endif
  296. }
  297. #endif
  298. rp = rrGetScrPriv(pScreen);
  299. if (rp) {
  300. /* Some RandR callbacks are optional */
  301. if (rp->rrSetConfig)
  302. wrap(vncHooksScreen, rp, rrSetConfig, vncHooksRandRSetConfig);
  303. if (rp->rrScreenSetSize)
  304. wrap(vncHooksScreen, rp, rrScreenSetSize, vncHooksRandRScreenSetSize);
  305. if (rp->rrCrtcSet)
  306. wrap(vncHooksScreen, rp, rrCrtcSet, vncHooksRandRCrtcSet);
  307. }
  308. return TRUE;
  309. }
  310. /////////////////////////////////////////////////////////////////////////////
  311. // vncGetScreenImage() grabs a chunk of data from the main screen into the
  312. // provided buffer. It lives here rather than in XorgGlue.c because it
  313. // temporarily pauses the hooks.
  314. void vncGetScreenImage(int scrIdx, int x, int y, int width, int height,
  315. char *buffer, int strideBytes)
  316. {
  317. ScreenPtr pScreen = screenInfo.screens[scrIdx];
  318. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
  319. int i;
  320. vncHooksScreen->ignoreHooks++;
  321. // We do one line at a time since GetImage() cannot handle stride
  322. for (i = y; i < y + height; i++) {
  323. DrawablePtr pDrawable;
  324. #if XORG < 19
  325. pDrawable = (DrawablePtr) WindowTable[scrIdx];
  326. #else
  327. pDrawable = (DrawablePtr) pScreen->root;
  328. #endif
  329. (*pScreen->GetImage) (pDrawable, x, i, width, 1,
  330. ZPixmap, (unsigned long)~0L, buffer);
  331. buffer += strideBytes;
  332. }
  333. vncHooksScreen->ignoreHooks--;
  334. }
  335. /////////////////////////////////////////////////////////////////////////////
  336. //
  337. // Helper functions
  338. //
  339. static inline void add_changed(ScreenPtr pScreen, RegionPtr reg)
  340. {
  341. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
  342. if (vncHooksScreen->ignoreHooks)
  343. return;
  344. vncAddChanged(pScreen->myNum,
  345. (const struct UpdateRect*)REGION_EXTENTS(pScreen, reg),
  346. REGION_NUM_RECTS(reg),
  347. (const struct UpdateRect*)REGION_RECTS(reg));
  348. }
  349. static inline void add_copied(ScreenPtr pScreen, RegionPtr dst,
  350. int dx, int dy)
  351. {
  352. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen);
  353. if (vncHooksScreen->ignoreHooks)
  354. return;
  355. vncAddCopied(pScreen->myNum,
  356. (const struct UpdateRect*)REGION_EXTENTS(pScreen, dst),
  357. REGION_NUM_RECTS(dst),
  358. (const struct UpdateRect*)REGION_RECTS(dst), dx, dy);
  359. }
  360. static inline Bool is_visible(DrawablePtr drawable)
  361. {
  362. PixmapPtr scrPixmap;
  363. scrPixmap = drawable->pScreen->GetScreenPixmap(drawable->pScreen);
  364. if (drawable->type == DRAWABLE_WINDOW) {
  365. WindowPtr window;
  366. PixmapPtr winPixmap;
  367. window = (WindowPtr)drawable;
  368. winPixmap = drawable->pScreen->GetWindowPixmap(window);
  369. if (!window->viewable)
  370. return FALSE;
  371. if (winPixmap != scrPixmap)
  372. return FALSE;
  373. return TRUE;
  374. }
  375. if (drawable != &scrPixmap->drawable)
  376. return FALSE;
  377. return TRUE;
  378. }
  379. /////////////////////////////////////////////////////////////////////////////
  380. //
  381. // screen functions
  382. //
  383. // Unwrap and rewrap helpers
  384. #define SCREEN_PROLOGUE(scrn,field) \
  385. ScreenPtr pScreen = scrn; \
  386. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
  387. unwrap(vncHooksScreen, pScreen, field); \
  388. DBGPRINT((stderr,"vncHooks" #field " called\n"));
  389. #define SCREEN_EPILOGUE(field) \
  390. wrap(vncHooksScreen, pScreen, field, vncHooks##field); \
  391. // CloseScreen - unwrap the screen functions and call the original CloseScreen
  392. // function
  393. #if XORG <= 112
  394. static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
  395. #else
  396. static Bool vncHooksCloseScreen(ScreenPtr pScreen_)
  397. #endif
  398. {
  399. #ifdef RENDER
  400. PictureScreenPtr ps;
  401. #endif
  402. rrScrPrivPtr rp;
  403. SCREEN_PROLOGUE(pScreen_, CloseScreen);
  404. unwrap(vncHooksScreen, pScreen, CreateGC);
  405. unwrap(vncHooksScreen, pScreen, CopyWindow);
  406. unwrap(vncHooksScreen, pScreen, ClearToBackground);
  407. #if XORG < 110
  408. unwrap(vncHooksScreen, pScreen, RestoreAreas);
  409. #endif
  410. unwrap(vncHooksScreen, pScreen, DisplayCursor);
  411. unwrap(vncHooksScreen, pScreen, BlockHandler);
  412. #ifdef RENDER
  413. ps = GetPictureScreenIfSet(pScreen);
  414. if (ps) {
  415. unwrap(vncHooksScreen, ps, Composite);
  416. unwrap(vncHooksScreen, ps, Glyphs);
  417. unwrap(vncHooksScreen, ps, CompositeRects);
  418. unwrap(vncHooksScreen, ps, Trapezoids);
  419. unwrap(vncHooksScreen, ps, Triangles);
  420. #if PICTURE_SCREEN_VERSION >= 2
  421. unwrap(vncHooksScreen, ps, TriStrip);
  422. unwrap(vncHooksScreen, ps, TriFan);
  423. #endif
  424. }
  425. #endif
  426. rp = rrGetScrPriv(pScreen);
  427. if (rp) {
  428. unwrap(vncHooksScreen, rp, rrSetConfig);
  429. unwrap(vncHooksScreen, rp, rrScreenSetSize);
  430. unwrap(vncHooksScreen, rp, rrCrtcSet);
  431. }
  432. DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
  433. #if XORG <= 112
  434. return (*pScreen->CloseScreen)(i, pScreen);
  435. #else
  436. return (*pScreen->CloseScreen)(pScreen);
  437. #endif
  438. }
  439. // CreateGC - wrap the "GC funcs"
  440. static Bool vncHooksCreateGC(GCPtr pGC)
  441. {
  442. vncHooksGCPtr vncHooksGC = vncHooksGCPrivate(pGC);
  443. Bool ret;
  444. SCREEN_PROLOGUE(pGC->pScreen, CreateGC);
  445. ret = (*pScreen->CreateGC) (pGC);
  446. vncHooksGC->ops = NULL;
  447. vncHooksGC->funcs = pGC->funcs;
  448. pGC->funcs = &vncHooksGCFuncs;
  449. SCREEN_EPILOGUE(CreateGC);
  450. return ret;
  451. }
  452. // CopyWindow - destination of the copy is the old region, clipped by
  453. // borderClip, translated by the delta. This call only does the copy - it
  454. // doesn't affect any other bits.
  455. static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
  456. RegionPtr pOldRegion)
  457. {
  458. int dx, dy;
  459. BoxRec screen_box;
  460. RegionRec copied, screen_rgn;
  461. SCREEN_PROLOGUE(pWin->drawable.pScreen, CopyWindow);
  462. REGION_NULL(pScreen, &copied);
  463. REGION_COPY(pScreen, &copied, pOldRegion);
  464. screen_box.x1 = 0;
  465. screen_box.y1 = 0;
  466. screen_box.x2 = pScreen->width;
  467. screen_box.y2 = pScreen->height;
  468. REGION_INIT(pScreen, &screen_rgn, &screen_box, 1);
  469. dx = pWin->drawable.x - ptOldOrg.x;
  470. dy = pWin->drawable.y - ptOldOrg.y;
  471. // RFB tracks copies in terms of destination rectangle, not source.
  472. // We also need to copy with changes to the Window's clipping region.
  473. // Finally, make sure we don't get copies to or from regions outside
  474. // the framebuffer.
  475. REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn);
  476. REGION_TRANSLATE(pScreen, &copied, dx, dy);
  477. REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn);
  478. REGION_INTERSECT(pScreen, &copied, &copied, &pWin->borderClip);
  479. (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
  480. if (REGION_NOTEMPTY(pScreen, &copied))
  481. add_copied(pScreen, &copied, dx, dy);
  482. REGION_UNINIT(pScreen, &copied);
  483. REGION_UNINIT(pScreen, &screen_rgn);
  484. SCREEN_EPILOGUE(CopyWindow);
  485. }
  486. // ClearToBackground - changed region is the given rectangle, clipped by
  487. // clipList, but only if generateExposures is false.
  488. static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
  489. int h, Bool generateExposures)
  490. {
  491. BoxRec box;
  492. RegionRec reg;
  493. SCREEN_PROLOGUE(pWin->drawable.pScreen, ClearToBackground);
  494. box.x1 = x + pWin->drawable.x;
  495. box.y1 = y + pWin->drawable.y;
  496. box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
  497. box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
  498. REGION_INIT(pScreen, &reg, &box, 0);
  499. REGION_INTERSECT(pScreen, &reg, &reg, &pWin->clipList);
  500. (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
  501. if (!generateExposures) {
  502. add_changed(pScreen, &reg);
  503. }
  504. REGION_UNINIT(pScreen, &reg);
  505. SCREEN_EPILOGUE(ClearToBackground);
  506. }
  507. #if XORG < 110
  508. // RestoreAreas - changed region is the given region
  509. static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
  510. {
  511. RegionRec reg;
  512. SCREEN_PROLOGUE(pWin->drawable.pScreen, RestoreAreas);
  513. REGION_NULL(pScreen, &reg);
  514. REGION_COPY(pScreen, &reg, pRegion);
  515. RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
  516. add_changed(pScreen, &reg);
  517. REGION_UNINIT(pScreen, &reg);
  518. SCREEN_EPILOGUE(RestoreAreas);
  519. return result;
  520. }
  521. #endif
  522. // DisplayCursor - get the cursor shape
  523. static Bool vncHooksDisplayCursor(DeviceIntPtr pDev,
  524. ScreenPtr pScreen_, CursorPtr cursor)
  525. {
  526. Bool ret;
  527. SCREEN_PROLOGUE(pScreen_, DisplayCursor);
  528. ret = (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
  529. /*
  530. * XXX DIX calls this function with NULL argument to remove cursor sprite from
  531. * screen. Should we handle this in setCursor as well?
  532. */
  533. if (cursor != NullCursor) {
  534. int width, height;
  535. int hotX, hotY;
  536. unsigned char *rgbaData;
  537. width = cursor->bits->width;
  538. height = cursor->bits->height;
  539. hotX = cursor->bits->xhot;
  540. hotY = cursor->bits->yhot;
  541. rgbaData = malloc(width * height * 4);
  542. if (rgbaData == NULL)
  543. goto out;
  544. #ifdef ARGB_CURSOR
  545. if (cursor->bits->argb) {
  546. unsigned char *out;
  547. CARD32 *in;
  548. int i;
  549. in = cursor->bits->argb;
  550. out = rgbaData;
  551. for (i = 0; i < width*height; i++) {
  552. out[0] = (*in >> 16) & 0xff;
  553. out[1] = (*in >> 8) & 0xff;
  554. out[2] = (*in >> 0) & 0xff;
  555. out[3] = (*in >> 24) & 0xff;
  556. out += 4;
  557. in++;
  558. }
  559. } else {
  560. #endif
  561. unsigned char *out;
  562. int xMaskBytesPerRow;
  563. xMaskBytesPerRow = BitmapBytePad(width);
  564. out = rgbaData;
  565. for (int y = 0; y < height; y++) {
  566. for (int x = 0; x < width; x++) {
  567. int byte = y * xMaskBytesPerRow + x / 8;
  568. #if (BITMAP_BIT_ORDER == MSBFirst)
  569. int bit = 7 - x % 8;
  570. #else
  571. int bit = x % 8;
  572. #endif
  573. if (cursor->bits->source[byte] & (1 << bit)) {
  574. out[0] = cursor->foreRed;
  575. out[1] = cursor->foreGreen;
  576. out[2] = cursor->foreBlue;
  577. } else {
  578. out[0] = cursor->backRed;
  579. out[1] = cursor->backGreen;
  580. out[2] = cursor->backBlue;
  581. }
  582. if (cursor->bits->mask[byte] & (1 << bit))
  583. out[3] = 0xff;
  584. else
  585. out[3] = 0x00;
  586. out += 4;
  587. }
  588. }
  589. #ifdef ARGB_CURSOR
  590. }
  591. #endif
  592. vncSetCursor(width, height, hotX, hotY, rgbaData);
  593. free(rgbaData);
  594. }
  595. out:
  596. SCREEN_EPILOGUE(DisplayCursor);
  597. return ret;
  598. }
  599. // BlockHandler - ignore any changes during the block handler - it's likely
  600. // these are just drawing the cursor.
  601. #if XORG <= 112
  602. static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
  603. pointer pReadmask)
  604. #elif XORG <= 118
  605. static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout,
  606. void * pReadmask)
  607. #else
  608. static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout)
  609. #endif
  610. {
  611. #if XORG <= 112
  612. SCREEN_PROLOGUE(screenInfo.screens[i], BlockHandler);
  613. #else
  614. SCREEN_PROLOGUE(pScreen_, BlockHandler);
  615. #endif
  616. vncHooksScreen->ignoreHooks++;
  617. #if XORG <= 112
  618. (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
  619. #elif XORG <= 118
  620. (*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask);
  621. #else
  622. (*pScreen->BlockHandler) (pScreen, pTimeout);
  623. #endif
  624. vncHooksScreen->ignoreHooks--;
  625. SCREEN_EPILOGUE(BlockHandler);
  626. }
  627. #ifdef RENDER
  628. // Unwrap and rewrap helpers
  629. #define RENDER_PROLOGUE(scrn,field) \
  630. ScreenPtr pScreen = scrn; \
  631. PictureScreenPtr ps = GetPictureScreen(pScreen); \
  632. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
  633. unwrap(vncHooksScreen, ps, field); \
  634. DBGPRINT((stderr,"vncHooks" #field " called\n"));
  635. #define RENDER_EPILOGUE(field) \
  636. wrap(vncHooksScreen, ps, field, vncHooks##field); \
  637. // Composite - The core of XRENDER
  638. static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
  639. PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
  640. INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
  641. {
  642. RegionRec changed;
  643. RENDER_PROLOGUE(pDst->pDrawable->pScreen, Composite);
  644. if (is_visible(pDst->pDrawable)) {
  645. BoxRec box;
  646. RegionRec fbreg;
  647. box.x1 = max(pDst->pDrawable->x + xDst, 0);
  648. box.y1 = max(pDst->pDrawable->y + yDst, 0);
  649. box.x2 = box.x1 + width;
  650. box.y2 = box.y1 + height;
  651. REGION_INIT(pScreen, &changed, &box, 0);
  652. box.x1 = 0;
  653. box.y1 = 0;
  654. box.x2 = pScreen->width;
  655. box.y2 = pScreen->height;
  656. REGION_INIT(pScreen, &fbreg, &box, 0);
  657. REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
  658. REGION_UNINIT(pScreen, &fbreg);
  659. } else {
  660. REGION_NULL(pScreen, &changed);
  661. }
  662. (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
  663. xMask, yMask, xDst, yDst, width, height);
  664. if (REGION_NOTEMPTY(pScreen, &changed))
  665. add_changed(pScreen, &changed);
  666. REGION_UNINIT(pScreen, &changed);
  667. RENDER_EPILOGUE(Composite);
  668. }
  669. static RegionPtr
  670. GlyphsToRegion(ScreenPtr pScreen, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
  671. {
  672. int n;
  673. GlyphPtr glyph;
  674. int x, y;
  675. int nrects = nlist;
  676. xRectangle rects[nrects];
  677. xRectanglePtr rect;
  678. x = 0;
  679. y = 0;
  680. rect = &rects[0];
  681. while (nlist--) {
  682. int left, right, top, bottom;
  683. x += list->xOff;
  684. y += list->yOff;
  685. n = list->len;
  686. list++;
  687. left = INT_MAX;
  688. top = INT_MAX;
  689. right = -INT_MAX;
  690. bottom = -INT_MAX;
  691. while (n--) {
  692. int gx, gy, gw, gh;
  693. glyph = *glyphs++;
  694. gx = x - glyph->info.x;
  695. gy = y - glyph->info.y;
  696. gw = glyph->info.width;
  697. gh = glyph->info.height;
  698. x += glyph->info.xOff;
  699. y += glyph->info.yOff;
  700. if (gx < left)
  701. left = gx;
  702. if (gy < top)
  703. top = gy;
  704. if (gx + gw > right)
  705. right = gx + gw;
  706. if (gy + gh > bottom)
  707. bottom = gy + gh;
  708. }
  709. rect->x = left;
  710. rect->y = top;
  711. if ((right > left) && (bottom > top)) {
  712. rect->width = right - left;
  713. rect->height = bottom - top;
  714. } else {
  715. rect->width = 0;
  716. rect->height = 0;
  717. }
  718. rect++;
  719. }
  720. return RECTS_TO_REGION(pScreen, nrects, rects, CT_NONE);
  721. }
  722. // Glyphs - Glyph specific version of Composite (caches and whatnot)
  723. static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  724. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
  725. GlyphListPtr lists, GlyphPtr * glyphs)
  726. {
  727. RegionPtr changed;
  728. RENDER_PROLOGUE(pDst->pDrawable->pScreen, Glyphs);
  729. if (is_visible(pDst->pDrawable)) {
  730. BoxRec fbbox;
  731. RegionRec fbreg;
  732. changed = GlyphsToRegion(pScreen, nlists, lists, glyphs);
  733. REGION_TRANSLATE(pScreen, changed,
  734. pDst->pDrawable->x, pDst->pDrawable->y);
  735. fbbox.x1 = 0;
  736. fbbox.y1 = 0;
  737. fbbox.x2 = pScreen->width;
  738. fbbox.y2 = pScreen->height;
  739. REGION_INIT(pScreen, &fbreg, &fbbox, 0);
  740. REGION_INTERSECT(pScreen, changed, changed, &fbreg);
  741. REGION_UNINIT(pScreen, &fbreg);
  742. } else {
  743. changed = REGION_CREATE(pScreen, NullBox, 0);
  744. }
  745. (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs);
  746. if (REGION_NOTEMPTY(pScreen, changed))
  747. add_changed(pScreen, changed);
  748. REGION_DESTROY(pScreen, changed);
  749. RENDER_EPILOGUE(Glyphs);
  750. }
  751. static void vncHooksCompositeRects(CARD8 op, PicturePtr pDst,
  752. xRenderColor * color, int nRect, xRectangle *rects)
  753. {
  754. RegionPtr changed;
  755. RENDER_PROLOGUE(pDst->pDrawable->pScreen, CompositeRects);
  756. if (is_visible(pDst->pDrawable)) {
  757. changed = RECTS_TO_REGION(pScreen, nRect, rects, CT_NONE);
  758. } else {
  759. changed = REGION_CREATE(pScreen, NullBox, 0);
  760. }
  761. (*ps->CompositeRects)(op, pDst, color, nRect, rects);
  762. if (REGION_NOTEMPTY(pScreen, changed))
  763. add_changed(pScreen, changed);
  764. REGION_DESTROY(pScreen, changed);
  765. RENDER_EPILOGUE(CompositeRects);
  766. }
  767. static inline short FixedToShort(xFixed fixed)
  768. {
  769. return (fixed + 0x8000) >> 16;
  770. }
  771. static void vncHooksTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  772. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  773. int ntrap, xTrapezoid * traps)
  774. {
  775. RegionRec changed;
  776. RENDER_PROLOGUE(pDst->pDrawable->pScreen, Trapezoids);
  777. if (is_visible(pDst->pDrawable)) {
  778. BoxRec box;
  779. RegionRec fbreg;
  780. // FIXME: We do a very crude bounding box around everything.
  781. // Might not be worth optimizing since this call is rarely
  782. // used.
  783. box.x1 = SHRT_MAX;
  784. box.y1 = SHRT_MAX;
  785. box.x2 = 0;
  786. box.y2 = 0;
  787. for (int i = 0;i < ntrap;i++) {
  788. if (FixedToShort(traps[i].left.p1.x) < box.x1)
  789. box.x1 = FixedToShort(traps[i].left.p1.x);
  790. if (FixedToShort(traps[i].left.p2.x) < box.x1)
  791. box.x1 = FixedToShort(traps[i].left.p2.x);
  792. if (FixedToShort(traps[i].top) < box.y1)
  793. box.y1 = FixedToShort(traps[i].top);
  794. if (FixedToShort(traps[i].right.p1.x) > box.x2)
  795. box.x2 = FixedToShort(traps[i].right.p1.x);
  796. if (FixedToShort(traps[i].right.p2.x) > box.x2)
  797. box.x2 = FixedToShort(traps[i].right.p2.x);
  798. if (FixedToShort(traps[i].bottom) > box.y2)
  799. box.y2 = FixedToShort(traps[i].bottom);
  800. }
  801. box.x1 += pDst->pDrawable->x;
  802. box.y1 += pDst->pDrawable->y;
  803. box.x2 += pDst->pDrawable->x;
  804. box.y2 += pDst->pDrawable->y;
  805. REGION_INIT(pScreen, &changed, &box, 0);
  806. box.x1 = 0;
  807. box.y1 = 0;
  808. box.x2 = pScreen->width;
  809. box.y2 = pScreen->height;
  810. REGION_INIT(pScreen, &fbreg, &box, 0);
  811. REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
  812. REGION_UNINIT(pScreen, &fbreg);
  813. } else {
  814. REGION_NULL(pScreen, &changed);
  815. }
  816. (*ps->Trapezoids)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
  817. if (REGION_NOTEMPTY(pScreen, &changed))
  818. add_changed(pScreen, &changed);
  819. REGION_UNINIT(pScreen, &changed);
  820. RENDER_EPILOGUE(Trapezoids);
  821. }
  822. static void vncHooksTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  823. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  824. int ntri, xTriangle * tris)
  825. {
  826. RegionRec changed;
  827. RENDER_PROLOGUE(pDst->pDrawable->pScreen, Triangles);
  828. if (is_visible(pDst->pDrawable)) {
  829. BoxRec box;
  830. RegionRec fbreg;
  831. // FIXME: We do a very crude bounding box around everything.
  832. // Might not be worth optimizing since this call is rarely
  833. // used.
  834. box.x1 = SHRT_MAX;
  835. box.y1 = SHRT_MAX;
  836. box.x2 = 0;
  837. box.y2 = 0;
  838. for (int i = 0;i < ntri;i++) {
  839. xFixed left, right, top, bottom;
  840. left = min(min(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);
  841. right = max(max(tris[i].p1.x, tris[i].p2.x), tris[i].p3.x);
  842. top = min(min(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);
  843. bottom = max(max(tris[i].p1.y, tris[i].p2.y), tris[i].p3.y);
  844. if (FixedToShort(left) < box.x1)
  845. box.x1 = FixedToShort(left);
  846. if (FixedToShort(top) < box.y1)
  847. box.y1 = FixedToShort(top);
  848. if (FixedToShort(right) > box.x2)
  849. box.x2 = FixedToShort(right);
  850. if (FixedToShort(bottom) > box.y2)
  851. box.y2 = FixedToShort(bottom);
  852. }
  853. box.x1 += pDst->pDrawable->x;
  854. box.y1 += pDst->pDrawable->y;
  855. box.x2 += pDst->pDrawable->x;
  856. box.y2 += pDst->pDrawable->y;
  857. REGION_INIT(pScreen, &changed, &box, 0);
  858. box.x1 = 0;
  859. box.y1 = 0;
  860. box.x2 = pScreen->width;
  861. box.y2 = pScreen->height;
  862. REGION_INIT(pScreen, &fbreg, &box, 0);
  863. REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
  864. REGION_UNINIT(pScreen, &fbreg);
  865. } else {
  866. REGION_NULL(pScreen, &changed);
  867. }
  868. (*ps->Triangles)(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
  869. if (REGION_NOTEMPTY(pScreen, &changed))
  870. add_changed(pScreen, &changed);
  871. REGION_UNINIT(pScreen, &changed);
  872. RENDER_EPILOGUE(Triangles);
  873. }
  874. #if PICTURE_SCREEN_VERSION >= 2
  875. static void vncHooksTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  876. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  877. int npoint, xPointFixed * points)
  878. {
  879. RegionRec changed;
  880. RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriStrip);
  881. if (is_visible(pDst->pDrawable)) {
  882. BoxRec box;
  883. RegionRec fbreg;
  884. // FIXME: We do a very crude bounding box around everything.
  885. // Might not be worth optimizing since this call is rarely
  886. // used.
  887. box.x1 = SHRT_MAX;
  888. box.y1 = SHRT_MAX;
  889. box.x2 = 0;
  890. box.y2 = 0;
  891. for (int i = 0;i < npoint;i++) {
  892. if (FixedToShort(points[i].x) < box.x1)
  893. box.x1 = FixedToShort(points[i].x);
  894. if (FixedToShort(points[i].y) < box.y1)
  895. box.y1 = FixedToShort(points[i].y);
  896. if (FixedToShort(points[i].x) > box.x2)
  897. box.x2 = FixedToShort(points[i].x);
  898. if (FixedToShort(points[i].y) > box.y2)
  899. box.y2 = FixedToShort(points[i].y);
  900. }
  901. box.x1 += pDst->pDrawable->x;
  902. box.y1 += pDst->pDrawable->y;
  903. box.x2 += pDst->pDrawable->x;
  904. box.y2 += pDst->pDrawable->y;
  905. REGION_INIT(pScreen, &changed, &box, 0);
  906. box.x1 = 0;
  907. box.y1 = 0;
  908. box.x2 = pScreen->width;
  909. box.y2 = pScreen->height;
  910. REGION_INIT(pScreen, &fbreg, &box, 0);
  911. REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
  912. REGION_UNINIT(pScreen, &fbreg);
  913. } else {
  914. REGION_NULL(pScreen, &changed);
  915. }
  916. (*ps->TriStrip)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);
  917. if (REGION_NOTEMPTY(pScreen, &changed))
  918. add_changed(pScreen, &changed);
  919. REGION_UNINIT(pScreen, &changed);
  920. RENDER_EPILOGUE(TriStrip);
  921. }
  922. static void vncHooksTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
  923. PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
  924. int npoint, xPointFixed * points)
  925. {
  926. RegionRec changed;
  927. RENDER_PROLOGUE(pDst->pDrawable->pScreen, TriFan);
  928. if (is_visible(pDst->pDrawable)) {
  929. BoxRec box;
  930. RegionRec fbreg;
  931. // FIXME: We do a very crude bounding box around everything.
  932. // Might not be worth optimizing since this call is rarely
  933. // used.
  934. box.x1 = SHRT_MAX;
  935. box.y1 = SHRT_MAX;
  936. box.x2 = 0;
  937. box.y2 = 0;
  938. for (int i = 0;i < npoint;i++) {
  939. if (FixedToShort(points[i].x) < box.x1)
  940. box.x1 = FixedToShort(points[i].x);
  941. if (FixedToShort(points[i].y) < box.y1)
  942. box.y1 = FixedToShort(points[i].y);
  943. if (FixedToShort(points[i].x) > box.x2)
  944. box.x2 = FixedToShort(points[i].x);
  945. if (FixedToShort(points[i].y) > box.y2)
  946. box.y2 = FixedToShort(points[i].y);
  947. }
  948. box.x1 += pDst->pDrawable->x;
  949. box.y1 += pDst->pDrawable->y;
  950. box.x2 += pDst->pDrawable->x;
  951. box.y2 += pDst->pDrawable->y;
  952. REGION_INIT(pScreen, &changed, &box, 0);
  953. box.x1 = 0;
  954. box.y1 = 0;
  955. box.x2 = pScreen->width;
  956. box.y2 = pScreen->height;
  957. REGION_INIT(pScreen, &fbreg, &box, 0);
  958. REGION_INTERSECT(pScreen, &changed, &changed, &fbreg);
  959. REGION_UNINIT(pScreen, &fbreg);
  960. } else {
  961. REGION_NULL(pScreen, &changed);
  962. }
  963. (*ps->TriFan)(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, points);
  964. if (REGION_NOTEMPTY(pScreen, &changed))
  965. add_changed(pScreen, &changed);
  966. REGION_UNINIT(pScreen, &changed);
  967. RENDER_EPILOGUE(TriFan);
  968. }
  969. #endif /* PICTURE_SCREEN_VERSION */
  970. #endif /* RENDER */
  971. // Unwrap and rewrap helpers
  972. #define RANDR_PROLOGUE(field) \
  973. rrScrPrivPtr rp = rrGetScrPriv(pScreen); \
  974. vncHooksScreenPtr vncHooksScreen = vncHooksScreenPrivate(pScreen); \
  975. unwrap(vncHooksScreen, rp, rr##field); \
  976. DBGPRINT((stderr,"vncHooksRandR" #field " called\n"));
  977. #define RANDR_EPILOGUE(field) \
  978. wrap(vncHooksScreen, rp, rr##field, vncHooksRandR##field); \
  979. // RandRSetConfig - follow any framebuffer changes
  980. static Bool vncHooksRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
  981. int rate, RRScreenSizePtr pSize)
  982. {
  983. Bool ret;
  984. RANDR_PROLOGUE(SetConfig);
  985. vncPreScreenResize(pScreen->myNum);
  986. ret = (*rp->rrSetConfig)(pScreen, rotation, rate, pSize);
  987. vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);
  988. RANDR_EPILOGUE(SetConfig);
  989. if (!ret)
  990. return FALSE;
  991. return TRUE;
  992. }
  993. static Bool vncHooksRandRScreenSetSize(ScreenPtr pScreen,
  994. CARD16 width, CARD16 height,
  995. CARD32 mmWidth, CARD32 mmHeight)
  996. {
  997. Bool ret;
  998. RANDR_PROLOGUE(ScreenSetSize);
  999. vncPreScreenResize(pScreen->myNum);
  1000. ret = (*rp->rrScreenSetSize)(pScreen, width, height, mmWidth, mmHeight);
  1001. vncPostScreenResize(pScreen->myNum, ret, pScreen->width, pScreen->height);
  1002. RANDR_EPILOGUE(ScreenSetSize);
  1003. if (!ret)
  1004. return FALSE;
  1005. return TRUE;
  1006. }
  1007. static Bool vncHooksRandRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc,
  1008. RRModePtr mode, int x, int y,
  1009. Rotation rotation, int num_outputs,
  1010. RROutputPtr *outputs)
  1011. {
  1012. Bool ret;
  1013. RANDR_PROLOGUE(CrtcSet);
  1014. ret = (*rp->rrCrtcSet)(pScreen, crtc, mode, x, y, rotation,
  1015. num_outputs, outputs);
  1016. RANDR_EPILOGUE(CrtcSet);
  1017. if (!ret)
  1018. return FALSE;
  1019. vncRefreshScreenLayout(pScreen->myNum);
  1020. return TRUE;
  1021. }
  1022. /////////////////////////////////////////////////////////////////////////////
  1023. //
  1024. // GC "funcs"
  1025. //
  1026. // Unwrap and rewrap helpers
  1027. #define GC_FUNC_PROLOGUE(pGC, name)\
  1028. vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
  1029. unwrap(pGCPriv, pGC, funcs);\
  1030. if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)\
  1031. DBGPRINT((stderr,"vncHooks" #name " called\n"))
  1032. #define GC_FUNC_EPILOGUE(pGC)\
  1033. wrap(pGCPriv, pGC, funcs, &vncHooksGCFuncs);\
  1034. if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &vncHooksGCOps)
  1035. // ValidateGC - wrap the "ops" if the drawable is on screen
  1036. static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
  1037. DrawablePtr pDrawable)
  1038. {
  1039. GC_FUNC_PROLOGUE(pGC, ValidateGC);
  1040. (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
  1041. if (is_visible(pDrawable)) {
  1042. pGCPriv->ops = pGC->ops;
  1043. DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
  1044. } else {
  1045. pGCPriv->ops = NULL;
  1046. }
  1047. GC_FUNC_EPILOGUE(pGC);
  1048. }
  1049. // Other GC funcs - just unwrap and call on
  1050. static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
  1051. GC_FUNC_PROLOGUE(pGC, ChangeGC);
  1052. (*pGC->funcs->ChangeGC) (pGC, mask);
  1053. GC_FUNC_EPILOGUE(pGC);
  1054. }
  1055. static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
  1056. GC_FUNC_PROLOGUE(dst, CopyGC);
  1057. (*dst->funcs->CopyGC) (src, mask, dst);
  1058. GC_FUNC_EPILOGUE(dst);
  1059. }
  1060. static void vncHooksDestroyGC(GCPtr pGC) {
  1061. GC_FUNC_PROLOGUE(pGC, DestroyGC);
  1062. (*pGC->funcs->DestroyGC) (pGC);
  1063. GC_FUNC_EPILOGUE(pGC);
  1064. }
  1065. static void vncHooksChangeClip(GCPtr pGC, int type, void * pValue, int nrects)
  1066. {
  1067. GC_FUNC_PROLOGUE(pGC, ChangeClip);
  1068. (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
  1069. GC_FUNC_EPILOGUE(pGC);
  1070. }
  1071. static void vncHooksDestroyClip(GCPtr pGC) {
  1072. GC_FUNC_PROLOGUE(pGC, DestroyClip);
  1073. (*pGC->funcs->DestroyClip) (pGC);
  1074. GC_FUNC_EPILOGUE(pGC);
  1075. }
  1076. static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
  1077. GC_FUNC_PROLOGUE(dst, CopyClip);
  1078. (*dst->funcs->CopyClip) (dst, src);
  1079. GC_FUNC_EPILOGUE(dst);
  1080. }
  1081. /////////////////////////////////////////////////////////////////////////////
  1082. //
  1083. // GC "ops"
  1084. //
  1085. // Unwrap and rewrap helpers
  1086. #if XORG >= 116
  1087. #define GC_OP_PROLOGUE(pGC, name)\
  1088. vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
  1089. const GCFuncs *oldFuncs = pGC->funcs;\
  1090. unwrap(pGCPriv, pGC, funcs);\
  1091. unwrap(pGCPriv, pGC, ops);\
  1092. DBGPRINT((stderr,"vncHooks" #name " called\n"))
  1093. #else
  1094. #define GC_OP_PROLOGUE(pGC, name)\
  1095. vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\
  1096. GCFuncs *oldFuncs = pGC->funcs;\
  1097. unwrap(pGCPriv, pGC, funcs);\
  1098. unwrap(pGCPriv, pGC, ops);\
  1099. DBGPRINT((stderr,"vncHooks" #name " called\n"))
  1100. #endif
  1101. #define GC_OP_EPILOGUE(pGC)\
  1102. wrap(pGCPriv, pGC, funcs, oldFuncs); \
  1103. wrap(pGCPriv, pGC, ops, &vncHooksGCOps)
  1104. // FillSpans - assume the entire clip region is damaged. This is pessimistic,
  1105. // but I believe this function is rarely used so it doesn't matter.
  1106. static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
  1107. DDXPointPtr pptInit, int *pwidthInit,
  1108. int fSorted)
  1109. {
  1110. RegionRec reg;
  1111. GC_OP_PROLOGUE(pGC, FillSpans);
  1112. REGION_NULL(pGC->pScreen, &reg);
  1113. REGION_COPY(pGC->pScreen, &reg, pGC->pCompositeClip);
  1114. if (pDrawable->type == DRAWABLE_WINDOW)
  1115. REGION_INTERSECT(pScreen, &reg, &reg, &((WindowPtr)pDrawable)->borderClip);
  1116. (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
  1117. add_changed(pGC->pScreen, &reg);
  1118. REGION_UNINIT(pGC->pScreen, &reg);
  1119. GC_OP_EPILOGUE(pGC);
  1120. }
  1121. // SetSpans - assume the entire clip region is damaged. This is pessimistic,
  1122. // but I believe this function is rarely used so it doesn't matter.
  1123. static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
  1124. DDXPointPtr ppt, int *pwidth, int nspans,
  1125. int fSorted)
  1126. {
  1127. RegionRec reg;
  1128. GC_OP_PROLOGUE(pGC, SetSpans);
  1129. REGION_NULL(pGC->pScreen, &reg);
  1130. REGION_COPY(pGC->pScreen, &reg, pGC->pCompositeClip);
  1131. if (pDrawable->type == DRAWABLE_WINDOW)
  1132. REGION_INTERSECT(pScreen, &reg, &reg, &((WindowPtr)pDrawable)->borderClip);
  1133. (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
  1134. add_changed(pGC->pScreen, &reg);
  1135. REGION_UNINIT(pGC->pScreen, &reg);
  1136. GC_OP_EPILOGUE(pGC);
  1137. }
  1138. // PutImage - changed region is the given rectangle, clipped by pCompositeClip
  1139. static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
  1140. int x, int y, int w, int h, int leftPad,
  1141. int format, char *pBits)
  1142. {
  1143. BoxRec box;
  1144. RegionRec reg;
  1145. GC_OP_PROLOGUE(pGC, PutImage);
  1146. box.x1 = x + pDrawable->x;
  1147. box.y1 = y + pDrawable->y;
  1148. box.x2 = box.x1 + w;
  1149. box.y2 = box.y1 + h;
  1150. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1151. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1152. (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
  1153. pBits);
  1154. add_changed(pGC->pScreen, &reg);
  1155. REGION_UNINIT(pGC->pScreen, &reg);
  1156. GC_OP_EPILOGUE(pGC);
  1157. }
  1158. // CopyArea - destination of the copy is the dest rectangle, clipped by
  1159. // pCompositeClip. Any parts of the destination which cannot be copied from
  1160. // the source (could be all of it) go into the changed region.
  1161. static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
  1162. GCPtr pGC, int srcx, int srcy, int w, int h,
  1163. int dstx, int dsty)
  1164. {
  1165. RegionRec dst, src, changed;
  1166. RegionPtr ret;
  1167. GC_OP_PROLOGUE(pGC, CopyArea);
  1168. // Apparently this happens now and then...
  1169. if ((w == 0) || (h == 0))
  1170. REGION_NULL(pGC->pScreen, &dst);
  1171. else {
  1172. BoxRec box;
  1173. box.x1 = dstx + pDst->x;
  1174. box.y1 = dsty + pDst->y;
  1175. box.x2 = box.x1 + w;
  1176. box.y2 = box.y1 + h;
  1177. REGION_INIT(pGC->pScreen, &dst, &box, 0);
  1178. }
  1179. REGION_INTERSECT(pGC->pScreen, &dst, &dst, pGC->pCompositeClip);
  1180. // The source of the data has to be something that's on screen.
  1181. if (is_visible(pSrc)) {
  1182. BoxRec box;
  1183. box.x1 = srcx + pSrc->x;
  1184. box.y1 = srcy + pSrc->y;
  1185. box.x2 = box.x1 + w;
  1186. box.y2 = box.y1 + h;
  1187. REGION_INIT(pGC->pScreen, &src, &box, 0);
  1188. if ((pSrc->type == DRAWABLE_WINDOW) &&
  1189. REGION_NOTEMPTY(pScreen, &((WindowPtr)pSrc)->clipList)) {
  1190. REGION_INTERSECT(pScreen, &src, &src, &((WindowPtr)pSrc)->clipList);
  1191. }
  1192. REGION_TRANSLATE(pScreen, &src,
  1193. dstx + pDst->x - srcx - pSrc->x,
  1194. dsty + pDst->y - srcy - pSrc->y);
  1195. } else {
  1196. REGION_NULL(pGC->pScreen, &src);
  1197. }
  1198. REGION_NULL(pGC->pScreen, &changed);
  1199. REGION_SUBTRACT(pScreen, &changed, &dst, &src);
  1200. REGION_INTERSECT(pScreen, &dst, &dst, &src);
  1201. ret = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
  1202. if (REGION_NOTEMPTY(pScreen, &dst))
  1203. add_copied(pGC->pScreen, &dst,
  1204. dstx + pDst->x - srcx - pSrc->x,
  1205. dsty + pDst->y - srcy - pSrc->y);
  1206. if (REGION_NOTEMPTY(pScreen, &changed))
  1207. add_changed(pGC->pScreen, &changed);
  1208. REGION_UNINIT(pGC->pScreen, &dst);
  1209. REGION_UNINIT(pGC->pScreen, &src);
  1210. REGION_UNINIT(pGC->pScreen, &changed);
  1211. GC_OP_EPILOGUE(pGC);
  1212. return ret;
  1213. }
  1214. // CopyPlane - changed region is the destination rectangle, clipped by
  1215. // pCompositeClip
  1216. static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
  1217. GCPtr pGC, int srcx, int srcy, int w, int h,
  1218. int dstx, int dsty, unsigned long plane)
  1219. {
  1220. BoxRec box;
  1221. RegionRec reg;
  1222. RegionPtr ret;
  1223. GC_OP_PROLOGUE(pGC, CopyPlane);
  1224. box.x1 = dstx + pDst->x;
  1225. box.y1 = dsty + pDst->y;
  1226. box.x2 = box.x1 + w;
  1227. box.y2 = box.y1 + h;
  1228. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1229. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1230. ret = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
  1231. dstx, dsty, plane);
  1232. add_changed(pGC->pScreen, &reg);
  1233. REGION_UNINIT(pGC->pScreen, &reg);
  1234. GC_OP_EPILOGUE(pGC);
  1235. return ret;
  1236. }
  1237. // PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
  1238. static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
  1239. int npt, xPoint *pts)
  1240. {
  1241. int minX, minY, maxX, maxY;
  1242. int i;
  1243. BoxRec box;
  1244. RegionRec reg;
  1245. GC_OP_PROLOGUE(pGC, PolyPoint);
  1246. if (npt == 0) {
  1247. (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
  1248. goto out;
  1249. }
  1250. minX = pts[0].x;
  1251. maxX = pts[0].x;
  1252. minY = pts[0].y;
  1253. maxY = pts[0].y;
  1254. if (mode == CoordModePrevious) {
  1255. int x = pts[0].x;
  1256. int y = pts[0].y;
  1257. for (i = 1; i < npt; i++) {
  1258. x += pts[i].x;
  1259. y += pts[i].y;
  1260. if (x < minX) minX = x;
  1261. if (x > maxX) maxX = x;
  1262. if (y < minY) minY = y;
  1263. if (y > maxY) maxY = y;
  1264. }
  1265. } else {
  1266. for (i = 1; i < npt; i++) {
  1267. if (pts[i].x < minX) minX = pts[i].x;
  1268. if (pts[i].x > maxX) maxX = pts[i].x;
  1269. if (pts[i].y < minY) minY = pts[i].y;
  1270. if (pts[i].y > maxY) maxY = pts[i].y;
  1271. }
  1272. }
  1273. box.x1 = minX + pDrawable->x;
  1274. box.y1 = minY + pDrawable->y;
  1275. box.x2 = maxX + 1 + pDrawable->x;
  1276. box.y2 = maxY + 1 + pDrawable->y;
  1277. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1278. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1279. (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
  1280. add_changed(pGC->pScreen, &reg);
  1281. REGION_UNINIT(pGC->pScreen, &reg);
  1282. out:
  1283. GC_OP_EPILOGUE(pGC);
  1284. }
  1285. // Polylines - changed region is the union of the bounding rects of each line,
  1286. // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines,
  1287. // just use the bounding rect of all the lines.
  1288. static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
  1289. int npt, DDXPointPtr ppts)
  1290. {
  1291. int nRegRects;
  1292. xRectangle regRects[MAX_RECTS_PER_OP];
  1293. int lw;
  1294. RegionPtr reg;
  1295. GC_OP_PROLOGUE(pGC, Polylines);
  1296. if (npt == 0) {
  1297. (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
  1298. goto out;
  1299. }
  1300. nRegRects = npt - 1;
  1301. lw = pGC->lineWidth;
  1302. if (lw == 0)
  1303. lw = 1;
  1304. if (npt == 1)
  1305. {
  1306. // a single point
  1307. nRegRects = 1;
  1308. regRects[0].x = pDrawable->x + ppts[0].x - lw;
  1309. regRects[0].y = pDrawable->y + ppts[0].y - lw;
  1310. regRects[0].width = 2*lw;
  1311. regRects[0].height = 2*lw;
  1312. }
  1313. else
  1314. {
  1315. /*
  1316. * mitered joins can project quite a way from
  1317. * the line end; the 11 degree miter limit limits
  1318. * this extension to lw / (2 * tan(11/2)), rounded up
  1319. * and converted to int yields 6 * lw
  1320. */
  1321. int extra;
  1322. int prevX, prevY, curX, curY;
  1323. int rectX1, rectY1, rectX2, rectY2;
  1324. int minX, minY, maxX, maxY;
  1325. int i;
  1326. extra = lw / 2;
  1327. if (pGC->joinStyle == JoinMiter) {
  1328. extra = 6 * lw;
  1329. }
  1330. prevX = ppts[0].x + pDrawable->x;
  1331. prevY = ppts[0].y + pDrawable->y;
  1332. minX = maxX = prevX;
  1333. minY = maxY = prevY;
  1334. for (i = 0; i < nRegRects; i++) {
  1335. if (mode == CoordModeOrigin) {
  1336. curX = pDrawable->x + ppts[i+1].x;
  1337. curY = pDrawable->y + ppts[i+1].y;
  1338. } else {
  1339. curX = prevX + ppts[i+1].x;
  1340. curY = prevY + ppts[i+1].y;
  1341. }
  1342. if (prevX > curX) {
  1343. rectX1 = curX - extra;
  1344. rectX2 = prevX + extra + 1;
  1345. } else {
  1346. rectX1 = prevX - extra;
  1347. rectX2 = curX + extra + 1;
  1348. }
  1349. if (prevY > curY) {
  1350. rectY1 = curY - extra;
  1351. rectY2 = prevY + extra + 1;
  1352. } else {
  1353. rectY1 = prevY - extra;
  1354. rectY2 = curY + extra + 1;
  1355. }
  1356. if (nRegRects <= MAX_RECTS_PER_OP) {
  1357. regRects[i].x = rectX1;
  1358. regRects[i].y = rectY1;
  1359. regRects[i].width = rectX2 - rectX1;
  1360. regRects[i].height = rectY2 - rectY1;
  1361. } else {
  1362. if (rectX1 < minX) minX = rectX1;
  1363. if (rectY1 < minY) minY = rectY1;
  1364. if (rectX2 > maxX) maxX = rectX2;
  1365. if (rectY2 > maxY) maxY = rectY2;
  1366. }
  1367. prevX = curX;
  1368. prevY = curY;
  1369. }
  1370. if (nRegRects > MAX_RECTS_PER_OP) {
  1371. regRects[0].x = minX;
  1372. regRects[0].y = minY;
  1373. regRects[0].width = maxX - minX;
  1374. regRects[0].height = maxY - minY;
  1375. nRegRects = 1;
  1376. }
  1377. }
  1378. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1379. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1380. (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
  1381. add_changed(pGC->pScreen, reg);
  1382. REGION_DESTROY(pGC->pScreen, reg);
  1383. out:
  1384. GC_OP_EPILOGUE(pGC);
  1385. }
  1386. // PolySegment - changed region is the union of the bounding rects of each
  1387. // segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
  1388. // segments, just use the bounding rect of all the segments.
  1389. static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
  1390. xSegment *segs)
  1391. {
  1392. xRectangle regRects[MAX_RECTS_PER_OP];
  1393. int nRegRects;
  1394. int lw, extra;
  1395. int rectX1, rectY1, rectX2, rectY2;
  1396. int minX, minY, maxX, maxY;
  1397. int i;
  1398. RegionPtr reg;
  1399. GC_OP_PROLOGUE(pGC, PolySegment);
  1400. if (nseg == 0) {
  1401. (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
  1402. goto out;
  1403. }
  1404. nRegRects = nseg;
  1405. lw = pGC->lineWidth;
  1406. extra = lw / 2;
  1407. minX = maxX = segs[0].x1;
  1408. minY = maxY = segs[0].y1;
  1409. for (i = 0; i < nseg; i++) {
  1410. if (segs[i].x1 > segs[i].x2) {
  1411. rectX1 = pDrawable->x + segs[i].x2 - extra;
  1412. rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
  1413. } else {
  1414. rectX1 = pDrawable->x + segs[i].x1 - extra;
  1415. rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
  1416. }
  1417. if (segs[i].y1 > segs[i].y2) {
  1418. rectY1 = pDrawable->y + segs[i].y2 - extra;
  1419. rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
  1420. } else {
  1421. rectY1 = pDrawable->y + segs[i].y1 - extra;
  1422. rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
  1423. }
  1424. if (nseg <= MAX_RECTS_PER_OP) {
  1425. regRects[i].x = rectX1;
  1426. regRects[i].y = rectY1;
  1427. regRects[i].width = rectX2 - rectX1;
  1428. regRects[i].height = rectY2 - rectY1;
  1429. } else {
  1430. if (rectX1 < minX) minX = rectX1;
  1431. if (rectY1 < minY) minY = rectY1;
  1432. if (rectX2 > maxX) maxX = rectX2;
  1433. if (rectY2 > maxY) maxY = rectY2;
  1434. }
  1435. }
  1436. if (nseg > MAX_RECTS_PER_OP) {
  1437. regRects[0].x = minX;
  1438. regRects[0].y = minY;
  1439. regRects[0].width = maxX - minX;
  1440. regRects[0].height = maxY - minY;
  1441. nRegRects = 1;
  1442. }
  1443. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1444. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1445. (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
  1446. add_changed(pGC->pScreen, reg);
  1447. REGION_DESTROY(pGC->pScreen, reg);
  1448. out:
  1449. GC_OP_EPILOGUE(pGC);
  1450. }
  1451. // PolyRectangle - changed region is the union of the bounding rects around
  1452. // each side of the outline rectangles, clipped by pCompositeClip. If there
  1453. // are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
  1454. // the rectangles.
  1455. static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
  1456. xRectangle *rects)
  1457. {
  1458. xRectangle regRects[MAX_RECTS_PER_OP*4];
  1459. int nRegRects;
  1460. int lw, extra;
  1461. int rectX1, rectY1, rectX2, rectY2;
  1462. int minX, minY, maxX, maxY;
  1463. int i;
  1464. RegionPtr reg;
  1465. GC_OP_PROLOGUE(pGC, PolyRectangle);
  1466. if (nrects == 0) {
  1467. (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
  1468. goto out;
  1469. }
  1470. nRegRects = nrects * 4;
  1471. lw = pGC->lineWidth;
  1472. extra = lw / 2;
  1473. minX = maxX = rects[0].x;
  1474. minY = maxY = rects[0].y;
  1475. for (i = 0; i < nrects; i++) {
  1476. if (nrects <= MAX_RECTS_PER_OP) {
  1477. regRects[i*4].x = rects[i].x - extra + pDrawable->x;
  1478. regRects[i*4].y = rects[i].y - extra + pDrawable->y;
  1479. regRects[i*4].width = rects[i].width + 1 + 2 * extra;
  1480. regRects[i*4].height = 1 + 2 * extra;
  1481. regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
  1482. regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
  1483. regRects[i*4+1].width = 1 + 2 * extra;
  1484. regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
  1485. regRects[i*4+2].x = rects[i].x + rects[i].width - extra + pDrawable->x;
  1486. regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
  1487. regRects[i*4+2].width = 1 + 2 * extra;
  1488. regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
  1489. regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
  1490. regRects[i*4+3].y = rects[i].y + rects[i].height - extra + pDrawable->y;
  1491. regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
  1492. regRects[i*4+3].height = 1 + 2 * extra;
  1493. } else {
  1494. rectX1 = pDrawable->x + rects[i].x - extra;
  1495. rectY1 = pDrawable->y + rects[i].y - extra;
  1496. rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
  1497. rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
  1498. if (rectX1 < minX) minX = rectX1;
  1499. if (rectY1 < minY) minY = rectY1;
  1500. if (rectX2 > maxX) maxX = rectX2;
  1501. if (rectY2 > maxY) maxY = rectY2;
  1502. }
  1503. }
  1504. if (nrects > MAX_RECTS_PER_OP) {
  1505. regRects[0].x = minX;
  1506. regRects[0].y = minY;
  1507. regRects[0].width = maxX - minX;
  1508. regRects[0].height = maxY - minY;
  1509. nRegRects = 1;
  1510. }
  1511. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1512. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1513. (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
  1514. add_changed(pGC->pScreen, reg);
  1515. REGION_DESTROY(pGC->pScreen, reg);
  1516. out:
  1517. GC_OP_EPILOGUE(pGC);
  1518. }
  1519. // PolyArc - changed region is the union of bounding rects around each arc,
  1520. // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
  1521. // arcs, just use the bounding rect of all the arcs.
  1522. static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
  1523. xArc *arcs)
  1524. {
  1525. xRectangle regRects[MAX_RECTS_PER_OP];
  1526. int nRegRects;
  1527. int lw, extra;
  1528. int rectX1, rectY1, rectX2, rectY2;
  1529. int minX, minY, maxX, maxY;
  1530. int i;
  1531. RegionPtr reg;
  1532. GC_OP_PROLOGUE(pGC, PolyArc);
  1533. if (narcs == 0) {
  1534. (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
  1535. goto out;
  1536. }
  1537. nRegRects = narcs;
  1538. lw = pGC->lineWidth;
  1539. if (lw == 0)
  1540. lw = 1;
  1541. extra = lw / 2;
  1542. minX = maxX = arcs[0].x;
  1543. minY = maxY = arcs[0].y;
  1544. for (i = 0; i < narcs; i++) {
  1545. if (narcs <= MAX_RECTS_PER_OP) {
  1546. regRects[i].x = arcs[i].x - extra + pDrawable->x;
  1547. regRects[i].y = arcs[i].y - extra + pDrawable->y;
  1548. regRects[i].width = arcs[i].width + lw;
  1549. regRects[i].height = arcs[i].height + lw;
  1550. } else {
  1551. rectX1 = pDrawable->x + arcs[i].x - extra;
  1552. rectY1 = pDrawable->y + arcs[i].y - extra;
  1553. rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
  1554. rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
  1555. if (rectX1 < minX) minX = rectX1;
  1556. if (rectY1 < minY) minY = rectY1;
  1557. if (rectX2 > maxX) maxX = rectX2;
  1558. if (rectY2 > maxY) maxY = rectY2;
  1559. }
  1560. }
  1561. if (narcs > MAX_RECTS_PER_OP) {
  1562. regRects[0].x = minX;
  1563. regRects[0].y = minY;
  1564. regRects[0].width = maxX - minX;
  1565. regRects[0].height = maxY - minY;
  1566. nRegRects = 1;
  1567. }
  1568. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1569. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1570. (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
  1571. add_changed(pGC->pScreen, reg);
  1572. REGION_DESTROY(pGC->pScreen, reg);
  1573. out:
  1574. GC_OP_EPILOGUE(pGC);
  1575. }
  1576. // FillPolygon - changed region is the bounding rect around the polygon,
  1577. // clipped by pCompositeClip
  1578. static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
  1579. int mode, int count, DDXPointPtr pts)
  1580. {
  1581. int minX, minY, maxX, maxY;
  1582. int i;
  1583. BoxRec box;
  1584. RegionRec reg;
  1585. GC_OP_PROLOGUE(pGC, FillPolygon);
  1586. if (count == 0) {
  1587. (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
  1588. goto out;
  1589. }
  1590. minX = pts[0].x;
  1591. maxX = pts[0].x;
  1592. minY = pts[0].y;
  1593. maxY = pts[0].y;
  1594. if (mode == CoordModePrevious) {
  1595. int x = pts[0].x;
  1596. int y = pts[0].y;
  1597. for (i = 1; i < count; i++) {
  1598. x += pts[i].x;
  1599. y += pts[i].y;
  1600. if (x < minX) minX = x;
  1601. if (x > maxX) maxX = x;
  1602. if (y < minY) minY = y;
  1603. if (y > maxY) maxY = y;
  1604. }
  1605. } else {
  1606. for (i = 1; i < count; i++) {
  1607. if (pts[i].x < minX) minX = pts[i].x;
  1608. if (pts[i].x > maxX) maxX = pts[i].x;
  1609. if (pts[i].y < minY) minY = pts[i].y;
  1610. if (pts[i].y > maxY) maxY = pts[i].y;
  1611. }
  1612. }
  1613. box.x1 = minX + pDrawable->x;
  1614. box.y1 = minY + pDrawable->y;
  1615. box.x2 = maxX + 1 + pDrawable->x;
  1616. box.y2 = maxY + 1 + pDrawable->y;
  1617. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1618. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1619. (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
  1620. add_changed(pGC->pScreen, &reg);
  1621. REGION_UNINIT(pGC->pScreen, &reg);
  1622. out:
  1623. GC_OP_EPILOGUE(pGC);
  1624. }
  1625. // PolyFillRect - changed region is the union of the rectangles, clipped by
  1626. // pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just
  1627. // use the bounding rect of all the rectangles.
  1628. static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
  1629. xRectangle *rects)
  1630. {
  1631. xRectangle regRects[MAX_RECTS_PER_OP];
  1632. int nRegRects;
  1633. int rectX1, rectY1, rectX2, rectY2;
  1634. int minX, minY, maxX, maxY;
  1635. int i;
  1636. RegionPtr reg;
  1637. GC_OP_PROLOGUE(pGC, PolyFillRect);
  1638. if (nrects == 0) {
  1639. (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
  1640. goto out;
  1641. }
  1642. nRegRects = nrects;
  1643. minX = maxX = rects[0].x;
  1644. minY = maxY = rects[0].y;
  1645. for (i = 0; i < nrects; i++) {
  1646. if (nrects <= MAX_RECTS_PER_OP) {
  1647. regRects[i].x = rects[i].x + pDrawable->x;
  1648. regRects[i].y = rects[i].y + pDrawable->y;
  1649. regRects[i].width = rects[i].width;
  1650. regRects[i].height = rects[i].height;
  1651. } else {
  1652. rectX1 = pDrawable->x + rects[i].x;
  1653. rectY1 = pDrawable->y + rects[i].y;
  1654. rectX2 = pDrawable->x + rects[i].x + rects[i].width;
  1655. rectY2 = pDrawable->y + rects[i].y + rects[i].height;
  1656. if (rectX1 < minX) minX = rectX1;
  1657. if (rectY1 < minY) minY = rectY1;
  1658. if (rectX2 > maxX) maxX = rectX2;
  1659. if (rectY2 > maxY) maxY = rectY2;
  1660. }
  1661. }
  1662. if (nrects > MAX_RECTS_PER_OP) {
  1663. regRects[0].x = minX;
  1664. regRects[0].y = minY;
  1665. regRects[0].width = maxX - minX;
  1666. regRects[0].height = maxY - minY;
  1667. nRegRects = 1;
  1668. }
  1669. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1670. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1671. (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
  1672. add_changed(pGC->pScreen, reg);
  1673. REGION_DESTROY(pGC->pScreen, reg);
  1674. out:
  1675. GC_OP_EPILOGUE(pGC);
  1676. }
  1677. // PolyFillArc - changed region is the union of bounding rects around each arc,
  1678. // clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs,
  1679. // just use the bounding rect of all the arcs.
  1680. static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
  1681. xArc *arcs)
  1682. {
  1683. xRectangle regRects[MAX_RECTS_PER_OP];
  1684. int nRegRects;
  1685. int lw, extra;
  1686. int rectX1, rectY1, rectX2, rectY2;
  1687. int minX, minY, maxX, maxY;
  1688. int i;
  1689. RegionPtr reg;
  1690. GC_OP_PROLOGUE(pGC, PolyFillArc);
  1691. if (narcs == 0) {
  1692. (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
  1693. goto out;
  1694. }
  1695. nRegRects = narcs;
  1696. lw = pGC->lineWidth;
  1697. if (lw == 0)
  1698. lw = 1;
  1699. extra = lw / 2;
  1700. minX = maxX = arcs[0].x;
  1701. minY = maxY = arcs[0].y;
  1702. for (i = 0; i < narcs; i++) {
  1703. if (narcs <= MAX_RECTS_PER_OP) {
  1704. regRects[i].x = arcs[i].x - extra + pDrawable->x;
  1705. regRects[i].y = arcs[i].y - extra + pDrawable->y;
  1706. regRects[i].width = arcs[i].width + lw;
  1707. regRects[i].height = arcs[i].height + lw;
  1708. } else {
  1709. rectX1 = pDrawable->x + arcs[i].x - extra;
  1710. rectY1 = pDrawable->y + arcs[i].y - extra;
  1711. rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
  1712. rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
  1713. if (rectX1 < minX) minX = rectX1;
  1714. if (rectY1 < minY) minY = rectY1;
  1715. if (rectX2 > maxX) maxX = rectX2;
  1716. if (rectY2 > maxY) maxY = rectY2;
  1717. }
  1718. }
  1719. if (narcs > MAX_RECTS_PER_OP) {
  1720. regRects[0].x = minX;
  1721. regRects[0].y = minY;
  1722. regRects[0].width = maxX - minX;
  1723. regRects[0].height = maxY - minY;
  1724. nRegRects = 1;
  1725. }
  1726. reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE);
  1727. REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip);
  1728. (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
  1729. add_changed(pGC->pScreen, reg);
  1730. REGION_DESTROY(pGC->pScreen, reg);
  1731. out:
  1732. GC_OP_EPILOGUE(pGC);
  1733. }
  1734. // GetTextBoundingRect - calculate a bounding rectangle around n chars of a
  1735. // font. Not particularly accurate, but good enough.
  1736. static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
  1737. int y, int nchars, BoxPtr box)
  1738. {
  1739. int ascent = max(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
  1740. int descent = max(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
  1741. int charWidth = max(FONTMAXBOUNDS(font,rightSideBearing),
  1742. FONTMAXBOUNDS(font,characterWidth));
  1743. box->x1 = pDrawable->x + x;
  1744. box->y1 = pDrawable->y + y - ascent;
  1745. box->x2 = box->x1 + charWidth * nchars;
  1746. box->y2 = box->y1 + ascent + descent;
  1747. if (FONTMINBOUNDS(font,leftSideBearing) < 0)
  1748. box->x1 += FONTMINBOUNDS(font,leftSideBearing);
  1749. }
  1750. // PolyText8 - changed region is bounding rect around count chars, clipped by
  1751. // pCompositeClip
  1752. static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  1753. int count, char *chars)
  1754. {
  1755. int ret;
  1756. BoxRec box;
  1757. RegionRec reg;
  1758. GC_OP_PROLOGUE(pGC, PolyText8);
  1759. if (count == 0) {
  1760. ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
  1761. goto out;
  1762. }
  1763. GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
  1764. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1765. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1766. ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
  1767. add_changed(pGC->pScreen, &reg);
  1768. REGION_UNINIT(pGC->pScreen, &reg);
  1769. out:
  1770. GC_OP_EPILOGUE(pGC);
  1771. return ret;
  1772. }
  1773. // PolyText16 - changed region is bounding rect around count chars, clipped by
  1774. // pCompositeClip
  1775. static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  1776. int count, unsigned short *chars)
  1777. {
  1778. int ret;
  1779. BoxRec box;
  1780. RegionRec reg;
  1781. GC_OP_PROLOGUE(pGC, PolyText16);
  1782. if (count == 0) {
  1783. ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
  1784. goto out;
  1785. }
  1786. GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
  1787. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1788. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1789. ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
  1790. add_changed(pGC->pScreen, &reg);
  1791. REGION_UNINIT(pGC->pScreen, &reg);
  1792. out:
  1793. GC_OP_EPILOGUE(pGC);
  1794. return ret;
  1795. }
  1796. // ImageText8 - changed region is bounding rect around count chars, clipped by
  1797. // pCompositeClip
  1798. static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  1799. int count, char *chars)
  1800. {
  1801. BoxRec box;
  1802. RegionRec reg;
  1803. GC_OP_PROLOGUE(pGC, ImageText8);
  1804. if (count == 0) {
  1805. (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
  1806. goto out;
  1807. }
  1808. GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
  1809. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1810. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1811. (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
  1812. add_changed(pGC->pScreen, &reg);
  1813. REGION_UNINIT(pGC->pScreen, &reg);
  1814. out:
  1815. GC_OP_EPILOGUE(pGC);
  1816. }
  1817. // ImageText16 - changed region is bounding rect around count chars, clipped by
  1818. // pCompositeClip
  1819. static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
  1820. int count, unsigned short *chars)
  1821. {
  1822. BoxRec box;
  1823. RegionRec reg;
  1824. GC_OP_PROLOGUE(pGC, ImageText16);
  1825. if (count == 0) {
  1826. (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
  1827. goto out;
  1828. }
  1829. GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
  1830. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1831. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1832. (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
  1833. add_changed(pGC->pScreen, &reg);
  1834. REGION_UNINIT(pGC->pScreen, &reg);
  1835. out:
  1836. GC_OP_EPILOGUE(pGC);
  1837. }
  1838. // ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
  1839. // by pCompositeClip
  1840. static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
  1841. int y, unsigned int nglyph,
  1842. CharInfoPtr *ppci, void * pglyphBase)
  1843. {
  1844. BoxRec box;
  1845. RegionRec reg;
  1846. GC_OP_PROLOGUE(pGC, ImageGlyphBlt);
  1847. if (nglyph == 0) {
  1848. (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
  1849. goto out;
  1850. }
  1851. GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
  1852. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1853. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1854. (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1855. add_changed(pGC->pScreen, &reg);
  1856. REGION_UNINIT(pGC->pScreen, &reg);
  1857. out:
  1858. GC_OP_EPILOGUE(pGC);
  1859. }
  1860. // PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
  1861. // by pCompositeClip
  1862. static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
  1863. int y, unsigned int nglyph,
  1864. CharInfoPtr *ppci, void * pglyphBase)
  1865. {
  1866. BoxRec box;
  1867. RegionRec reg;
  1868. GC_OP_PROLOGUE(pGC, PolyGlyphBlt);
  1869. if (nglyph == 0) {
  1870. (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
  1871. goto out;
  1872. }
  1873. GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
  1874. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1875. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1876. (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
  1877. add_changed(pGC->pScreen, &reg);
  1878. REGION_UNINIT(pGC->pScreen, &reg);
  1879. out:
  1880. GC_OP_EPILOGUE(pGC);
  1881. }
  1882. // PushPixels - changed region is the given rectangle, clipped by
  1883. // pCompositeClip
  1884. static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
  1885. DrawablePtr pDrawable, int w, int h, int x,
  1886. int y)
  1887. {
  1888. BoxRec box;
  1889. RegionRec reg;
  1890. GC_OP_PROLOGUE(pGC, PushPixels);
  1891. box.x1 = x + pDrawable->x;
  1892. box.y1 = y + pDrawable->y;
  1893. box.x2 = box.x1 + w;
  1894. box.y2 = box.y1 + h;
  1895. REGION_INIT(pGC->pScreen, &reg, &box, 0);
  1896. REGION_INTERSECT(pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
  1897. (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
  1898. add_changed(pGC->pScreen, &reg);
  1899. REGION_UNINIT(pGC->pScreen, &reg);
  1900. GC_OP_EPILOGUE(pGC);
  1901. }