mibank.c 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456
  1. /*
  2. * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of Marc Aurele La France not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. Marc Aurele La France makes no representations
  11. * about the suitability of this software for any purpose. It is provided
  12. * "as-is" without express or implied warranty.
  13. *
  14. * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
  16. * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20. * PERFORMANCE OF THIS SOFTWARE.
  21. */
  22. /*
  23. * Copyright 1990,91,92,93 by Thomas Roell, Germany.
  24. * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
  25. *
  26. * Permission to use, copy, modify, distribute, and sell this software
  27. * and its documentation for any purpose is hereby granted without fee,
  28. * provided that the above copyright notice appear in all copies and
  29. * that both that copyright notice and this permission notice appear
  30. * in supporting documentation, and that the name of Thomas Roell nor
  31. * SGCS be used in advertising or publicity pertaining to distribution
  32. * of the software without specific, written prior permission.
  33. * Thomas Roell nor SGCS makes no representations about the suitability
  34. * of this software for any purpose. It is provided "as is" without
  35. * express or implied warranty.
  36. *
  37. * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  38. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  39. * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
  40. * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  41. * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  42. * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  43. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  44. */
  45. /*
  46. * This thing originated from an idea of Edwin Goei and his bank switching
  47. * code for the DEC TX board.
  48. */
  49. /*
  50. * Heavily modified for the XFree86 Project to turn this into an mi wrapper.
  51. * --- Marc Aurele La France (tsi@xfree86.org)
  52. */
  53. /*
  54. * "Heavily modified", indeed! By the time this is finalized, there probably
  55. * won't be much left of Roell's code...
  56. *
  57. * Miscellaneous notes:
  58. * - Pixels with imbedded bank boundaries are required to be off-screen. There
  59. * >might< be a way to fool the underlying framebuffer into dealing with
  60. * partial pixels.
  61. * - Plans to generalise this to do (hardware) colour plane switching have been
  62. * dropped due to colour flashing concerns.
  63. *
  64. * TODO:
  65. * - Allow miModifyBanking() to change BankSize and nBankDepth.
  66. * - Re-instate shared and double banking for framebuffers whose pixmap formats
  67. * don't describe how the server "sees" the screen.
  68. * - Remove remaining assumptions that a pixmap's devPrivate field points
  69. * directly to its pixel data.
  70. */
  71. /* #define NO_ALLOCA 1 */
  72. #ifdef HAVE_DIX_CONFIG_H
  73. #include <dix-config.h>
  74. #endif
  75. #include "servermd.h"
  76. #include "gcstruct.h"
  77. #include "pixmapstr.h"
  78. #include "scrnintstr.h"
  79. #include "windowstr.h"
  80. #include "mi.h"
  81. #include "mibank.h"
  82. #define BANK_SINGLE 0
  83. #define BANK_SHARED 1
  84. #define BANK_DOUBLE 2
  85. #define BANK_NOBANK 3
  86. typedef struct _miBankScreen
  87. {
  88. miBankInfoRec BankInfo;
  89. unsigned int nBankBPP;
  90. unsigned int type;
  91. unsigned long nBitsPerBank;
  92. unsigned long nBitsPerScanline;
  93. unsigned long nPixelsPerScanlinePadUnit;
  94. PixmapPtr pScreenPixmap;
  95. PixmapPtr pBankPixmap;
  96. GCPtr pBankGC;
  97. int nBanks, maxRects;
  98. RegionPtr *pBanks;
  99. pointer pbits;
  100. /*
  101. * Screen Wrappers
  102. */
  103. CreateScreenResourcesProcPtr CreateScreenResources;
  104. ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
  105. CloseScreenProcPtr CloseScreen;
  106. GetImageProcPtr GetImage;
  107. GetSpansProcPtr GetSpans;
  108. CreateGCProcPtr CreateGC;
  109. PaintWindowBackgroundProcPtr PaintWindowBackground;
  110. PaintWindowBorderProcPtr PaintWindowBorder;
  111. CopyWindowProcPtr CopyWindow;
  112. } miBankScreenRec, *miBankScreenPtr;
  113. typedef struct _miBankGC
  114. {
  115. GCOps *wrappedOps, *unwrappedOps;
  116. const GCFuncs *wrappedFuncs, *unwrappedFuncs;
  117. Bool fastCopy, fastPlane;
  118. RegionPtr pBankedClips[1];
  119. } miBankGCRec, *miBankGCPtr;
  120. typedef struct _miBankQueue
  121. {
  122. Bool fastBlit;
  123. unsigned short srcBankNo;
  124. unsigned short dstBankNo;
  125. short x;
  126. short y;
  127. short w;
  128. short h;
  129. } miBankQueue;
  130. /*
  131. * CAVEAT: This banking scheme requires that the DDX store Pixmap data in the
  132. * server's address space.
  133. */
  134. #define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
  135. (*pScreen->ModifyPixmapHeader)((_pPix), \
  136. (_width), -1, -1, -1, (_devKind), (_pbits))
  137. #define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \
  138. ModifyPixmap(_pPix, _width, _devKind, \
  139. (char *)pScreenPriv->BankInfo.pBankA + \
  140. (*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \
  141. (pScreenPriv->BankInfo.BankSize * (_no)))
  142. #define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \
  143. ModifyPixmap(_pPix, _width, _devKind, \
  144. (char *)pScreenPriv->BankInfo.pBankA + \
  145. (*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \
  146. (pScreenPriv->BankInfo.BankSize * (_no)))
  147. #define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \
  148. ModifyPixmap(_pPix, _width, _devKind, \
  149. (char *)pScreenPriv->BankInfo.pBankB + \
  150. (*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \
  151. (pScreenPriv->BankInfo.BankSize * (_no)))
  152. #define ALLOCATE_LOCAL_ARRAY(atype, ntype) \
  153. (atype *)ALLOCATE_LOCAL((ntype) * sizeof(atype))
  154. static int miBankScreenIndex;
  155. static int miBankGCIndex;
  156. static unsigned long miBankGeneration = 0;
  157. #define BANK_SCRPRIVLVAL pScreen->devPrivates[miBankScreenIndex].ptr
  158. #define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
  159. #define BANK_GCPRIVLVAL(pGC) (pGC)->devPrivates[miBankGCIndex].ptr
  160. #define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
  161. #define PIXMAP_STATUS(_pPix) \
  162. pointer pbits = (_pPix)->devPrivate.ptr
  163. #define PIXMAP_SAVE(_pPix) \
  164. PIXMAP_STATUS(_pPix); \
  165. if (pbits == (pointer)pScreenPriv) \
  166. (_pPix)->devPrivate.ptr = pScreenPriv->pbits
  167. #define PIXMAP_RESTORE(_pPix) \
  168. (_pPix)->devPrivate.ptr = pbits
  169. #define BANK_SAVE \
  170. int width = pScreenPriv->pBankPixmap->drawable.width; \
  171. int devKind = pScreenPriv->pBankPixmap->devKind; \
  172. PIXMAP_SAVE(pScreenPriv->pBankPixmap)
  173. #define BANK_RESTORE \
  174. pScreenPriv->pBankPixmap->drawable.width = width; \
  175. pScreenPriv->pBankPixmap->devKind = devKind; \
  176. PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
  177. #define SCREEN_STATUS \
  178. PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
  179. #define SCREEN_SAVE \
  180. PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
  181. #define SCREEN_RESTORE \
  182. PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
  183. #define SCREEN_INIT \
  184. miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
  185. #define SCREEN_UNWRAP(field) \
  186. pScreen->field = pScreenPriv->field
  187. #define SCREEN_WRAP(field, wrapper) \
  188. pScreenPriv->field = pScreen->field; \
  189. pScreen->field = wrapper
  190. #define GC_INIT(pGC) \
  191. miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
  192. #define GC_UNWRAP(pGC) \
  193. pGCPriv->unwrappedOps = (pGC)->ops; \
  194. pGCPriv->unwrappedFuncs = (pGC)->funcs; \
  195. (pGC)->ops = pGCPriv->wrappedOps; \
  196. (pGC)->funcs = pGCPriv->wrappedFuncs
  197. #define GC_WRAP(pGC) \
  198. pGCPriv->wrappedOps = (pGC)->ops; \
  199. pGCPriv->wrappedFuncs = (pGC)->funcs; \
  200. (pGC)->ops = pGCPriv->unwrappedOps; \
  201. (pGC)->funcs = pGCPriv->unwrappedFuncs
  202. #define IS_BANKED(pDrawable) \
  203. ((pbits == (pointer)pScreenPriv) && \
  204. (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
  205. #define CLIP_SAVE \
  206. RegionPtr pOrigCompositeClip = pGC->pCompositeClip
  207. #define CLIP_RESTORE \
  208. pGC->pCompositeClip = pOrigCompositeClip
  209. #define GCOP_INIT \
  210. ScreenPtr pScreen = pGC->pScreen; \
  211. SCREEN_INIT; \
  212. GC_INIT(pGC)
  213. #define GCOP_UNWRAP \
  214. GC_UNWRAP(pGC)
  215. #define GCOP_WRAP \
  216. GC_WRAP(pGC)
  217. #define GCOP_TOP_PART \
  218. for (i = 0; i < pScreenPriv->nBanks; i++) \
  219. { \
  220. if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
  221. continue; \
  222. GCOP_UNWRAP; \
  223. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
  224. #define GCOP_BOTTOM_PART \
  225. GCOP_WRAP; \
  226. }
  227. #define GCOP_SIMPLE(statement) \
  228. if (nArray > 0) \
  229. { \
  230. GCOP_INIT; \
  231. SCREEN_SAVE; \
  232. if (!IS_BANKED(pDrawable)) \
  233. { \
  234. GCOP_UNWRAP; \
  235. statement; \
  236. GCOP_WRAP; \
  237. } \
  238. else \
  239. { \
  240. int i; \
  241. CLIP_SAVE; \
  242. GCOP_TOP_PART; \
  243. statement; \
  244. GCOP_BOTTOM_PART; \
  245. CLIP_RESTORE; \
  246. } \
  247. SCREEN_RESTORE; \
  248. }
  249. #define GCOP_0D_ARGS mode,
  250. #define GCOP_1D_ARGS
  251. #define GCOP_2D_ARGS shape, mode,
  252. #define GCOP_COMPLEX(aop, atype) \
  253. if (nArray > 0) \
  254. { \
  255. GCOP_INIT; \
  256. SCREEN_SAVE; \
  257. if (!IS_BANKED(pDrawable)) \
  258. { \
  259. GCOP_UNWRAP; \
  260. (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
  261. GCOP_WRAP; \
  262. } \
  263. else \
  264. { \
  265. atype *aarg = pArray, *acopy; \
  266. int i; \
  267. CLIP_SAVE; \
  268. if ((acopy = ALLOCATE_LOCAL_ARRAY(atype, nArray))) \
  269. aarg = acopy; \
  270. GCOP_TOP_PART; \
  271. if (acopy) \
  272. memcpy(acopy, pArray, nArray * sizeof(atype)); \
  273. (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
  274. GCOP_BOTTOM_PART; \
  275. DEALLOCATE_LOCAL(acopy); \
  276. CLIP_RESTORE; \
  277. } \
  278. SCREEN_RESTORE; \
  279. }
  280. /*********************
  281. * Utility functions *
  282. *********************/
  283. static int
  284. miBankOf(
  285. miBankScreenPtr pScreenPriv,
  286. int x,
  287. int y
  288. )
  289. {
  290. int iBank = ((x * (int)pScreenPriv->nBankBPP) +
  291. (y * (long)pScreenPriv->nBitsPerScanline)) /
  292. (long)pScreenPriv->nBitsPerBank;
  293. if (iBank < 0)
  294. iBank = 0;
  295. else if (iBank >= pScreenPriv->nBanks)
  296. iBank = pScreenPriv->nBanks - 1;
  297. return iBank;
  298. }
  299. #define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
  300. #define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
  301. /* Determine banking type from the BankInfoRec */
  302. static unsigned int
  303. miBankDeriveType(
  304. ScreenPtr pScreen,
  305. miBankInfoPtr pBankInfo
  306. )
  307. {
  308. unsigned int type;
  309. if (pBankInfo->pBankA == pBankInfo->pBankB)
  310. {
  311. if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
  312. {
  313. if (pBankInfo->SetSourceAndDestinationBanks !=
  314. pBankInfo->SetSourceBank)
  315. return BANK_NOBANK;
  316. type = BANK_SINGLE;
  317. }
  318. else
  319. {
  320. if (pBankInfo->SetSourceAndDestinationBanks ==
  321. pBankInfo->SetDestinationBank)
  322. return BANK_NOBANK;
  323. if (pBankInfo->SetSourceAndDestinationBanks ==
  324. pBankInfo->SetSourceBank)
  325. return BANK_NOBANK;
  326. type = BANK_SHARED;
  327. }
  328. }
  329. else
  330. {
  331. if ((unsigned long)abs((char *)pBankInfo->pBankA -
  332. (char *)pBankInfo->pBankB) < pBankInfo->BankSize)
  333. return BANK_NOBANK;
  334. if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
  335. {
  336. if (pBankInfo->SetSourceAndDestinationBanks !=
  337. pBankInfo->SetSourceBank)
  338. return BANK_NOBANK;
  339. }
  340. else
  341. {
  342. if (pBankInfo->SetSourceAndDestinationBanks ==
  343. pBankInfo->SetDestinationBank)
  344. return BANK_NOBANK;
  345. }
  346. type = BANK_DOUBLE;
  347. }
  348. /*
  349. * Internal limitation: Currently, only single banking is supported when
  350. * the pixmap format and the screen's pixel format are different. The
  351. * following test is only partially successful at detecting this condition.
  352. */
  353. if (pBankInfo->nBankDepth != pScreen->rootDepth)
  354. type = BANK_SINGLE;
  355. return type;
  356. }
  357. /* Least common multiple */
  358. static unsigned int
  359. miLCM(
  360. unsigned int x,
  361. unsigned int y
  362. )
  363. {
  364. unsigned int m = x, n = y, o;
  365. while ((o = m % n))
  366. {
  367. m = n;
  368. n = o;
  369. }
  370. return (x / n) * y;
  371. }
  372. /******************
  373. * GCOps wrappers *
  374. ******************/
  375. static void
  376. miBankFillSpans(
  377. DrawablePtr pDrawable,
  378. GCPtr pGC,
  379. int nArray,
  380. DDXPointPtr pptInit,
  381. int *pwidthInit,
  382. int fSorted
  383. )
  384. {
  385. GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC,
  386. nArray, pptInit, pwidthInit, fSorted));
  387. }
  388. static void
  389. miBankSetSpans(
  390. DrawablePtr pDrawable,
  391. GCPtr pGC,
  392. char *psrc,
  393. DDXPointPtr ppt,
  394. int *pwidth,
  395. int nArray,
  396. int fSorted
  397. )
  398. {
  399. GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc,
  400. ppt, pwidth, nArray, fSorted));
  401. }
  402. static void
  403. miBankPutImage(
  404. DrawablePtr pDrawable,
  405. GCPtr pGC,
  406. int depth,
  407. int x,
  408. int y,
  409. int w,
  410. int h,
  411. int leftPad,
  412. int format,
  413. char *pImage
  414. )
  415. {
  416. if ((w > 0) && (h > 0))
  417. {
  418. GCOP_INIT;
  419. SCREEN_SAVE;
  420. if (!IS_BANKED(pDrawable))
  421. {
  422. GCOP_UNWRAP;
  423. (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
  424. leftPad, format, pImage);
  425. GCOP_WRAP;
  426. }
  427. else
  428. {
  429. int i, j;
  430. CLIP_SAVE;
  431. i = FirstBankOf(x + pDrawable->x, y + pDrawable->y);
  432. j = LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h);
  433. for (; i <= j; i++)
  434. {
  435. if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
  436. continue;
  437. GCOP_UNWRAP;
  438. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
  439. (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
  440. leftPad, format, pImage);
  441. GCOP_WRAP;
  442. }
  443. CLIP_RESTORE;
  444. }
  445. SCREEN_RESTORE;
  446. }
  447. }
  448. /*
  449. * Here the CopyArea/CopyPlane wrappers. First off, we have to clip against
  450. * the source in order to make the minimal number of copies in case of slow
  451. * systems. Also the exposure handling is quite tricky. Special attention
  452. * is to be given to the way the copies are sequenced. The list of boxes after
  453. * the source clip is used to build a workqueue, that contains the atomic
  454. * copies (i.e. only from one bank to one bank). Doing so produces a minimal
  455. * list of things to do.
  456. */
  457. static RegionPtr
  458. miBankCopy(
  459. DrawablePtr pSrc,
  460. DrawablePtr pDst,
  461. GCPtr pGC,
  462. int srcx,
  463. int srcy,
  464. int w,
  465. int h,
  466. int dstx,
  467. int dsty,
  468. unsigned long plane,
  469. Bool SinglePlane
  470. )
  471. {
  472. int cx1, cy1, cx2, cy2;
  473. int ns, nd, nse, nde, dx, dy, xorg = 0, yorg = 0;
  474. int maxWidth = 0, maxHeight = 0, paddedWidth = 0;
  475. int nBox, nBoxClipSrc, nBoxClipDst, nQueue;
  476. BoxPtr pBox, pBoxClipSrc, pBoxClipDst;
  477. BoxRec fastBox, ccBox;
  478. RegionPtr ret = NULL, prgnSrcClip = NULL;
  479. RegionRec rgnDst;
  480. char *pImage = NULL;
  481. miBankQueue *pQueue, *pQueueNew, *Queue;
  482. miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase;
  483. Bool fastBlit, freeSrcClip, fastClip;
  484. Bool fExpose = FALSE, fastExpose = FALSE;
  485. GCOP_INIT;
  486. SCREEN_SAVE;
  487. if (!IS_BANKED(pSrc) && !IS_BANKED(pDst))
  488. {
  489. GCOP_UNWRAP;
  490. if (SinglePlane)
  491. ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
  492. srcx, srcy, w, h, dstx, dsty, plane);
  493. else
  494. ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
  495. srcx, srcy, w, h, dstx, dsty);
  496. GCOP_WRAP;
  497. }
  498. else if (!IS_BANKED(pDst))
  499. {
  500. fExpose = pGC->fExpose;
  501. pGC->fExpose = FALSE;
  502. xorg = pSrc->x;
  503. yorg = pSrc->y;
  504. dx = dstx - srcx;
  505. dy = dsty - srcy;
  506. srcx += xorg;
  507. srcy += yorg;
  508. ns = FirstBankOf(srcx, srcy);
  509. nse = LastBankOf(srcx + w, srcy + h);
  510. for (; ns <= nse; ns++)
  511. {
  512. if (!pScreenPriv->pBanks[ns])
  513. continue;
  514. nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
  515. pBox = REGION_RECTS(pScreenPriv->pBanks[ns]);
  516. for (; nBox--; pBox++)
  517. {
  518. cx1 = max(pBox->x1, srcx);
  519. cy1 = max(pBox->y1, srcy);
  520. cx2 = min(pBox->x2, srcx + w);
  521. cy2 = min(pBox->y2, srcy + h);
  522. if ((cx1 >= cx2) || (cy1 >= cy2))
  523. continue;
  524. GCOP_UNWRAP;
  525. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns);
  526. if (SinglePlane)
  527. (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
  528. cx1 - xorg, cy1 - yorg,
  529. cx2 - cx1, cy2 - cy1,
  530. cx1 + dx - xorg, cy1 + dy - yorg, plane);
  531. else
  532. (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
  533. cx1 - xorg, cy1 - yorg,
  534. cx2 - cx1, cy2 - cy1,
  535. cx1 + dx - xorg, cy1 + dy - yorg);
  536. GCOP_WRAP;
  537. }
  538. }
  539. pGC->fExpose = fExpose;
  540. srcx -= xorg;
  541. srcy -= yorg;
  542. }
  543. else if (!IS_BANKED(pSrc))
  544. {
  545. CLIP_SAVE;
  546. if (pGC->miTranslate)
  547. {
  548. xorg = pDst->x;
  549. yorg = pDst->y;
  550. }
  551. dx = srcx - dstx;
  552. dy = srcy - dsty;
  553. dstx += xorg;
  554. dsty += yorg;
  555. nd = FirstBankOf(dstx, dsty);
  556. nde = LastBankOf(dstx + w, dsty + h);
  557. for (; nd <= nde; nd++)
  558. {
  559. if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd]))
  560. continue;
  561. /*
  562. * It's faster to let the lower-level CopyArea do the clipping
  563. * within each bank.
  564. */
  565. nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
  566. pBox = REGION_RECTS(pScreenPriv->pBanks[nd]);
  567. for (; nBox--; pBox++)
  568. {
  569. cx1 = max(pBox->x1, dstx);
  570. cy1 = max(pBox->y1, dsty);
  571. cx2 = min(pBox->x2, dstx + w);
  572. cy2 = min(pBox->y2, dsty + h);
  573. if ((cx1 >= cx2) || (cy1 >= cy2))
  574. continue;
  575. GCOP_UNWRAP;
  576. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd);
  577. if (SinglePlane)
  578. (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
  579. cx1 + dx - xorg, cy1 + dy - yorg,
  580. cx2 - cx1, cy2 - cy1,
  581. cx1 - xorg, cy1 - yorg, plane);
  582. else
  583. (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
  584. cx1 + dx - xorg, cy1 + dy - yorg,
  585. cx2 - cx1, cy2 - cy1,
  586. cx1 - xorg, cy1 - yorg);
  587. GCOP_WRAP;
  588. }
  589. }
  590. CLIP_RESTORE;
  591. }
  592. else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
  593. {
  594. CLIP_SAVE;
  595. fExpose = pGC->fExpose;
  596. fastBox.x1 = srcx + pSrc->x;
  597. fastBox.y1 = srcy + pSrc->y;
  598. fastBox.x2 = fastBox.x1 + w;
  599. fastBox.y2 = fastBox.y1 + h;
  600. dx = dstx - fastBox.x1;
  601. dy = dsty - fastBox.y1;
  602. if (pGC->miTranslate)
  603. {
  604. xorg = pDst->x;
  605. yorg = pDst->y;
  606. }
  607. /*
  608. * Clip against the source. Otherwise we will blit too much for SINGLE
  609. * and SHARED banked systems.
  610. */
  611. freeSrcClip = FALSE;
  612. fastClip = FALSE;
  613. fastExpose = FALSE;
  614. if (pGC->subWindowMode != IncludeInferiors)
  615. prgnSrcClip = &((WindowPtr)pSrc)->clipList;
  616. else if (!((WindowPtr)pSrc)->parent)
  617. fastClip = TRUE;
  618. else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE))
  619. prgnSrcClip = pGC->pCompositeClip;
  620. else
  621. {
  622. prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc);
  623. freeSrcClip = TRUE;
  624. }
  625. if (fastClip)
  626. {
  627. fastExpose = TRUE;
  628. /*
  629. * Clip the source. If regions extend beyond the source size, make
  630. * sure exposure events get sent.
  631. */
  632. if (fastBox.x1 < pSrc->x)
  633. {
  634. fastBox.x1 = pSrc->x;
  635. fastExpose = FALSE;
  636. }
  637. if (fastBox.y1 < pSrc->y)
  638. {
  639. fastBox.y1 = pSrc->y;
  640. fastExpose = FALSE;
  641. }
  642. if (fastBox.x2 > pSrc->x + (int) pSrc->width)
  643. {
  644. fastBox.x2 = pSrc->x + (int) pSrc->width;
  645. fastExpose = FALSE;
  646. }
  647. if (fastBox.y2 > pSrc->y + (int) pSrc->height)
  648. {
  649. fastBox.y2 = pSrc->y + (int) pSrc->height;
  650. fastExpose = FALSE;
  651. }
  652. nBox = 1;
  653. pBox = &fastBox;
  654. }
  655. else
  656. {
  657. REGION_INIT(&rgnDst, &fastBox, 1);
  658. REGION_INTERSECT(&rgnDst, &rgnDst, prgnSrcClip);
  659. pBox = REGION_RECTS(&rgnDst);
  660. nBox = REGION_NUM_RECTS(&rgnDst);
  661. }
  662. /*
  663. * fastBlit can only be TRUE if we don't need to worry about attempts
  664. * to read partial pixels through the destination bank.
  665. */
  666. if (SinglePlane)
  667. fastBlit = pGCPriv->fastPlane;
  668. else
  669. fastBlit = pGCPriv->fastCopy;
  670. nQueue = nBox * pScreenPriv->maxRects * 2;
  671. pQueue = Queue = ALLOCATE_LOCAL_ARRAY(miBankQueue, nQueue);
  672. if (Queue)
  673. {
  674. for (; nBox--; pBox++)
  675. {
  676. ns = FirstBankOf(pBox->x1, pBox->y1);
  677. nse = LastBankOf(pBox->x2, pBox->y2);
  678. for (; ns <= nse; ns++)
  679. {
  680. if (!pScreenPriv->pBanks[ns])
  681. continue;
  682. nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
  683. pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]);
  684. for (; nBoxClipSrc--; pBoxClipSrc++)
  685. {
  686. cx1 = max(pBox->x1, pBoxClipSrc->x1);
  687. cy1 = max(pBox->y1, pBoxClipSrc->y1);
  688. cx2 = min(pBox->x2, pBoxClipSrc->x2);
  689. cy2 = min(pBox->y2, pBoxClipSrc->y2);
  690. /* Check to see if the region is empty */
  691. if ((cx1 >= cx2) || (cy1 >= cy2))
  692. continue;
  693. /* Translate c[xy]* to destination coordinates */
  694. cx1 += dx + xorg;
  695. cy1 += dy + yorg;
  696. cx2 += dx + xorg;
  697. cy2 += dy + yorg;
  698. nd = FirstBankOf(cx1, cy1);
  699. nde = LastBankOf(cx2, cy2);
  700. for (; nd <= nde; nd++)
  701. {
  702. if (!pGCPriv->pBankedClips[nd])
  703. continue;
  704. /*
  705. * Clients can send quite large clip descriptions,
  706. * so use the bank clips here instead.
  707. */
  708. nBoxClipDst =
  709. REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
  710. pBoxClipDst =
  711. REGION_RECTS(pScreenPriv->pBanks[nd]);
  712. for (; nBoxClipDst--; pBoxClipDst++)
  713. {
  714. ccBox.x1 = max(cx1, pBoxClipDst->x1);
  715. ccBox.y1 = max(cy1, pBoxClipDst->y1);
  716. ccBox.x2 = min(cx2, pBoxClipDst->x2);
  717. ccBox.y2 = min(cy2, pBoxClipDst->y2);
  718. /* Check to see if the region is empty */
  719. if ((ccBox.x1 >= ccBox.x2) ||
  720. (ccBox.y1 >= ccBox.y2))
  721. continue;
  722. pQueue->srcBankNo = ns;
  723. pQueue->dstBankNo = nd;
  724. pQueue->x = ccBox.x1 - xorg;
  725. pQueue->y = ccBox.y1 - yorg;
  726. pQueue->w = ccBox.x2 - ccBox.x1;
  727. pQueue->h = ccBox.y2 - ccBox.y1;
  728. if (maxWidth < pQueue->w)
  729. maxWidth = pQueue->w;
  730. if (maxHeight < pQueue->h)
  731. maxHeight = pQueue->h;
  732. /*
  733. * When shared banking is used and the source
  734. * and destination banks differ, prevent
  735. * attempts to fetch partial scanline pad units
  736. * through the destination bank.
  737. */
  738. pQueue->fastBlit = fastBlit;
  739. if (fastBlit &&
  740. (pScreenPriv->type == BANK_SHARED) &&
  741. (ns != nd) &&
  742. ((ccBox.x1 %
  743. pScreenPriv->nPixelsPerScanlinePadUnit) ||
  744. (ccBox.x2 %
  745. pScreenPriv->nPixelsPerScanlinePadUnit) ||
  746. (RECT_IN_REGION(
  747. pGCPriv->pBankedClips[nd], &ccBox) !=
  748. rgnIN)))
  749. pQueue->fastBlit = FALSE;
  750. pQueue++;
  751. }
  752. }
  753. }
  754. }
  755. }
  756. }
  757. if (!fastClip)
  758. {
  759. REGION_UNINIT(&rgnDst);
  760. if (freeSrcClip)
  761. REGION_DESTROY(prgnSrcClip);
  762. }
  763. pQueueNew = pQueue;
  764. nQueue = pQueue - Queue;
  765. if (nQueue > 0)
  766. {
  767. BANK_SAVE;
  768. pQueue = Queue;
  769. if ((nQueue > 1) &&
  770. ((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors)))
  771. {
  772. if ((srcy + pSrc->y) < (dsty + yorg))
  773. {
  774. /* Sort from bottom to top */
  775. pQueueBase = pQueueNext = pQueue + nQueue - 1;
  776. while (pQueueBase >= pQueue)
  777. {
  778. while ((pQueueNext >= pQueue) &&
  779. (pQueueBase->y == pQueueNext->y))
  780. pQueueNext--;
  781. pQueueTmp = pQueueNext + 1;
  782. while (pQueueTmp <= pQueueBase)
  783. *pQueueNew++ = *pQueueTmp++;
  784. pQueueBase = pQueueNext;
  785. }
  786. pQueueNew -= nQueue;
  787. pQueue = pQueueNew;
  788. pQueueNew = Queue;
  789. }
  790. if ((srcx + pSrc->x) < (dstx + xorg))
  791. {
  792. /* Sort from right to left */
  793. pQueueBase = pQueueNext = pQueue;
  794. while (pQueueBase < pQueue + nQueue)
  795. {
  796. while ((pQueueNext < pQueue + nQueue) &&
  797. (pQueueNext->y == pQueueBase->y))
  798. pQueueNext++;
  799. pQueueTmp = pQueueNext;
  800. while (pQueueTmp != pQueueBase)
  801. *pQueueNew++ = *--pQueueTmp;
  802. pQueueBase = pQueueNext;
  803. }
  804. pQueueNew -= nQueue;
  805. pQueue = pQueueNew;
  806. }
  807. }
  808. paddedWidth = PixmapBytePad(maxWidth,
  809. pScreenPriv->pScreenPixmap->drawable.depth);
  810. pImage = (char *)ALLOCATE_LOCAL(paddedWidth * maxHeight);
  811. pGC->fExpose = FALSE;
  812. while (nQueue--)
  813. {
  814. pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo];
  815. GCOP_UNWRAP;
  816. if (pQueue->srcBankNo == pQueue->dstBankNo)
  817. {
  818. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
  819. -1, -1, pQueue->srcBankNo);
  820. if (SinglePlane)
  821. (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
  822. pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
  823. pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
  824. else
  825. (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
  826. pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
  827. pQueue->w, pQueue->h, pQueue->x, pQueue->y);
  828. }
  829. else if (pQueue->fastBlit)
  830. {
  831. SET_SOURCE_BANK (pScreenPriv->pBankPixmap,
  832. pScreenPriv->pScreenPixmap->drawable.width,
  833. pScreenPriv->pScreenPixmap->devKind,
  834. pQueue->srcBankNo);
  835. SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap,
  836. -1, -1, pQueue->dstBankNo);
  837. if (SinglePlane)
  838. (*pGC->ops->CopyPlane)(
  839. (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
  840. pQueue->x - dx, pQueue->y - dy,
  841. pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
  842. else
  843. (*pGC->ops->CopyArea)(
  844. (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
  845. pQueue->x - dx, pQueue->y - dy,
  846. pQueue->w, pQueue->h, pQueue->x, pQueue->y);
  847. }
  848. else if (pImage)
  849. {
  850. ModifyPixmap(pScreenPriv->pBankPixmap,
  851. maxWidth, paddedWidth, pImage);
  852. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
  853. -1, -1, pQueue->srcBankNo);
  854. (*pScreenPriv->pBankGC->ops->CopyArea)(
  855. pSrc, (DrawablePtr)pScreenPriv->pBankPixmap,
  856. pScreenPriv->pBankGC,
  857. pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
  858. pQueue->w, pQueue->h, 0, 0);
  859. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
  860. -1, -1, pQueue->dstBankNo);
  861. if (SinglePlane)
  862. (*pGC->ops->CopyPlane)(
  863. (DrawablePtr)pScreenPriv->pBankPixmap,
  864. pDst, pGC, 0, 0, pQueue->w, pQueue->h,
  865. pQueue->x, pQueue->y, plane);
  866. else
  867. (*pGC->ops->CopyArea)(
  868. (DrawablePtr)pScreenPriv->pBankPixmap,
  869. pDst, pGC, 0, 0, pQueue->w, pQueue->h,
  870. pQueue->x, pQueue->y);
  871. }
  872. GCOP_WRAP;
  873. pQueue++;
  874. }
  875. DEALLOCATE_LOCAL(pImage);
  876. BANK_RESTORE;
  877. }
  878. CLIP_RESTORE;
  879. pGC->fExpose = fExpose;
  880. DEALLOCATE_LOCAL(Queue);
  881. }
  882. SCREEN_RESTORE;
  883. if (!fExpose || fastExpose)
  884. return ret;
  885. return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0);
  886. }
  887. static RegionPtr
  888. miBankCopyArea(
  889. DrawablePtr pSrc,
  890. DrawablePtr pDst,
  891. GCPtr pGC,
  892. int srcx,
  893. int srcy,
  894. int w,
  895. int h,
  896. int dstx,
  897. int dsty
  898. )
  899. {
  900. return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE);
  901. }
  902. static RegionPtr
  903. miBankCopyPlane(
  904. DrawablePtr pSrc,
  905. DrawablePtr pDst,
  906. GCPtr pGC,
  907. int srcx,
  908. int srcy,
  909. int w,
  910. int h,
  911. int dstx,
  912. int dsty,
  913. unsigned long plane
  914. )
  915. {
  916. return
  917. miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE);
  918. }
  919. static void
  920. miBankPolyPoint(
  921. DrawablePtr pDrawable,
  922. GCPtr pGC,
  923. int mode,
  924. int nArray,
  925. xPoint *pArray
  926. )
  927. {
  928. # define GCOP_ARGS GCOP_0D_ARGS
  929. GCOP_COMPLEX(PolyPoint, xPoint);
  930. # undef GCOP_ARGS
  931. }
  932. static void
  933. miBankPolylines(
  934. DrawablePtr pDrawable,
  935. GCPtr pGC,
  936. int mode,
  937. int nArray,
  938. DDXPointPtr pArray
  939. )
  940. {
  941. # define GCOP_ARGS GCOP_0D_ARGS
  942. GCOP_COMPLEX(Polylines, DDXPointRec);
  943. # undef GCOP_ARGS
  944. }
  945. static void
  946. miBankPolySegment(
  947. DrawablePtr pDrawable,
  948. GCPtr pGC,
  949. int nArray,
  950. xSegment *pArray
  951. )
  952. {
  953. # define GCOP_ARGS GCOP_1D_ARGS
  954. GCOP_COMPLEX(PolySegment, xSegment);
  955. # undef GCOP_ARGS
  956. }
  957. static void
  958. miBankPolyRectangle(
  959. DrawablePtr pDrawable,
  960. GCPtr pGC,
  961. int nArray,
  962. xRectangle *pArray
  963. )
  964. {
  965. # define GCOP_ARGS GCOP_1D_ARGS
  966. GCOP_COMPLEX(PolyRectangle, xRectangle);
  967. # undef GCOP_ARGS
  968. }
  969. static void
  970. miBankPolyArc(
  971. DrawablePtr pDrawable,
  972. GCPtr pGC,
  973. int nArray,
  974. xArc *pArray
  975. )
  976. {
  977. # define GCOP_ARGS GCOP_1D_ARGS
  978. GCOP_COMPLEX(PolyArc, xArc);
  979. # undef GCOP_ARGS
  980. }
  981. static void
  982. miBankFillPolygon(
  983. DrawablePtr pDrawable,
  984. GCPtr pGC,
  985. int shape,
  986. int mode,
  987. int nArray,
  988. DDXPointRec *pArray
  989. )
  990. {
  991. # define GCOP_ARGS GCOP_2D_ARGS
  992. GCOP_COMPLEX(FillPolygon, DDXPointRec);
  993. # undef GCOP_ARGS
  994. }
  995. static void
  996. miBankPolyFillRect(
  997. DrawablePtr pDrawable,
  998. GCPtr pGC,
  999. int nArray,
  1000. xRectangle *pArray
  1001. )
  1002. {
  1003. # define GCOP_ARGS GCOP_1D_ARGS
  1004. GCOP_COMPLEX(PolyFillRect, xRectangle);
  1005. # undef GCOP_ARGS
  1006. }
  1007. static void
  1008. miBankPolyFillArc(
  1009. DrawablePtr pDrawable,
  1010. GCPtr pGC,
  1011. int nArray,
  1012. xArc *pArray
  1013. )
  1014. {
  1015. # define GCOP_ARGS GCOP_1D_ARGS
  1016. GCOP_COMPLEX(PolyFillArc, xArc);
  1017. # undef GCOP_ARGS
  1018. }
  1019. static int
  1020. miBankPolyText8(
  1021. DrawablePtr pDrawable,
  1022. GCPtr pGC,
  1023. int x,
  1024. int y,
  1025. int nArray,
  1026. char *pchar
  1027. )
  1028. {
  1029. int retval = x;
  1030. GCOP_SIMPLE(retval =
  1031. (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar));
  1032. return retval;
  1033. }
  1034. static int
  1035. miBankPolyText16(
  1036. DrawablePtr pDrawable,
  1037. GCPtr pGC,
  1038. int x,
  1039. int y,
  1040. int nArray,
  1041. unsigned short *pchar
  1042. )
  1043. {
  1044. int retval = x;
  1045. GCOP_SIMPLE(retval =
  1046. (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar));
  1047. return retval;
  1048. }
  1049. static void
  1050. miBankImageText8(
  1051. DrawablePtr pDrawable,
  1052. GCPtr pGC,
  1053. int x,
  1054. int y,
  1055. int nArray,
  1056. char *pchar
  1057. )
  1058. {
  1059. GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar));
  1060. }
  1061. static void
  1062. miBankImageText16(
  1063. DrawablePtr pDrawable,
  1064. GCPtr pGC,
  1065. int x,
  1066. int y,
  1067. int nArray,
  1068. unsigned short *pchar
  1069. )
  1070. {
  1071. GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar));
  1072. }
  1073. static void
  1074. miBankImageGlyphBlt(
  1075. DrawablePtr pDrawable,
  1076. GCPtr pGC,
  1077. int x,
  1078. int y,
  1079. unsigned int nArray,
  1080. CharInfoPtr *ppci,
  1081. pointer pglyphBase
  1082. )
  1083. {
  1084. GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC,
  1085. x, y, nArray, ppci, pglyphBase));
  1086. }
  1087. static void
  1088. miBankPolyGlyphBlt(
  1089. DrawablePtr pDrawable,
  1090. GCPtr pGC,
  1091. int x,
  1092. int y,
  1093. unsigned int nArray,
  1094. CharInfoPtr *ppci,
  1095. pointer pglyphBase
  1096. )
  1097. {
  1098. GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC,
  1099. x, y, nArray, ppci, pglyphBase));
  1100. }
  1101. static void
  1102. miBankPushPixels(
  1103. GCPtr pGC,
  1104. PixmapPtr pBitmap,
  1105. DrawablePtr pDrawable,
  1106. int w,
  1107. int h,
  1108. int x,
  1109. int y
  1110. )
  1111. {
  1112. if ((w > 0) && (h > 0))
  1113. {
  1114. GCOP_INIT;
  1115. SCREEN_SAVE;
  1116. if (!IS_BANKED(pDrawable))
  1117. {
  1118. GCOP_UNWRAP;
  1119. (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
  1120. GCOP_WRAP;
  1121. }
  1122. else
  1123. {
  1124. int i, j;
  1125. CLIP_SAVE;
  1126. i = FirstBankOf(x, y);
  1127. j = LastBankOf(x + w, y + h);
  1128. for (; i <= j; i++)
  1129. {
  1130. if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
  1131. continue;
  1132. GCOP_UNWRAP;
  1133. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
  1134. (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
  1135. GCOP_WRAP;
  1136. }
  1137. CLIP_RESTORE;
  1138. }
  1139. SCREEN_RESTORE;
  1140. }
  1141. }
  1142. static GCOps miBankGCOps =
  1143. {
  1144. miBankFillSpans,
  1145. miBankSetSpans,
  1146. miBankPutImage,
  1147. miBankCopyArea,
  1148. miBankCopyPlane,
  1149. miBankPolyPoint,
  1150. miBankPolylines,
  1151. miBankPolySegment,
  1152. miBankPolyRectangle,
  1153. miBankPolyArc,
  1154. miBankFillPolygon,
  1155. miBankPolyFillRect,
  1156. miBankPolyFillArc,
  1157. miBankPolyText8,
  1158. miBankPolyText16,
  1159. miBankImageText8,
  1160. miBankImageText16,
  1161. miBankImageGlyphBlt,
  1162. miBankPolyGlyphBlt,
  1163. miBankPushPixels,
  1164. {NULL} /* devPrivate */
  1165. };
  1166. /********************
  1167. * GCFuncs wrappers *
  1168. ********************/
  1169. static void
  1170. miBankValidateGC(
  1171. GCPtr pGC,
  1172. unsigned long changes,
  1173. DrawablePtr pDrawable
  1174. )
  1175. {
  1176. GC_INIT(pGC);
  1177. GC_UNWRAP(pGC);
  1178. (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
  1179. if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
  1180. (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
  1181. {
  1182. ScreenPtr pScreen = pGC->pScreen;
  1183. RegionPtr prgnClip;
  1184. unsigned long planemask;
  1185. int i;
  1186. SCREEN_INIT;
  1187. SCREEN_SAVE;
  1188. if (IS_BANKED(pDrawable))
  1189. {
  1190. for (i = 0; i < pScreenPriv->nBanks; i++)
  1191. {
  1192. if (!pScreenPriv->pBanks[i])
  1193. continue;
  1194. if (!(prgnClip = pGCPriv->pBankedClips[i]))
  1195. prgnClip = REGION_CREATE(NULL, 1);
  1196. REGION_INTERSECT(prgnClip,
  1197. pScreenPriv->pBanks[i], pGC->pCompositeClip);
  1198. if ((REGION_NUM_RECTS(prgnClip) <= 1) &&
  1199. ((prgnClip->extents.x1 == prgnClip->extents.x2) ||
  1200. (prgnClip->extents.y1 == prgnClip->extents.y2)))
  1201. {
  1202. REGION_DESTROY(prgnClip);
  1203. pGCPriv->pBankedClips[i] = NULL;
  1204. }
  1205. else
  1206. pGCPriv->pBankedClips[i] = prgnClip;
  1207. }
  1208. /*
  1209. * fastCopy and fastPlane can only be TRUE if we don't need to
  1210. * worry about attempts to read partial pixels through the
  1211. * destination bank.
  1212. */
  1213. switch (pScreenPriv->type)
  1214. {
  1215. case BANK_SHARED:
  1216. pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
  1217. if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) &&
  1218. (pGC->alu != GXcopyInverted) && (pGC->alu != GXset))
  1219. break;
  1220. if (pScreen->rootDepth == 1)
  1221. pGCPriv->fastPlane = TRUE;
  1222. /* This is probably paranoia */
  1223. if ((pDrawable->depth != pScreen->rootDepth) ||
  1224. (pDrawable->depth != pGC->depth))
  1225. break;
  1226. planemask = (1 << pGC->depth) - 1;
  1227. if ((pGC->planemask & planemask) == planemask)
  1228. pGCPriv->fastCopy = TRUE;
  1229. break;
  1230. case BANK_DOUBLE:
  1231. pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE;
  1232. break;
  1233. default:
  1234. pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
  1235. break;
  1236. }
  1237. }
  1238. else
  1239. {
  1240. /*
  1241. * Here we are on a pixmap and don't need all that special clipping
  1242. * stuff, hence free it.
  1243. */
  1244. for (i = 0; i < pScreenPriv->nBanks; i++)
  1245. {
  1246. if (!pGCPriv->pBankedClips[i])
  1247. continue;
  1248. REGION_DESTROY(pGCPriv->pBankedClips[i]);
  1249. pGCPriv->pBankedClips[i] = NULL;
  1250. }
  1251. }
  1252. SCREEN_RESTORE;
  1253. }
  1254. GC_WRAP(pGC);
  1255. }
  1256. static void
  1257. miBankChangeGC(
  1258. GCPtr pGC,
  1259. unsigned long mask
  1260. )
  1261. {
  1262. GC_INIT(pGC);
  1263. GC_UNWRAP(pGC);
  1264. (*pGC->funcs->ChangeGC)(pGC, mask);
  1265. GC_WRAP(pGC);
  1266. }
  1267. static void
  1268. miBankCopyGC(
  1269. GCPtr pGCSrc,
  1270. unsigned long mask,
  1271. GCPtr pGCDst
  1272. )
  1273. {
  1274. GC_INIT(pGCDst);
  1275. GC_UNWRAP(pGCDst);
  1276. (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
  1277. GC_WRAP(pGCDst);
  1278. }
  1279. static void
  1280. miBankDestroyGC(
  1281. GCPtr pGC
  1282. )
  1283. {
  1284. ScreenPtr pScreen = pGC->pScreen;
  1285. int i;
  1286. SCREEN_INIT;
  1287. GC_INIT(pGC);
  1288. GC_UNWRAP(pGC);
  1289. (*pGC->funcs->DestroyGC)(pGC);
  1290. for (i = 0; i < pScreenPriv->nBanks; i++)
  1291. {
  1292. if (!pGCPriv->pBankedClips[i])
  1293. continue;
  1294. REGION_DESTROY(pGCPriv->pBankedClips[i]);
  1295. pGCPriv->pBankedClips[i] = NULL;
  1296. }
  1297. GC_WRAP(pGC);
  1298. }
  1299. static void
  1300. miBankChangeClip(
  1301. GCPtr pGC,
  1302. int type,
  1303. pointer pvalue,
  1304. int nrects
  1305. )
  1306. {
  1307. GC_INIT(pGC);
  1308. GC_UNWRAP(pGC);
  1309. (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
  1310. GC_WRAP(pGC);
  1311. }
  1312. static void
  1313. miBankDestroyClip(
  1314. GCPtr pGC
  1315. )
  1316. {
  1317. GC_INIT(pGC);
  1318. GC_UNWRAP(pGC);
  1319. (*pGC->funcs->DestroyClip)(pGC);
  1320. GC_WRAP(pGC);
  1321. }
  1322. static void
  1323. miBankCopyClip(
  1324. GCPtr pGCDst,
  1325. GCPtr pGCSrc
  1326. )
  1327. {
  1328. GC_INIT(pGCDst);
  1329. GC_UNWRAP(pGCDst);
  1330. (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
  1331. GC_WRAP(pGCDst);
  1332. }
  1333. static GCFuncs miBankGCFuncs =
  1334. {
  1335. miBankValidateGC,
  1336. miBankChangeGC,
  1337. miBankCopyGC,
  1338. miBankDestroyGC,
  1339. miBankChangeClip,
  1340. miBankDestroyClip,
  1341. miBankCopyClip
  1342. };
  1343. /*******************
  1344. * Screen Wrappers *
  1345. *******************/
  1346. static Bool
  1347. miBankCreateScreenResources(
  1348. ScreenPtr pScreen
  1349. )
  1350. {
  1351. Bool retval;
  1352. SCREEN_INIT;
  1353. SCREEN_UNWRAP(CreateScreenResources);
  1354. if ((retval = (*pScreen->CreateScreenResources)(pScreen)))
  1355. {
  1356. /* Set screen buffer address to something recognizable */
  1357. pScreenPriv->pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
  1358. pScreenPriv->pbits = pScreenPriv->pScreenPixmap->devPrivate.ptr;
  1359. pScreenPriv->pScreenPixmap->devPrivate.ptr = (pointer)pScreenPriv;
  1360. /* Get shadow pixmap; width & height of 0 means no pixmap data */
  1361. pScreenPriv->pBankPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0,
  1362. pScreenPriv->pScreenPixmap->drawable.depth);
  1363. if (!pScreenPriv->pBankPixmap)
  1364. retval = FALSE;
  1365. }
  1366. /* Shadow the screen */
  1367. if (retval)
  1368. retval = (*pScreen->ModifyPixmapHeader)(pScreenPriv->pBankPixmap,
  1369. pScreenPriv->pScreenPixmap->drawable.width,
  1370. pScreenPriv->pScreenPixmap->drawable.height,
  1371. pScreenPriv->pScreenPixmap->drawable.depth,
  1372. pScreenPriv->pScreenPixmap->drawable.bitsPerPixel,
  1373. pScreenPriv->pScreenPixmap->devKind, NULL);
  1374. /* Create shadow GC */
  1375. if (retval)
  1376. {
  1377. pScreenPriv->pBankGC = CreateScratchGC(pScreen,
  1378. pScreenPriv->pBankPixmap->drawable.depth);
  1379. if (!pScreenPriv->pBankGC)
  1380. retval = FALSE;
  1381. }
  1382. /* Validate shadow GC */
  1383. if (retval)
  1384. {
  1385. pScreenPriv->pBankGC->graphicsExposures = FALSE;
  1386. pScreenPriv->pBankGC->subWindowMode = IncludeInferiors;
  1387. ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap,
  1388. pScreenPriv->pBankGC);
  1389. }
  1390. SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
  1391. return retval;
  1392. }
  1393. static Bool
  1394. miBankModifyPixmapHeader(
  1395. PixmapPtr pPixmap,
  1396. int width,
  1397. int height,
  1398. int depth,
  1399. int bitsPerPixel,
  1400. int devKind,
  1401. pointer pPixData
  1402. )
  1403. {
  1404. Bool retval = FALSE;
  1405. if (pPixmap)
  1406. {
  1407. ScreenPtr pScreen = pPixmap->drawable.pScreen;
  1408. SCREEN_INIT;
  1409. PIXMAP_SAVE(pPixmap);
  1410. SCREEN_UNWRAP(ModifyPixmapHeader);
  1411. retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height,
  1412. depth, bitsPerPixel, devKind, pPixData);
  1413. SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
  1414. if (pbits == (pointer)pScreenPriv)
  1415. {
  1416. pScreenPriv->pbits = pPixmap->devPrivate.ptr;
  1417. pPixmap->devPrivate.ptr = pbits;
  1418. }
  1419. }
  1420. return retval;
  1421. }
  1422. static Bool
  1423. miBankCloseScreen(
  1424. int nIndex,
  1425. ScreenPtr pScreen
  1426. )
  1427. {
  1428. int i;
  1429. SCREEN_INIT;
  1430. /* Free shadow GC */
  1431. FreeScratchGC(pScreenPriv->pBankGC);
  1432. /* Free shadow pixmap */
  1433. (*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap);
  1434. /* Restore screen pixmap devPrivate pointer */
  1435. pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits;
  1436. /* Delete bank clips */
  1437. for (i = 0; i < pScreenPriv->nBanks; i++)
  1438. if (pScreenPriv->pBanks[i])
  1439. REGION_DESTROY(pScreenPriv->pBanks[i]);
  1440. free(pScreenPriv->pBanks);
  1441. SCREEN_UNWRAP(CreateScreenResources);
  1442. SCREEN_UNWRAP(ModifyPixmapHeader);
  1443. SCREEN_UNWRAP(CloseScreen);
  1444. SCREEN_UNWRAP(GetImage);
  1445. SCREEN_UNWRAP(GetSpans);
  1446. SCREEN_UNWRAP(CreateGC);
  1447. SCREEN_UNWRAP(PaintWindowBackground);
  1448. SCREEN_UNWRAP(PaintWindowBorder);
  1449. SCREEN_UNWRAP(CopyWindow);
  1450. free(pScreenPriv);
  1451. return (*pScreen->CloseScreen)(nIndex, pScreen);
  1452. }
  1453. static void
  1454. miBankGetImage(
  1455. DrawablePtr pDrawable,
  1456. int sx,
  1457. int sy,
  1458. int w,
  1459. int h,
  1460. unsigned int format,
  1461. unsigned long planemask,
  1462. char *pImage
  1463. )
  1464. {
  1465. if ((w > 0) && (h > 0))
  1466. {
  1467. ScreenPtr pScreen = pDrawable->pScreen;
  1468. SCREEN_INIT;
  1469. SCREEN_STATUS;
  1470. SCREEN_UNWRAP(GetImage);
  1471. if (!IS_BANKED(pDrawable))
  1472. {
  1473. (*pScreen->GetImage)(pDrawable, sx, sy, w, h,
  1474. format, planemask, pImage);
  1475. }
  1476. else
  1477. {
  1478. int paddedWidth;
  1479. char *pBankImage;
  1480. paddedWidth = PixmapBytePad(w,
  1481. pScreenPriv->pScreenPixmap->drawable.depth);
  1482. pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth * h);
  1483. if (pBankImage)
  1484. {
  1485. BANK_SAVE;
  1486. ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth,
  1487. pBankImage);
  1488. (*pScreenPriv->pBankGC->ops->CopyArea)(
  1489. (DrawablePtr)WindowTable[pScreen->myNum],
  1490. (DrawablePtr)pScreenPriv->pBankPixmap,
  1491. pScreenPriv->pBankGC,
  1492. sx + pDrawable->x, sy + pDrawable->y, w, h, 0, 0);
  1493. (*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap,
  1494. 0, 0, w, h, format, planemask, pImage);
  1495. BANK_RESTORE;
  1496. DEALLOCATE_LOCAL(pBankImage);
  1497. }
  1498. }
  1499. SCREEN_WRAP(GetImage, miBankGetImage);
  1500. }
  1501. }
  1502. static void
  1503. miBankGetSpans(
  1504. DrawablePtr pDrawable,
  1505. int wMax,
  1506. DDXPointPtr ppt,
  1507. int *pwidth,
  1508. int nspans,
  1509. char *pImage
  1510. )
  1511. {
  1512. if (nspans > 0)
  1513. {
  1514. ScreenPtr pScreen = pDrawable->pScreen;
  1515. SCREEN_INIT;
  1516. SCREEN_STATUS;
  1517. SCREEN_UNWRAP(GetSpans);
  1518. if (!IS_BANKED(pDrawable))
  1519. {
  1520. (*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage);
  1521. }
  1522. else
  1523. {
  1524. char *pBankImage;
  1525. int paddedWidth;
  1526. DDXPointRec pt;
  1527. pt.x = pt.y = 0;
  1528. paddedWidth =
  1529. PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width,
  1530. pScreenPriv->pScreenPixmap->drawable.depth);
  1531. pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth);
  1532. if (pBankImage)
  1533. {
  1534. BANK_SAVE;
  1535. ModifyPixmap(pScreenPriv->pBankPixmap,
  1536. pScreenPriv->pScreenPixmap->drawable.width,
  1537. paddedWidth, pBankImage);
  1538. for (; nspans--; ppt++, pwidth++)
  1539. {
  1540. if (*pwidth <= 0)
  1541. continue;
  1542. (*pScreenPriv->pBankGC->ops->CopyArea)(
  1543. (DrawablePtr)WindowTable[pScreen->myNum],
  1544. (DrawablePtr)pScreenPriv->pBankPixmap,
  1545. pScreenPriv->pBankGC,
  1546. ppt->x, ppt->y, *pwidth, 1, 0, 0);
  1547. (*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap,
  1548. wMax, &pt, pwidth, 1, pImage);
  1549. pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth);
  1550. }
  1551. BANK_RESTORE;
  1552. DEALLOCATE_LOCAL(pBankImage);
  1553. }
  1554. }
  1555. SCREEN_WRAP(GetSpans, miBankGetSpans);
  1556. }
  1557. }
  1558. static Bool
  1559. miBankCreateGC(
  1560. GCPtr pGC
  1561. )
  1562. {
  1563. ScreenPtr pScreen = pGC->pScreen;
  1564. miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC);
  1565. Bool ret;
  1566. SCREEN_INIT;
  1567. SCREEN_UNWRAP(CreateGC);
  1568. if ((ret = (*pScreen->CreateGC)(pGC)))
  1569. {
  1570. pGCPriv->unwrappedOps = &miBankGCOps;
  1571. pGCPriv->unwrappedFuncs = &miBankGCFuncs;
  1572. GC_WRAP(pGC);
  1573. memset(&pGCPriv->pBankedClips, 0,
  1574. pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips));
  1575. }
  1576. SCREEN_WRAP(CreateGC, miBankCreateGC);
  1577. return ret;
  1578. }
  1579. static void
  1580. miBankPaintWindow(
  1581. WindowPtr pWin,
  1582. RegionPtr pRegion,
  1583. int what
  1584. )
  1585. {
  1586. ScreenPtr pScreen = pWin->drawable.pScreen;
  1587. RegionRec tmpReg;
  1588. int i;
  1589. PaintWindowProcPtr PaintWindow;
  1590. SCREEN_INIT;
  1591. SCREEN_SAVE;
  1592. if (what == PW_BORDER)
  1593. {
  1594. SCREEN_UNWRAP(PaintWindowBorder);
  1595. PaintWindow = pScreen->PaintWindowBorder;
  1596. }
  1597. else
  1598. {
  1599. SCREEN_UNWRAP(PaintWindowBackground);
  1600. PaintWindow = pScreen->PaintWindowBackground;
  1601. }
  1602. if (!IS_BANKED(pWin))
  1603. {
  1604. (*PaintWindow)(pWin, pRegion, what);
  1605. }
  1606. else
  1607. {
  1608. REGION_NULL(&tmpReg);
  1609. for (i = 0; i < pScreenPriv->nBanks; i++)
  1610. {
  1611. if (!pScreenPriv->pBanks[i])
  1612. continue;
  1613. REGION_INTERSECT(&tmpReg, pRegion,
  1614. pScreenPriv->pBanks[i]);
  1615. if (REGION_NIL(&tmpReg))
  1616. continue;
  1617. SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
  1618. (*PaintWindow)(pWin, &tmpReg, what);
  1619. }
  1620. REGION_UNINIT(&tmpReg);
  1621. }
  1622. if (what == PW_BORDER)
  1623. {
  1624. SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
  1625. }
  1626. else
  1627. {
  1628. SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
  1629. }
  1630. SCREEN_RESTORE;
  1631. }
  1632. static void
  1633. miBankCopyWindow(
  1634. WindowPtr pWindow,
  1635. DDXPointRec ptOldOrg,
  1636. RegionPtr pRgnSrc
  1637. )
  1638. {
  1639. ScreenPtr pScreen = pWindow->drawable.pScreen;
  1640. GCPtr pGC;
  1641. int dx, dy, nBox;
  1642. DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum];
  1643. RegionPtr pRgnDst;
  1644. BoxPtr pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2;
  1645. XID subWindowMode = IncludeInferiors;
  1646. pGC = GetScratchGC(pDrawable->depth, pScreen);
  1647. ChangeGC(pGC, GCSubwindowMode, &subWindowMode);
  1648. ValidateGC(pDrawable, pGC);
  1649. pRgnDst = REGION_CREATE(NULL, 1);
  1650. dx = ptOldOrg.x - pWindow->drawable.x;
  1651. dy = ptOldOrg.y - pWindow->drawable.y;
  1652. REGION_TRANSLATE(pRgnSrc, -dx, -dy);
  1653. REGION_INTERSECT(pRgnDst, &pWindow->borderClip, pRgnSrc);
  1654. pBox = REGION_RECTS(pRgnDst);
  1655. nBox = REGION_NUM_RECTS(pRgnDst);
  1656. pBoxNew1 = NULL;
  1657. pBoxNew2 = NULL;
  1658. if (nBox > 1)
  1659. {
  1660. if (dy < 0)
  1661. {
  1662. /* Sort boxes from bottom to top */
  1663. pBoxNew1 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
  1664. if (pBoxNew1)
  1665. {
  1666. pBoxBase = pBoxNext = pBox + nBox - 1;
  1667. while (pBoxBase >= pBox)
  1668. {
  1669. while ((pBoxNext >= pBox) &&
  1670. (pBoxBase->y1 == pBoxNext->y1))
  1671. pBoxNext--;
  1672. pBoxTmp = pBoxNext + 1;
  1673. while (pBoxTmp <= pBoxBase)
  1674. *pBoxNew1++ = *pBoxTmp++;
  1675. pBoxBase = pBoxNext;
  1676. }
  1677. pBoxNew1 -= nBox;
  1678. pBox = pBoxNew1;
  1679. }
  1680. }
  1681. if (dx < 0)
  1682. {
  1683. /* Sort boxes from right to left */
  1684. pBoxNew2 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
  1685. if (pBoxNew2)
  1686. {
  1687. pBoxBase = pBoxNext = pBox;
  1688. while (pBoxBase < pBox + nBox)
  1689. {
  1690. while ((pBoxNext < pBox + nBox) &&
  1691. (pBoxNext->y1 == pBoxBase->y1))
  1692. pBoxNext++;
  1693. pBoxTmp = pBoxNext;
  1694. while (pBoxTmp != pBoxBase)
  1695. *pBoxNew2++ = *--pBoxTmp;
  1696. pBoxBase = pBoxNext;
  1697. }
  1698. pBoxNew2 -= nBox;
  1699. pBox = pBoxNew2;
  1700. }
  1701. }
  1702. }
  1703. while (nBox--)
  1704. {
  1705. (*pGC->ops->CopyArea)(pDrawable, pDrawable, pGC,
  1706. pBox->x1 + dx, pBox->y1 + dy,
  1707. pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
  1708. pBox->x1, pBox->y1);
  1709. pBox++;
  1710. }
  1711. FreeScratchGC(pGC);
  1712. REGION_DESTROY(pRgnDst);
  1713. DEALLOCATE_LOCAL(pBoxNew2);
  1714. DEALLOCATE_LOCAL(pBoxNew1);
  1715. }
  1716. _X_EXPORT Bool
  1717. miInitializeBanking(
  1718. ScreenPtr pScreen,
  1719. unsigned int xsize,
  1720. unsigned int ysize,
  1721. unsigned int width,
  1722. miBankInfoPtr pBankInfo
  1723. )
  1724. {
  1725. miBankScreenPtr pScreenPriv;
  1726. unsigned long nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit;
  1727. unsigned long BankBase, ServerPad;
  1728. unsigned int type, iBank, nBanks, maxRects, we, nBankBPP;
  1729. int i;
  1730. if (!pBankInfo || !pBankInfo->BankSize)
  1731. return TRUE; /* No banking required */
  1732. /* Sanity checks */
  1733. if (!pScreen || !xsize || !ysize || (xsize > width) ||
  1734. !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
  1735. !pBankInfo->SetSourceAndDestinationBanks ||
  1736. !pBankInfo->pBankA || !pBankInfo->pBankB ||
  1737. !pBankInfo->nBankDepth)
  1738. return FALSE;
  1739. /*
  1740. * DDX *must* have registered a pixmap format whose depth is
  1741. * pBankInfo->nBankDepth. This is not necessarily the rootDepth
  1742. * pixmap format.
  1743. */
  1744. i = 0;
  1745. while (screenInfo.formats[i].depth != pBankInfo->nBankDepth)
  1746. if (++i >= screenInfo.numPixmapFormats)
  1747. return FALSE;
  1748. nBankBPP = screenInfo.formats[i].bitsPerPixel;
  1749. i = 0;
  1750. while (screenInfo.formats[i].depth != pScreen->rootDepth)
  1751. if (++i >= screenInfo.numPixmapFormats)
  1752. return FALSE;
  1753. if (nBankBPP > screenInfo.formats[i].bitsPerPixel)
  1754. return FALSE;
  1755. /* Determine banking type */
  1756. if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
  1757. return FALSE;
  1758. /* Internal data */
  1759. nBitsPerBank = pBankInfo->BankSize * 8;
  1760. ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8;
  1761. if (nBitsPerBank % ServerPad)
  1762. return FALSE;
  1763. nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8;
  1764. nBanks = ((nBitsPerScanline * (ysize - 1)) +
  1765. (nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank;
  1766. nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP;
  1767. /* Private areas */
  1768. if (miBankGeneration != serverGeneration)
  1769. {
  1770. if (((miBankScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
  1771. ((miBankGCIndex = AllocateGCPrivateIndex()) < 0))
  1772. return FALSE;
  1773. miBankGeneration = serverGeneration;
  1774. }
  1775. if (!AllocateGCPrivate(pScreen, miBankGCIndex,
  1776. (nBanks * sizeof(RegionPtr)) +
  1777. (sizeof(miBankGCRec) - sizeof(RegionPtr))))
  1778. return FALSE;
  1779. if (!(pScreenPriv = (miBankScreenPtr)calloc(1, sizeof(miBankScreenRec))))
  1780. return FALSE;
  1781. if (!(pScreenPriv->pBanks = /* Allocate and clear */
  1782. (RegionPtr *)calloc(nBanks, sizeof(RegionPtr))))
  1783. {
  1784. free(pScreenPriv);
  1785. return FALSE;
  1786. }
  1787. /*
  1788. * Translate banks into clipping regions which are themselves clipped
  1789. * against the screen. This also ensures that pixels with imbedded bank
  1790. * boundaries are off-screen.
  1791. */
  1792. BankBase = 0;
  1793. maxRects = 0;
  1794. we = 0;
  1795. for (iBank = 0; iBank < nBanks; iBank++)
  1796. {
  1797. xRectangle pRects[3], *pRect = pRects;
  1798. unsigned int xb, yb, xe, ye;
  1799. xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP;
  1800. yb = (BankBase + nBankBPP - 1) / nBitsPerScanline;
  1801. if (xb >= xsize)
  1802. {
  1803. xb = we = 0;
  1804. yb++;
  1805. }
  1806. if (yb >= ysize)
  1807. {
  1808. we = 0;
  1809. break;
  1810. }
  1811. if (we)
  1812. break;
  1813. BankBase += nBitsPerBank;
  1814. we = (BankBase % nBitsPerScanline) % nBankBPP;
  1815. xe = (BankBase % nBitsPerScanline) / nBankBPP;
  1816. ye = BankBase / nBitsPerScanline;
  1817. if (xe >= xsize)
  1818. {
  1819. we = xe = 0;
  1820. ye++;
  1821. }
  1822. if (ye >= ysize)
  1823. {
  1824. we = xe = 0;
  1825. ye = ysize;
  1826. }
  1827. if (yb == ye)
  1828. {
  1829. if (xb >= xe)
  1830. continue;
  1831. pRect->x = xb;
  1832. pRect->y = yb;
  1833. pRect->width = xe - xb;
  1834. pRect->height = 1;
  1835. maxRects += 2;
  1836. pRect++;
  1837. }
  1838. else
  1839. {
  1840. if (xb)
  1841. {
  1842. pRect->x = xb;
  1843. pRect->y = yb++;
  1844. pRect->width = xsize - xb;
  1845. pRect->height = 1;
  1846. maxRects += 2;
  1847. pRect++;
  1848. }
  1849. if (yb < ye)
  1850. {
  1851. pRect->x = 0;
  1852. pRect->y = yb;
  1853. pRect->width = xsize;
  1854. pRect->height = ye - yb;
  1855. maxRects += min(pRect->height, 3) + 1;
  1856. pRect++;
  1857. }
  1858. if (xe)
  1859. {
  1860. pRect->x = 0;
  1861. pRect->y = ye;
  1862. pRect->width = xe;
  1863. pRect->height = 1;
  1864. maxRects += 2;
  1865. pRect++;
  1866. }
  1867. }
  1868. pScreenPriv->pBanks[iBank] =
  1869. RECTS_TO_REGION(pRect - pRects, pRects, 0);
  1870. if (!pScreenPriv->pBanks[iBank] ||
  1871. REGION_NAR(pScreenPriv->pBanks[iBank]))
  1872. {
  1873. we = 1;
  1874. break;
  1875. }
  1876. }
  1877. if (we && (iBank < nBanks))
  1878. {
  1879. for (i = iBank; i >= 0; i--)
  1880. if (pScreenPriv->pBanks[i])
  1881. REGION_DESTROY(pScreenPriv->pBanks[i]);
  1882. free(pScreenPriv->pBanks);
  1883. free(pScreenPriv);
  1884. return FALSE;
  1885. }
  1886. /* Open for business */
  1887. pScreenPriv->type = type;
  1888. pScreenPriv->nBanks = nBanks;
  1889. pScreenPriv->maxRects = maxRects;
  1890. pScreenPriv->nBankBPP = nBankBPP;
  1891. pScreenPriv->BankInfo = *pBankInfo;
  1892. pScreenPriv->nBitsPerBank = nBitsPerBank;
  1893. pScreenPriv->nBitsPerScanline = nBitsPerScanline;
  1894. pScreenPriv->nPixelsPerScanlinePadUnit = nPixelsPerScanlinePadUnit;
  1895. SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
  1896. SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
  1897. SCREEN_WRAP(CloseScreen, miBankCloseScreen);
  1898. SCREEN_WRAP(GetImage, miBankGetImage);
  1899. SCREEN_WRAP(GetSpans, miBankGetSpans);
  1900. SCREEN_WRAP(CreateGC, miBankCreateGC);
  1901. SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
  1902. SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
  1903. SCREEN_WRAP(CopyWindow, miBankCopyWindow);
  1904. BANK_SCRPRIVLVAL = (pointer)pScreenPriv;
  1905. return TRUE;
  1906. }
  1907. /* This is used to force GC revalidation when the banking type is changed */
  1908. /*ARGSUSED*/
  1909. static int
  1910. miBankNewSerialNumber(
  1911. WindowPtr pWin,
  1912. pointer unused
  1913. )
  1914. {
  1915. pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  1916. return WT_WALKCHILDREN;
  1917. }
  1918. /* This entry modifies the banking interface */
  1919. _X_EXPORT Bool
  1920. miModifyBanking(
  1921. ScreenPtr pScreen,
  1922. miBankInfoPtr pBankInfo
  1923. )
  1924. {
  1925. unsigned int type;
  1926. if (!pScreen)
  1927. return FALSE;
  1928. if (miBankGeneration == serverGeneration)
  1929. {
  1930. SCREEN_INIT;
  1931. if (pScreenPriv)
  1932. {
  1933. if (!pBankInfo || !pBankInfo->BankSize ||
  1934. !pBankInfo->pBankA || !pBankInfo->pBankB ||
  1935. !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
  1936. !pBankInfo->SetSourceAndDestinationBanks)
  1937. return FALSE;
  1938. /* BankSize and nBankDepth cannot, as yet, be changed */
  1939. if ((pScreenPriv->BankInfo.BankSize != pBankInfo->BankSize) ||
  1940. (pScreenPriv->BankInfo.nBankDepth != pBankInfo->nBankDepth))
  1941. return FALSE;
  1942. if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
  1943. return FALSE;
  1944. /* Reset banking info */
  1945. pScreenPriv->BankInfo = *pBankInfo;
  1946. if (type != pScreenPriv->type)
  1947. {
  1948. /*
  1949. * Banking type is changing. Revalidate all window GC's.
  1950. */
  1951. pScreenPriv->type = type;
  1952. WalkTree(pScreen, miBankNewSerialNumber, 0);
  1953. }
  1954. return TRUE;
  1955. }
  1956. }
  1957. if (!pBankInfo || !pBankInfo->BankSize)
  1958. return TRUE; /* No change requested */
  1959. return FALSE;
  1960. }
  1961. /*
  1962. * Given various screen attributes, determine the minimum scanline width such
  1963. * that each scanline is server and DDX padded and any pixels with imbedded
  1964. * bank boundaries are off-screen. This function returns -1 if such a width
  1965. * cannot exist. This function exists because the DDX needs to be able to
  1966. * determine this width before initializing a frame buffer.
  1967. */
  1968. int
  1969. miScanLineWidth(
  1970. unsigned int xsize, /* pixels */
  1971. unsigned int ysize, /* pixels */
  1972. unsigned int width, /* pixels */
  1973. unsigned long BankSize, /* char's */
  1974. PixmapFormatRec *pBankFormat,
  1975. unsigned int nWidthUnit /* bits */
  1976. )
  1977. {
  1978. unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
  1979. unsigned long minBitsPerScanline, maxBitsPerScanline;
  1980. /* Sanity checks */
  1981. if (!nWidthUnit || !pBankFormat)
  1982. return -1;
  1983. nBitsPerBank = BankSize * 8;
  1984. if (nBitsPerBank % pBankFormat->scanlinePad)
  1985. return -1;
  1986. if (xsize > width)
  1987. width = xsize;
  1988. nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit);
  1989. nBitsPerScanline =
  1990. (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
  1991. nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
  1992. width = nBitsPerScanline / pBankFormat->bitsPerPixel;
  1993. if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
  1994. return (int)width;
  1995. /*
  1996. * Scanlines will be server-pad aligned at this point. They will also be
  1997. * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
  1998. * bank boundaries are off-screen.
  1999. *
  2000. * It seems reasonable to limit total frame buffer size to 1/16 of the
  2001. * theoretical maximum address space size. On a machine with 32-bit
  2002. * addresses (to 8-bit quantities) this turns out to be 256MB. Not only
  2003. * does this provide a simple limiting condition for the loops below, but
  2004. * it also prevents unsigned long wraparounds.
  2005. */
  2006. if (!ysize)
  2007. return -1;
  2008. minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
  2009. if (minBitsPerScanline > nBitsPerBank)
  2010. return -1;
  2011. if (ysize == 1)
  2012. return (int)width;
  2013. maxBitsPerScanline =
  2014. (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
  2015. while (nBitsPerScanline <= maxBitsPerScanline)
  2016. {
  2017. unsigned long BankBase, BankUnit;
  2018. BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
  2019. nBitsPerBank;
  2020. if (!(BankUnit % nBitsPerScanline))
  2021. return (int)width;
  2022. for (BankBase = BankUnit; ; BankBase += nBitsPerBank)
  2023. {
  2024. unsigned long x, y;
  2025. y = BankBase / nBitsPerScanline;
  2026. if (y >= ysize)
  2027. return (int)width;
  2028. x = BankBase % nBitsPerScanline;
  2029. if (!(x % pBankFormat->bitsPerPixel))
  2030. continue;
  2031. if (x < minBitsPerScanline)
  2032. {
  2033. /*
  2034. * Skip ahead certain widths by dividing the excess scanline
  2035. * amongst the y's.
  2036. */
  2037. y *= nBitsPerScanlinePadUnit;
  2038. nBitsPerScanline +=
  2039. ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
  2040. width = nBitsPerScanline / pBankFormat->bitsPerPixel;
  2041. break;
  2042. }
  2043. if (BankBase != BankUnit)
  2044. continue;
  2045. if (!(nBitsPerScanline % x))
  2046. return (int)width;
  2047. BankBase = ((nBitsPerScanline - minBitsPerScanline) /
  2048. (nBitsPerScanline - x)) * BankUnit;
  2049. }
  2050. }
  2051. return -1;
  2052. }