12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456 |
- /*
- * Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of Marc Aurele La France not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. Marc Aurele La France makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as-is" without express or implied warranty.
- *
- * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
- * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /*
- * Copyright 1990,91,92,93 by Thomas Roell, Germany.
- * Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
- *
- * Permission to use, copy, modify, distribute, and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation, and that the name of Thomas Roell nor
- * SGCS be used in advertising or publicity pertaining to distribution
- * of the software without specific, written prior permission.
- * Thomas Roell nor SGCS makes no representations about the suitability
- * of this software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- * THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /*
- * This thing originated from an idea of Edwin Goei and his bank switching
- * code for the DEC TX board.
- */
- /*
- * Heavily modified for the XFree86 Project to turn this into an mi wrapper.
- * --- Marc Aurele La France (tsi@xfree86.org)
- */
- /*
- * "Heavily modified", indeed! By the time this is finalized, there probably
- * won't be much left of Roell's code...
- *
- * Miscellaneous notes:
- * - Pixels with imbedded bank boundaries are required to be off-screen. There
- * >might< be a way to fool the underlying framebuffer into dealing with
- * partial pixels.
- * - Plans to generalise this to do (hardware) colour plane switching have been
- * dropped due to colour flashing concerns.
- *
- * TODO:
- * - Allow miModifyBanking() to change BankSize and nBankDepth.
- * - Re-instate shared and double banking for framebuffers whose pixmap formats
- * don't describe how the server "sees" the screen.
- * - Remove remaining assumptions that a pixmap's devPrivate field points
- * directly to its pixel data.
- */
- /* #define NO_ALLOCA 1 */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "servermd.h"
- #include "gcstruct.h"
- #include "pixmapstr.h"
- #include "scrnintstr.h"
- #include "windowstr.h"
- #include "mi.h"
- #include "mibank.h"
- #define BANK_SINGLE 0
- #define BANK_SHARED 1
- #define BANK_DOUBLE 2
- #define BANK_NOBANK 3
- typedef struct _miBankScreen
- {
- miBankInfoRec BankInfo;
- unsigned int nBankBPP;
- unsigned int type;
- unsigned long nBitsPerBank;
- unsigned long nBitsPerScanline;
- unsigned long nPixelsPerScanlinePadUnit;
- PixmapPtr pScreenPixmap;
- PixmapPtr pBankPixmap;
- GCPtr pBankGC;
- int nBanks, maxRects;
- RegionPtr *pBanks;
- pointer pbits;
- /*
- * Screen Wrappers
- */
- CreateScreenResourcesProcPtr CreateScreenResources;
- ModifyPixmapHeaderProcPtr ModifyPixmapHeader;
- CloseScreenProcPtr CloseScreen;
- GetImageProcPtr GetImage;
- GetSpansProcPtr GetSpans;
- CreateGCProcPtr CreateGC;
- PaintWindowBackgroundProcPtr PaintWindowBackground;
- PaintWindowBorderProcPtr PaintWindowBorder;
- CopyWindowProcPtr CopyWindow;
- } miBankScreenRec, *miBankScreenPtr;
- typedef struct _miBankGC
- {
- GCOps *wrappedOps, *unwrappedOps;
- const GCFuncs *wrappedFuncs, *unwrappedFuncs;
- Bool fastCopy, fastPlane;
- RegionPtr pBankedClips[1];
- } miBankGCRec, *miBankGCPtr;
- typedef struct _miBankQueue
- {
- Bool fastBlit;
- unsigned short srcBankNo;
- unsigned short dstBankNo;
- short x;
- short y;
- short w;
- short h;
- } miBankQueue;
- /*
- * CAVEAT: This banking scheme requires that the DDX store Pixmap data in the
- * server's address space.
- */
- #define ModifyPixmap(_pPix, _width, _devKind, _pbits) \
- (*pScreen->ModifyPixmapHeader)((_pPix), \
- (_width), -1, -1, -1, (_devKind), (_pbits))
- #define SET_SINGLE_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankA + \
- (*pScreenPriv->BankInfo.SetSourceAndDestinationBanks)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
- #define SET_SOURCE_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankA + \
- (*pScreenPriv->BankInfo.SetSourceBank)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
- #define SET_DESTINATION_BANK(_pPix, _width, _devKind, _no) \
- ModifyPixmap(_pPix, _width, _devKind, \
- (char *)pScreenPriv->BankInfo.pBankB + \
- (*pScreenPriv->BankInfo.SetDestinationBank)(pScreen, (_no)) - \
- (pScreenPriv->BankInfo.BankSize * (_no)))
- #define ALLOCATE_LOCAL_ARRAY(atype, ntype) \
- (atype *)ALLOCATE_LOCAL((ntype) * sizeof(atype))
- static int miBankScreenIndex;
- static int miBankGCIndex;
- static unsigned long miBankGeneration = 0;
- #define BANK_SCRPRIVLVAL pScreen->devPrivates[miBankScreenIndex].ptr
- #define BANK_SCRPRIVATE ((miBankScreenPtr)(BANK_SCRPRIVLVAL))
- #define BANK_GCPRIVLVAL(pGC) (pGC)->devPrivates[miBankGCIndex].ptr
- #define BANK_GCPRIVATE(pGC) ((miBankGCPtr)(BANK_GCPRIVLVAL(pGC)))
- #define PIXMAP_STATUS(_pPix) \
- pointer pbits = (_pPix)->devPrivate.ptr
- #define PIXMAP_SAVE(_pPix) \
- PIXMAP_STATUS(_pPix); \
- if (pbits == (pointer)pScreenPriv) \
- (_pPix)->devPrivate.ptr = pScreenPriv->pbits
- #define PIXMAP_RESTORE(_pPix) \
- (_pPix)->devPrivate.ptr = pbits
- #define BANK_SAVE \
- int width = pScreenPriv->pBankPixmap->drawable.width; \
- int devKind = pScreenPriv->pBankPixmap->devKind; \
- PIXMAP_SAVE(pScreenPriv->pBankPixmap)
- #define BANK_RESTORE \
- pScreenPriv->pBankPixmap->drawable.width = width; \
- pScreenPriv->pBankPixmap->devKind = devKind; \
- PIXMAP_RESTORE(pScreenPriv->pBankPixmap)
- #define SCREEN_STATUS \
- PIXMAP_STATUS(pScreenPriv->pScreenPixmap)
- #define SCREEN_SAVE \
- PIXMAP_SAVE(pScreenPriv->pScreenPixmap)
- #define SCREEN_RESTORE \
- PIXMAP_RESTORE(pScreenPriv->pScreenPixmap)
- #define SCREEN_INIT \
- miBankScreenPtr pScreenPriv = BANK_SCRPRIVATE
- #define SCREEN_UNWRAP(field) \
- pScreen->field = pScreenPriv->field
- #define SCREEN_WRAP(field, wrapper) \
- pScreenPriv->field = pScreen->field; \
- pScreen->field = wrapper
- #define GC_INIT(pGC) \
- miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC)
- #define GC_UNWRAP(pGC) \
- pGCPriv->unwrappedOps = (pGC)->ops; \
- pGCPriv->unwrappedFuncs = (pGC)->funcs; \
- (pGC)->ops = pGCPriv->wrappedOps; \
- (pGC)->funcs = pGCPriv->wrappedFuncs
- #define GC_WRAP(pGC) \
- pGCPriv->wrappedOps = (pGC)->ops; \
- pGCPriv->wrappedFuncs = (pGC)->funcs; \
- (pGC)->ops = pGCPriv->unwrappedOps; \
- (pGC)->funcs = pGCPriv->unwrappedFuncs
- #define IS_BANKED(pDrawable) \
- ((pbits == (pointer)pScreenPriv) && \
- (((DrawablePtr)(pDrawable))->type == DRAWABLE_WINDOW))
- #define CLIP_SAVE \
- RegionPtr pOrigCompositeClip = pGC->pCompositeClip
- #define CLIP_RESTORE \
- pGC->pCompositeClip = pOrigCompositeClip
- #define GCOP_INIT \
- ScreenPtr pScreen = pGC->pScreen; \
- SCREEN_INIT; \
- GC_INIT(pGC)
- #define GCOP_UNWRAP \
- GC_UNWRAP(pGC)
- #define GCOP_WRAP \
- GC_WRAP(pGC)
- #define GCOP_TOP_PART \
- for (i = 0; i < pScreenPriv->nBanks; i++) \
- { \
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i])) \
- continue; \
- GCOP_UNWRAP; \
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i)
- #define GCOP_BOTTOM_PART \
- GCOP_WRAP; \
- }
- #define GCOP_SIMPLE(statement) \
- if (nArray > 0) \
- { \
- GCOP_INIT; \
- SCREEN_SAVE; \
- if (!IS_BANKED(pDrawable)) \
- { \
- GCOP_UNWRAP; \
- statement; \
- GCOP_WRAP; \
- } \
- else \
- { \
- int i; \
- CLIP_SAVE; \
- GCOP_TOP_PART; \
- statement; \
- GCOP_BOTTOM_PART; \
- CLIP_RESTORE; \
- } \
- SCREEN_RESTORE; \
- }
- #define GCOP_0D_ARGS mode,
- #define GCOP_1D_ARGS
- #define GCOP_2D_ARGS shape, mode,
- #define GCOP_COMPLEX(aop, atype) \
- if (nArray > 0) \
- { \
- GCOP_INIT; \
- SCREEN_SAVE; \
- if (!IS_BANKED(pDrawable)) \
- { \
- GCOP_UNWRAP; \
- (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, pArray); \
- GCOP_WRAP; \
- } \
- else \
- { \
- atype *aarg = pArray, *acopy; \
- int i; \
- CLIP_SAVE; \
- if ((acopy = ALLOCATE_LOCAL_ARRAY(atype, nArray))) \
- aarg = acopy; \
- GCOP_TOP_PART; \
- if (acopy) \
- memcpy(acopy, pArray, nArray * sizeof(atype)); \
- (*pGC->ops->aop)(pDrawable, pGC, GCOP_ARGS nArray, aarg); \
- GCOP_BOTTOM_PART; \
- DEALLOCATE_LOCAL(acopy); \
- CLIP_RESTORE; \
- } \
- SCREEN_RESTORE; \
- }
- /*********************
- * Utility functions *
- *********************/
- static int
- miBankOf(
- miBankScreenPtr pScreenPriv,
- int x,
- int y
- )
- {
- int iBank = ((x * (int)pScreenPriv->nBankBPP) +
- (y * (long)pScreenPriv->nBitsPerScanline)) /
- (long)pScreenPriv->nBitsPerBank;
- if (iBank < 0)
- iBank = 0;
- else if (iBank >= pScreenPriv->nBanks)
- iBank = pScreenPriv->nBanks - 1;
- return iBank;
- }
- #define FirstBankOf(_x, _y) miBankOf(pScreenPriv, (_x), (_y))
- #define LastBankOf(_x, _y) miBankOf(pScreenPriv, (_x) - 1, (_y))
- /* Determine banking type from the BankInfoRec */
- static unsigned int
- miBankDeriveType(
- ScreenPtr pScreen,
- miBankInfoPtr pBankInfo
- )
- {
- unsigned int type;
- if (pBankInfo->pBankA == pBankInfo->pBankB)
- {
- if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
- {
- if (pBankInfo->SetSourceAndDestinationBanks !=
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
- type = BANK_SINGLE;
- }
- else
- {
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetDestinationBank)
- return BANK_NOBANK;
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
- type = BANK_SHARED;
- }
- }
- else
- {
- if ((unsigned long)abs((char *)pBankInfo->pBankA -
- (char *)pBankInfo->pBankB) < pBankInfo->BankSize)
- return BANK_NOBANK;
- if (pBankInfo->SetSourceBank == pBankInfo->SetDestinationBank)
- {
- if (pBankInfo->SetSourceAndDestinationBanks !=
- pBankInfo->SetSourceBank)
- return BANK_NOBANK;
- }
- else
- {
- if (pBankInfo->SetSourceAndDestinationBanks ==
- pBankInfo->SetDestinationBank)
- return BANK_NOBANK;
- }
- type = BANK_DOUBLE;
- }
- /*
- * Internal limitation: Currently, only single banking is supported when
- * the pixmap format and the screen's pixel format are different. The
- * following test is only partially successful at detecting this condition.
- */
- if (pBankInfo->nBankDepth != pScreen->rootDepth)
- type = BANK_SINGLE;
- return type;
- }
- /* Least common multiple */
- static unsigned int
- miLCM(
- unsigned int x,
- unsigned int y
- )
- {
- unsigned int m = x, n = y, o;
- while ((o = m % n))
- {
- m = n;
- n = o;
- }
- return (x / n) * y;
- }
- /******************
- * GCOps wrappers *
- ******************/
- static void
- miBankFillSpans(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- DDXPointPtr pptInit,
- int *pwidthInit,
- int fSorted
- )
- {
- GCOP_SIMPLE((*pGC->ops->FillSpans)(pDrawable, pGC,
- nArray, pptInit, pwidthInit, fSorted));
- }
- static void
- miBankSetSpans(
- DrawablePtr pDrawable,
- GCPtr pGC,
- char *psrc,
- DDXPointPtr ppt,
- int *pwidth,
- int nArray,
- int fSorted
- )
- {
- GCOP_SIMPLE((*pGC->ops->SetSpans)(pDrawable, pGC, psrc,
- ppt, pwidth, nArray, fSorted));
- }
- static void
- miBankPutImage(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int depth,
- int x,
- int y,
- int w,
- int h,
- int leftPad,
- int format,
- char *pImage
- )
- {
- if ((w > 0) && (h > 0))
- {
- GCOP_INIT;
- SCREEN_SAVE;
- if (!IS_BANKED(pDrawable))
- {
- GCOP_UNWRAP;
- (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
- GCOP_WRAP;
- }
- else
- {
- int i, j;
- CLIP_SAVE;
- i = FirstBankOf(x + pDrawable->x, y + pDrawable->y);
- j = LastBankOf(x + pDrawable->x + w, y + pDrawable->y + h);
- for (; i <= j; i++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
- continue;
- GCOP_UNWRAP;
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
- (*pGC->ops->PutImage)(pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pImage);
- GCOP_WRAP;
- }
- CLIP_RESTORE;
- }
- SCREEN_RESTORE;
- }
- }
- /*
- * Here the CopyArea/CopyPlane wrappers. First off, we have to clip against
- * the source in order to make the minimal number of copies in case of slow
- * systems. Also the exposure handling is quite tricky. Special attention
- * is to be given to the way the copies are sequenced. The list of boxes after
- * the source clip is used to build a workqueue, that contains the atomic
- * copies (i.e. only from one bank to one bank). Doing so produces a minimal
- * list of things to do.
- */
- static RegionPtr
- miBankCopy(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty,
- unsigned long plane,
- Bool SinglePlane
- )
- {
- int cx1, cy1, cx2, cy2;
- int ns, nd, nse, nde, dx, dy, xorg = 0, yorg = 0;
- int maxWidth = 0, maxHeight = 0, paddedWidth = 0;
- int nBox, nBoxClipSrc, nBoxClipDst, nQueue;
- BoxPtr pBox, pBoxClipSrc, pBoxClipDst;
- BoxRec fastBox, ccBox;
- RegionPtr ret = NULL, prgnSrcClip = NULL;
- RegionRec rgnDst;
- char *pImage = NULL;
- miBankQueue *pQueue, *pQueueNew, *Queue;
- miBankQueue *pQueueTmp, *pQueueNext, *pQueueBase;
- Bool fastBlit, freeSrcClip, fastClip;
- Bool fExpose = FALSE, fastExpose = FALSE;
- GCOP_INIT;
- SCREEN_SAVE;
- if (!IS_BANKED(pSrc) && !IS_BANKED(pDst))
- {
- GCOP_UNWRAP;
- if (SinglePlane)
- ret = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- srcx, srcy, w, h, dstx, dsty, plane);
- else
- ret = (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- srcx, srcy, w, h, dstx, dsty);
- GCOP_WRAP;
- }
- else if (!IS_BANKED(pDst))
- {
- fExpose = pGC->fExpose;
- pGC->fExpose = FALSE;
- xorg = pSrc->x;
- yorg = pSrc->y;
- dx = dstx - srcx;
- dy = dsty - srcy;
- srcx += xorg;
- srcy += yorg;
- ns = FirstBankOf(srcx, srcy);
- nse = LastBankOf(srcx + w, srcy + h);
- for (; ns <= nse; ns++)
- {
- if (!pScreenPriv->pBanks[ns])
- continue;
- nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
- pBox = REGION_RECTS(pScreenPriv->pBanks[ns]);
- for (; nBox--; pBox++)
- {
- cx1 = max(pBox->x1, srcx);
- cy1 = max(pBox->y1, srcy);
- cx2 = min(pBox->x2, srcx + w);
- cy2 = min(pBox->y2, srcy + h);
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
- GCOP_UNWRAP;
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, ns);
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- cx1 - xorg, cy1 - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 + dx - xorg, cy1 + dy - yorg, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- cx1 - xorg, cy1 - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 + dx - xorg, cy1 + dy - yorg);
- GCOP_WRAP;
- }
- }
- pGC->fExpose = fExpose;
- srcx -= xorg;
- srcy -= yorg;
- }
- else if (!IS_BANKED(pSrc))
- {
- CLIP_SAVE;
- if (pGC->miTranslate)
- {
- xorg = pDst->x;
- yorg = pDst->y;
- }
- dx = srcx - dstx;
- dy = srcy - dsty;
- dstx += xorg;
- dsty += yorg;
- nd = FirstBankOf(dstx, dsty);
- nde = LastBankOf(dstx + w, dsty + h);
- for (; nd <= nde; nd++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[nd]))
- continue;
- /*
- * It's faster to let the lower-level CopyArea do the clipping
- * within each bank.
- */
- nBox = REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
- pBox = REGION_RECTS(pScreenPriv->pBanks[nd]);
- for (; nBox--; pBox++)
- {
- cx1 = max(pBox->x1, dstx);
- cy1 = max(pBox->y1, dsty);
- cx2 = min(pBox->x2, dstx + w);
- cy2 = min(pBox->y2, dsty + h);
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
- GCOP_UNWRAP;
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, nd);
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- cx1 + dx - xorg, cy1 + dy - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 - xorg, cy1 - yorg, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- cx1 + dx - xorg, cy1 + dy - yorg,
- cx2 - cx1, cy2 - cy1,
- cx1 - xorg, cy1 - yorg);
- GCOP_WRAP;
- }
- }
- CLIP_RESTORE;
- }
- else /* IS_BANKED(pSrc) && IS_BANKED(pDst) */
- {
- CLIP_SAVE;
- fExpose = pGC->fExpose;
- fastBox.x1 = srcx + pSrc->x;
- fastBox.y1 = srcy + pSrc->y;
- fastBox.x2 = fastBox.x1 + w;
- fastBox.y2 = fastBox.y1 + h;
- dx = dstx - fastBox.x1;
- dy = dsty - fastBox.y1;
- if (pGC->miTranslate)
- {
- xorg = pDst->x;
- yorg = pDst->y;
- }
- /*
- * Clip against the source. Otherwise we will blit too much for SINGLE
- * and SHARED banked systems.
- */
- freeSrcClip = FALSE;
- fastClip = FALSE;
- fastExpose = FALSE;
- if (pGC->subWindowMode != IncludeInferiors)
- prgnSrcClip = &((WindowPtr)pSrc)->clipList;
- else if (!((WindowPtr)pSrc)->parent)
- fastClip = TRUE;
- else if ((pSrc == pDst) && (pGC->clientClipType == CT_NONE))
- prgnSrcClip = pGC->pCompositeClip;
- else
- {
- prgnSrcClip = NotClippedByChildren((WindowPtr)pSrc);
- freeSrcClip = TRUE;
- }
- if (fastClip)
- {
- fastExpose = TRUE;
- /*
- * Clip the source. If regions extend beyond the source size, make
- * sure exposure events get sent.
- */
- if (fastBox.x1 < pSrc->x)
- {
- fastBox.x1 = pSrc->x;
- fastExpose = FALSE;
- }
- if (fastBox.y1 < pSrc->y)
- {
- fastBox.y1 = pSrc->y;
- fastExpose = FALSE;
- }
- if (fastBox.x2 > pSrc->x + (int) pSrc->width)
- {
- fastBox.x2 = pSrc->x + (int) pSrc->width;
- fastExpose = FALSE;
- }
- if (fastBox.y2 > pSrc->y + (int) pSrc->height)
- {
- fastBox.y2 = pSrc->y + (int) pSrc->height;
- fastExpose = FALSE;
- }
- nBox = 1;
- pBox = &fastBox;
- }
- else
- {
- REGION_INIT(&rgnDst, &fastBox, 1);
- REGION_INTERSECT(&rgnDst, &rgnDst, prgnSrcClip);
- pBox = REGION_RECTS(&rgnDst);
- nBox = REGION_NUM_RECTS(&rgnDst);
- }
- /*
- * fastBlit can only be TRUE if we don't need to worry about attempts
- * to read partial pixels through the destination bank.
- */
- if (SinglePlane)
- fastBlit = pGCPriv->fastPlane;
- else
- fastBlit = pGCPriv->fastCopy;
- nQueue = nBox * pScreenPriv->maxRects * 2;
- pQueue = Queue = ALLOCATE_LOCAL_ARRAY(miBankQueue, nQueue);
- if (Queue)
- {
- for (; nBox--; pBox++)
- {
- ns = FirstBankOf(pBox->x1, pBox->y1);
- nse = LastBankOf(pBox->x2, pBox->y2);
- for (; ns <= nse; ns++)
- {
- if (!pScreenPriv->pBanks[ns])
- continue;
- nBoxClipSrc = REGION_NUM_RECTS(pScreenPriv->pBanks[ns]);
- pBoxClipSrc = REGION_RECTS(pScreenPriv->pBanks[ns]);
- for (; nBoxClipSrc--; pBoxClipSrc++)
- {
- cx1 = max(pBox->x1, pBoxClipSrc->x1);
- cy1 = max(pBox->y1, pBoxClipSrc->y1);
- cx2 = min(pBox->x2, pBoxClipSrc->x2);
- cy2 = min(pBox->y2, pBoxClipSrc->y2);
- /* Check to see if the region is empty */
- if ((cx1 >= cx2) || (cy1 >= cy2))
- continue;
- /* Translate c[xy]* to destination coordinates */
- cx1 += dx + xorg;
- cy1 += dy + yorg;
- cx2 += dx + xorg;
- cy2 += dy + yorg;
- nd = FirstBankOf(cx1, cy1);
- nde = LastBankOf(cx2, cy2);
- for (; nd <= nde; nd++)
- {
- if (!pGCPriv->pBankedClips[nd])
- continue;
- /*
- * Clients can send quite large clip descriptions,
- * so use the bank clips here instead.
- */
- nBoxClipDst =
- REGION_NUM_RECTS(pScreenPriv->pBanks[nd]);
- pBoxClipDst =
- REGION_RECTS(pScreenPriv->pBanks[nd]);
- for (; nBoxClipDst--; pBoxClipDst++)
- {
- ccBox.x1 = max(cx1, pBoxClipDst->x1);
- ccBox.y1 = max(cy1, pBoxClipDst->y1);
- ccBox.x2 = min(cx2, pBoxClipDst->x2);
- ccBox.y2 = min(cy2, pBoxClipDst->y2);
- /* Check to see if the region is empty */
- if ((ccBox.x1 >= ccBox.x2) ||
- (ccBox.y1 >= ccBox.y2))
- continue;
- pQueue->srcBankNo = ns;
- pQueue->dstBankNo = nd;
- pQueue->x = ccBox.x1 - xorg;
- pQueue->y = ccBox.y1 - yorg;
- pQueue->w = ccBox.x2 - ccBox.x1;
- pQueue->h = ccBox.y2 - ccBox.y1;
- if (maxWidth < pQueue->w)
- maxWidth = pQueue->w;
- if (maxHeight < pQueue->h)
- maxHeight = pQueue->h;
- /*
- * When shared banking is used and the source
- * and destination banks differ, prevent
- * attempts to fetch partial scanline pad units
- * through the destination bank.
- */
- pQueue->fastBlit = fastBlit;
- if (fastBlit &&
- (pScreenPriv->type == BANK_SHARED) &&
- (ns != nd) &&
- ((ccBox.x1 %
- pScreenPriv->nPixelsPerScanlinePadUnit) ||
- (ccBox.x2 %
- pScreenPriv->nPixelsPerScanlinePadUnit) ||
- (RECT_IN_REGION(
- pGCPriv->pBankedClips[nd], &ccBox) !=
- rgnIN)))
- pQueue->fastBlit = FALSE;
- pQueue++;
- }
- }
- }
- }
- }
- }
- if (!fastClip)
- {
- REGION_UNINIT(&rgnDst);
- if (freeSrcClip)
- REGION_DESTROY(prgnSrcClip);
- }
- pQueueNew = pQueue;
- nQueue = pQueue - Queue;
- if (nQueue > 0)
- {
- BANK_SAVE;
- pQueue = Queue;
- if ((nQueue > 1) &&
- ((pSrc == pDst) || (pGC->subWindowMode == IncludeInferiors)))
- {
- if ((srcy + pSrc->y) < (dsty + yorg))
- {
- /* Sort from bottom to top */
- pQueueBase = pQueueNext = pQueue + nQueue - 1;
- while (pQueueBase >= pQueue)
- {
- while ((pQueueNext >= pQueue) &&
- (pQueueBase->y == pQueueNext->y))
- pQueueNext--;
- pQueueTmp = pQueueNext + 1;
- while (pQueueTmp <= pQueueBase)
- *pQueueNew++ = *pQueueTmp++;
- pQueueBase = pQueueNext;
- }
- pQueueNew -= nQueue;
- pQueue = pQueueNew;
- pQueueNew = Queue;
- }
- if ((srcx + pSrc->x) < (dstx + xorg))
- {
- /* Sort from right to left */
- pQueueBase = pQueueNext = pQueue;
- while (pQueueBase < pQueue + nQueue)
- {
- while ((pQueueNext < pQueue + nQueue) &&
- (pQueueNext->y == pQueueBase->y))
- pQueueNext++;
- pQueueTmp = pQueueNext;
- while (pQueueTmp != pQueueBase)
- *pQueueNew++ = *--pQueueTmp;
- pQueueBase = pQueueNext;
- }
- pQueueNew -= nQueue;
- pQueue = pQueueNew;
- }
- }
- paddedWidth = PixmapBytePad(maxWidth,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pImage = (char *)ALLOCATE_LOCAL(paddedWidth * maxHeight);
- pGC->fExpose = FALSE;
- while (nQueue--)
- {
- pGC->pCompositeClip = pGCPriv->pBankedClips[pQueue->dstBankNo];
- GCOP_UNWRAP;
- if (pQueue->srcBankNo == pQueue->dstBankNo)
- {
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->srcBankNo);
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(pSrc, pDst, pGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y);
- }
- else if (pQueue->fastBlit)
- {
- SET_SOURCE_BANK (pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->devKind,
- pQueue->srcBankNo);
- SET_DESTINATION_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->dstBankNo);
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(
- (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
- pQueue->x - dx, pQueue->y - dy,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(
- (DrawablePtr)pScreenPriv->pBankPixmap, pDst, pGC,
- pQueue->x - dx, pQueue->y - dy,
- pQueue->w, pQueue->h, pQueue->x, pQueue->y);
- }
- else if (pImage)
- {
- ModifyPixmap(pScreenPriv->pBankPixmap,
- maxWidth, paddedWidth, pImage);
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->srcBankNo);
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- pSrc, (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- pQueue->x - dx - pSrc->x, pQueue->y - dy - pSrc->y,
- pQueue->w, pQueue->h, 0, 0);
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap,
- -1, -1, pQueue->dstBankNo);
- if (SinglePlane)
- (*pGC->ops->CopyPlane)(
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pDst, pGC, 0, 0, pQueue->w, pQueue->h,
- pQueue->x, pQueue->y, plane);
- else
- (*pGC->ops->CopyArea)(
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pDst, pGC, 0, 0, pQueue->w, pQueue->h,
- pQueue->x, pQueue->y);
- }
- GCOP_WRAP;
- pQueue++;
- }
- DEALLOCATE_LOCAL(pImage);
- BANK_RESTORE;
- }
- CLIP_RESTORE;
- pGC->fExpose = fExpose;
- DEALLOCATE_LOCAL(Queue);
- }
- SCREEN_RESTORE;
- if (!fExpose || fastExpose)
- return ret;
- return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0);
- }
- static RegionPtr
- miBankCopyArea(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty
- )
- {
- return miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, 0, FALSE);
- }
- static RegionPtr
- miBankCopyPlane(
- DrawablePtr pSrc,
- DrawablePtr pDst,
- GCPtr pGC,
- int srcx,
- int srcy,
- int w,
- int h,
- int dstx,
- int dsty,
- unsigned long plane
- )
- {
- return
- miBankCopy(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane, TRUE);
- }
- static void
- miBankPolyPoint(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int nArray,
- xPoint *pArray
- )
- {
- # define GCOP_ARGS GCOP_0D_ARGS
- GCOP_COMPLEX(PolyPoint, xPoint);
- # undef GCOP_ARGS
- }
- static void
- miBankPolylines(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int mode,
- int nArray,
- DDXPointPtr pArray
- )
- {
- # define GCOP_ARGS GCOP_0D_ARGS
- GCOP_COMPLEX(Polylines, DDXPointRec);
- # undef GCOP_ARGS
- }
- static void
- miBankPolySegment(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xSegment *pArray
- )
- {
- # define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolySegment, xSegment);
- # undef GCOP_ARGS
- }
- static void
- miBankPolyRectangle(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xRectangle *pArray
- )
- {
- # define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyRectangle, xRectangle);
- # undef GCOP_ARGS
- }
- static void
- miBankPolyArc(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xArc *pArray
- )
- {
- # define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyArc, xArc);
- # undef GCOP_ARGS
- }
- static void
- miBankFillPolygon(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int shape,
- int mode,
- int nArray,
- DDXPointRec *pArray
- )
- {
- # define GCOP_ARGS GCOP_2D_ARGS
- GCOP_COMPLEX(FillPolygon, DDXPointRec);
- # undef GCOP_ARGS
- }
- static void
- miBankPolyFillRect(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xRectangle *pArray
- )
- {
- # define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyFillRect, xRectangle);
- # undef GCOP_ARGS
- }
- static void
- miBankPolyFillArc(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int nArray,
- xArc *pArray
- )
- {
- # define GCOP_ARGS GCOP_1D_ARGS
- GCOP_COMPLEX(PolyFillArc, xArc);
- # undef GCOP_ARGS
- }
- static int
- miBankPolyText8(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- char *pchar
- )
- {
- int retval = x;
- GCOP_SIMPLE(retval =
- (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, nArray, pchar));
- return retval;
- }
- static int
- miBankPolyText16(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- unsigned short *pchar
- )
- {
- int retval = x;
- GCOP_SIMPLE(retval =
- (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, nArray, pchar));
- return retval;
- }
- static void
- miBankImageText8(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- char *pchar
- )
- {
- GCOP_SIMPLE((*pGC->ops->ImageText8)(pDrawable, pGC, x, y, nArray, pchar));
- }
- static void
- miBankImageText16(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- int nArray,
- unsigned short *pchar
- )
- {
- GCOP_SIMPLE((*pGC->ops->ImageText16)(pDrawable, pGC, x, y, nArray, pchar));
- }
- static void
- miBankImageGlyphBlt(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nArray,
- CharInfoPtr *ppci,
- pointer pglyphBase
- )
- {
- GCOP_SIMPLE((*pGC->ops->ImageGlyphBlt)(pDrawable, pGC,
- x, y, nArray, ppci, pglyphBase));
- }
- static void
- miBankPolyGlyphBlt(
- DrawablePtr pDrawable,
- GCPtr pGC,
- int x,
- int y,
- unsigned int nArray,
- CharInfoPtr *ppci,
- pointer pglyphBase
- )
- {
- GCOP_SIMPLE((*pGC->ops->PolyGlyphBlt)(pDrawable, pGC,
- x, y, nArray, ppci, pglyphBase));
- }
- static void
- miBankPushPixels(
- GCPtr pGC,
- PixmapPtr pBitmap,
- DrawablePtr pDrawable,
- int w,
- int h,
- int x,
- int y
- )
- {
- if ((w > 0) && (h > 0))
- {
- GCOP_INIT;
- SCREEN_SAVE;
- if (!IS_BANKED(pDrawable))
- {
- GCOP_UNWRAP;
- (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
- GCOP_WRAP;
- }
- else
- {
- int i, j;
- CLIP_SAVE;
- i = FirstBankOf(x, y);
- j = LastBankOf(x + w, y + h);
- for (; i <= j; i++)
- {
- if (!(pGC->pCompositeClip = pGCPriv->pBankedClips[i]))
- continue;
- GCOP_UNWRAP;
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
- (*pGC->ops->PushPixels)(pGC, pBitmap, pDrawable, w, h, x, y);
- GCOP_WRAP;
- }
- CLIP_RESTORE;
- }
- SCREEN_RESTORE;
- }
- }
- static GCOps miBankGCOps =
- {
- miBankFillSpans,
- miBankSetSpans,
- miBankPutImage,
- miBankCopyArea,
- miBankCopyPlane,
- miBankPolyPoint,
- miBankPolylines,
- miBankPolySegment,
- miBankPolyRectangle,
- miBankPolyArc,
- miBankFillPolygon,
- miBankPolyFillRect,
- miBankPolyFillArc,
- miBankPolyText8,
- miBankPolyText16,
- miBankImageText8,
- miBankImageText16,
- miBankImageGlyphBlt,
- miBankPolyGlyphBlt,
- miBankPushPixels,
- {NULL} /* devPrivate */
- };
- /********************
- * GCFuncs wrappers *
- ********************/
- static void
- miBankValidateGC(
- GCPtr pGC,
- unsigned long changes,
- DrawablePtr pDrawable
- )
- {
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
- (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
- if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
- (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)))
- {
- ScreenPtr pScreen = pGC->pScreen;
- RegionPtr prgnClip;
- unsigned long planemask;
- int i;
- SCREEN_INIT;
- SCREEN_SAVE;
- if (IS_BANKED(pDrawable))
- {
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pScreenPriv->pBanks[i])
- continue;
- if (!(prgnClip = pGCPriv->pBankedClips[i]))
- prgnClip = REGION_CREATE(NULL, 1);
- REGION_INTERSECT(prgnClip,
- pScreenPriv->pBanks[i], pGC->pCompositeClip);
- if ((REGION_NUM_RECTS(prgnClip) <= 1) &&
- ((prgnClip->extents.x1 == prgnClip->extents.x2) ||
- (prgnClip->extents.y1 == prgnClip->extents.y2)))
- {
- REGION_DESTROY(prgnClip);
- pGCPriv->pBankedClips[i] = NULL;
- }
- else
- pGCPriv->pBankedClips[i] = prgnClip;
- }
- /*
- * fastCopy and fastPlane can only be TRUE if we don't need to
- * worry about attempts to read partial pixels through the
- * destination bank.
- */
- switch (pScreenPriv->type)
- {
- case BANK_SHARED:
- pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
- if ((pGC->alu != GXclear) && (pGC->alu != GXcopy) &&
- (pGC->alu != GXcopyInverted) && (pGC->alu != GXset))
- break;
- if (pScreen->rootDepth == 1)
- pGCPriv->fastPlane = TRUE;
- /* This is probably paranoia */
- if ((pDrawable->depth != pScreen->rootDepth) ||
- (pDrawable->depth != pGC->depth))
- break;
- planemask = (1 << pGC->depth) - 1;
- if ((pGC->planemask & planemask) == planemask)
- pGCPriv->fastCopy = TRUE;
- break;
- case BANK_DOUBLE:
- pGCPriv->fastCopy = pGCPriv->fastPlane = TRUE;
- break;
- default:
- pGCPriv->fastCopy = pGCPriv->fastPlane = FALSE;
- break;
- }
- }
- else
- {
- /*
- * Here we are on a pixmap and don't need all that special clipping
- * stuff, hence free it.
- */
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pGCPriv->pBankedClips[i])
- continue;
- REGION_DESTROY(pGCPriv->pBankedClips[i]);
- pGCPriv->pBankedClips[i] = NULL;
- }
- }
- SCREEN_RESTORE;
- }
- GC_WRAP(pGC);
- }
- static void
- miBankChangeGC(
- GCPtr pGC,
- unsigned long mask
- )
- {
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
- (*pGC->funcs->ChangeGC)(pGC, mask);
- GC_WRAP(pGC);
- }
- static void
- miBankCopyGC(
- GCPtr pGCSrc,
- unsigned long mask,
- GCPtr pGCDst
- )
- {
- GC_INIT(pGCDst);
- GC_UNWRAP(pGCDst);
- (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
- GC_WRAP(pGCDst);
- }
- static void
- miBankDestroyGC(
- GCPtr pGC
- )
- {
- ScreenPtr pScreen = pGC->pScreen;
- int i;
- SCREEN_INIT;
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
- (*pGC->funcs->DestroyGC)(pGC);
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pGCPriv->pBankedClips[i])
- continue;
- REGION_DESTROY(pGCPriv->pBankedClips[i]);
- pGCPriv->pBankedClips[i] = NULL;
- }
- GC_WRAP(pGC);
- }
- static void
- miBankChangeClip(
- GCPtr pGC,
- int type,
- pointer pvalue,
- int nrects
- )
- {
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
- (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
- GC_WRAP(pGC);
- }
- static void
- miBankDestroyClip(
- GCPtr pGC
- )
- {
- GC_INIT(pGC);
- GC_UNWRAP(pGC);
- (*pGC->funcs->DestroyClip)(pGC);
- GC_WRAP(pGC);
- }
- static void
- miBankCopyClip(
- GCPtr pGCDst,
- GCPtr pGCSrc
- )
- {
- GC_INIT(pGCDst);
- GC_UNWRAP(pGCDst);
- (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc);
- GC_WRAP(pGCDst);
- }
- static GCFuncs miBankGCFuncs =
- {
- miBankValidateGC,
- miBankChangeGC,
- miBankCopyGC,
- miBankDestroyGC,
- miBankChangeClip,
- miBankDestroyClip,
- miBankCopyClip
- };
- /*******************
- * Screen Wrappers *
- *******************/
- static Bool
- miBankCreateScreenResources(
- ScreenPtr pScreen
- )
- {
- Bool retval;
- SCREEN_INIT;
- SCREEN_UNWRAP(CreateScreenResources);
- if ((retval = (*pScreen->CreateScreenResources)(pScreen)))
- {
- /* Set screen buffer address to something recognizable */
- pScreenPriv->pScreenPixmap = (*pScreen->GetScreenPixmap)(pScreen);
- pScreenPriv->pbits = pScreenPriv->pScreenPixmap->devPrivate.ptr;
- pScreenPriv->pScreenPixmap->devPrivate.ptr = (pointer)pScreenPriv;
- /* Get shadow pixmap; width & height of 0 means no pixmap data */
- pScreenPriv->pBankPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0,
- pScreenPriv->pScreenPixmap->drawable.depth);
- if (!pScreenPriv->pBankPixmap)
- retval = FALSE;
- }
- /* Shadow the screen */
- if (retval)
- retval = (*pScreen->ModifyPixmapHeader)(pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->drawable.height,
- pScreenPriv->pScreenPixmap->drawable.depth,
- pScreenPriv->pScreenPixmap->drawable.bitsPerPixel,
- pScreenPriv->pScreenPixmap->devKind, NULL);
- /* Create shadow GC */
- if (retval)
- {
- pScreenPriv->pBankGC = CreateScratchGC(pScreen,
- pScreenPriv->pBankPixmap->drawable.depth);
- if (!pScreenPriv->pBankGC)
- retval = FALSE;
- }
- /* Validate shadow GC */
- if (retval)
- {
- pScreenPriv->pBankGC->graphicsExposures = FALSE;
- pScreenPriv->pBankGC->subWindowMode = IncludeInferiors;
- ValidateGC((DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC);
- }
- SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
- return retval;
- }
- static Bool
- miBankModifyPixmapHeader(
- PixmapPtr pPixmap,
- int width,
- int height,
- int depth,
- int bitsPerPixel,
- int devKind,
- pointer pPixData
- )
- {
- Bool retval = FALSE;
- if (pPixmap)
- {
- ScreenPtr pScreen = pPixmap->drawable.pScreen;
- SCREEN_INIT;
- PIXMAP_SAVE(pPixmap);
- SCREEN_UNWRAP(ModifyPixmapHeader);
- retval = (*pScreen->ModifyPixmapHeader)(pPixmap, width, height,
- depth, bitsPerPixel, devKind, pPixData);
- SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
- if (pbits == (pointer)pScreenPriv)
- {
- pScreenPriv->pbits = pPixmap->devPrivate.ptr;
- pPixmap->devPrivate.ptr = pbits;
- }
- }
- return retval;
- }
- static Bool
- miBankCloseScreen(
- int nIndex,
- ScreenPtr pScreen
- )
- {
- int i;
- SCREEN_INIT;
- /* Free shadow GC */
- FreeScratchGC(pScreenPriv->pBankGC);
- /* Free shadow pixmap */
- (*pScreen->DestroyPixmap)(pScreenPriv->pBankPixmap);
- /* Restore screen pixmap devPrivate pointer */
- pScreenPriv->pScreenPixmap->devPrivate.ptr = pScreenPriv->pbits;
- /* Delete bank clips */
- for (i = 0; i < pScreenPriv->nBanks; i++)
- if (pScreenPriv->pBanks[i])
- REGION_DESTROY(pScreenPriv->pBanks[i]);
- free(pScreenPriv->pBanks);
- SCREEN_UNWRAP(CreateScreenResources);
- SCREEN_UNWRAP(ModifyPixmapHeader);
- SCREEN_UNWRAP(CloseScreen);
- SCREEN_UNWRAP(GetImage);
- SCREEN_UNWRAP(GetSpans);
- SCREEN_UNWRAP(CreateGC);
- SCREEN_UNWRAP(PaintWindowBackground);
- SCREEN_UNWRAP(PaintWindowBorder);
- SCREEN_UNWRAP(CopyWindow);
- free(pScreenPriv);
- return (*pScreen->CloseScreen)(nIndex, pScreen);
- }
- static void
- miBankGetImage(
- DrawablePtr pDrawable,
- int sx,
- int sy,
- int w,
- int h,
- unsigned int format,
- unsigned long planemask,
- char *pImage
- )
- {
- if ((w > 0) && (h > 0))
- {
- ScreenPtr pScreen = pDrawable->pScreen;
- SCREEN_INIT;
- SCREEN_STATUS;
- SCREEN_UNWRAP(GetImage);
- if (!IS_BANKED(pDrawable))
- {
- (*pScreen->GetImage)(pDrawable, sx, sy, w, h,
- format, planemask, pImage);
- }
- else
- {
- int paddedWidth;
- char *pBankImage;
- paddedWidth = PixmapBytePad(w,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth * h);
- if (pBankImage)
- {
- BANK_SAVE;
- ModifyPixmap(pScreenPriv->pBankPixmap, w, paddedWidth,
- pBankImage);
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- (DrawablePtr)WindowTable[pScreen->myNum],
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- sx + pDrawable->x, sy + pDrawable->y, w, h, 0, 0);
- (*pScreen->GetImage)((DrawablePtr)pScreenPriv->pBankPixmap,
- 0, 0, w, h, format, planemask, pImage);
- BANK_RESTORE;
- DEALLOCATE_LOCAL(pBankImage);
- }
- }
- SCREEN_WRAP(GetImage, miBankGetImage);
- }
- }
- static void
- miBankGetSpans(
- DrawablePtr pDrawable,
- int wMax,
- DDXPointPtr ppt,
- int *pwidth,
- int nspans,
- char *pImage
- )
- {
- if (nspans > 0)
- {
- ScreenPtr pScreen = pDrawable->pScreen;
- SCREEN_INIT;
- SCREEN_STATUS;
- SCREEN_UNWRAP(GetSpans);
- if (!IS_BANKED(pDrawable))
- {
- (*pScreen->GetSpans)(pDrawable, wMax, ppt, pwidth, nspans, pImage);
- }
- else
- {
- char *pBankImage;
- int paddedWidth;
- DDXPointRec pt;
- pt.x = pt.y = 0;
- paddedWidth =
- PixmapBytePad(pScreenPriv->pScreenPixmap->drawable.width,
- pScreenPriv->pScreenPixmap->drawable.depth);
- pBankImage = (char *)ALLOCATE_LOCAL(paddedWidth);
- if (pBankImage)
- {
- BANK_SAVE;
- ModifyPixmap(pScreenPriv->pBankPixmap,
- pScreenPriv->pScreenPixmap->drawable.width,
- paddedWidth, pBankImage);
- for (; nspans--; ppt++, pwidth++)
- {
- if (*pwidth <= 0)
- continue;
- (*pScreenPriv->pBankGC->ops->CopyArea)(
- (DrawablePtr)WindowTable[pScreen->myNum],
- (DrawablePtr)pScreenPriv->pBankPixmap,
- pScreenPriv->pBankGC,
- ppt->x, ppt->y, *pwidth, 1, 0, 0);
- (*pScreen->GetSpans)((DrawablePtr)pScreenPriv->pBankPixmap,
- wMax, &pt, pwidth, 1, pImage);
- pImage = pImage + PixmapBytePad(*pwidth, pDrawable->depth);
- }
- BANK_RESTORE;
- DEALLOCATE_LOCAL(pBankImage);
- }
- }
- SCREEN_WRAP(GetSpans, miBankGetSpans);
- }
- }
- static Bool
- miBankCreateGC(
- GCPtr pGC
- )
- {
- ScreenPtr pScreen = pGC->pScreen;
- miBankGCPtr pGCPriv = BANK_GCPRIVATE(pGC);
- Bool ret;
- SCREEN_INIT;
- SCREEN_UNWRAP(CreateGC);
- if ((ret = (*pScreen->CreateGC)(pGC)))
- {
- pGCPriv->unwrappedOps = &miBankGCOps;
- pGCPriv->unwrappedFuncs = &miBankGCFuncs;
- GC_WRAP(pGC);
- memset(&pGCPriv->pBankedClips, 0,
- pScreenPriv->nBanks * sizeof(pGCPriv->pBankedClips));
- }
- SCREEN_WRAP(CreateGC, miBankCreateGC);
- return ret;
- }
- static void
- miBankPaintWindow(
- WindowPtr pWin,
- RegionPtr pRegion,
- int what
- )
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RegionRec tmpReg;
- int i;
- PaintWindowProcPtr PaintWindow;
- SCREEN_INIT;
- SCREEN_SAVE;
- if (what == PW_BORDER)
- {
- SCREEN_UNWRAP(PaintWindowBorder);
- PaintWindow = pScreen->PaintWindowBorder;
- }
- else
- {
- SCREEN_UNWRAP(PaintWindowBackground);
- PaintWindow = pScreen->PaintWindowBackground;
- }
- if (!IS_BANKED(pWin))
- {
- (*PaintWindow)(pWin, pRegion, what);
- }
- else
- {
- REGION_NULL(&tmpReg);
- for (i = 0; i < pScreenPriv->nBanks; i++)
- {
- if (!pScreenPriv->pBanks[i])
- continue;
- REGION_INTERSECT(&tmpReg, pRegion,
- pScreenPriv->pBanks[i]);
- if (REGION_NIL(&tmpReg))
- continue;
- SET_SINGLE_BANK(pScreenPriv->pScreenPixmap, -1, -1, i);
- (*PaintWindow)(pWin, &tmpReg, what);
- }
- REGION_UNINIT(&tmpReg);
- }
- if (what == PW_BORDER)
- {
- SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
- }
- else
- {
- SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
- }
- SCREEN_RESTORE;
- }
- static void
- miBankCopyWindow(
- WindowPtr pWindow,
- DDXPointRec ptOldOrg,
- RegionPtr pRgnSrc
- )
- {
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- GCPtr pGC;
- int dx, dy, nBox;
- DrawablePtr pDrawable = (DrawablePtr)WindowTable[pScreen->myNum];
- RegionPtr pRgnDst;
- BoxPtr pBox, pBoxTmp, pBoxNext, pBoxBase, pBoxNew1, pBoxNew2;
- XID subWindowMode = IncludeInferiors;
- pGC = GetScratchGC(pDrawable->depth, pScreen);
- ChangeGC(pGC, GCSubwindowMode, &subWindowMode);
- ValidateGC(pDrawable, pGC);
- pRgnDst = REGION_CREATE(NULL, 1);
- dx = ptOldOrg.x - pWindow->drawable.x;
- dy = ptOldOrg.y - pWindow->drawable.y;
- REGION_TRANSLATE(pRgnSrc, -dx, -dy);
- REGION_INTERSECT(pRgnDst, &pWindow->borderClip, pRgnSrc);
- pBox = REGION_RECTS(pRgnDst);
- nBox = REGION_NUM_RECTS(pRgnDst);
- pBoxNew1 = NULL;
- pBoxNew2 = NULL;
- if (nBox > 1)
- {
- if (dy < 0)
- {
- /* Sort boxes from bottom to top */
- pBoxNew1 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
- if (pBoxNew1)
- {
- pBoxBase = pBoxNext = pBox + nBox - 1;
- while (pBoxBase >= pBox)
- {
- while ((pBoxNext >= pBox) &&
- (pBoxBase->y1 == pBoxNext->y1))
- pBoxNext--;
- pBoxTmp = pBoxNext + 1;
- while (pBoxTmp <= pBoxBase)
- *pBoxNew1++ = *pBoxTmp++;
- pBoxBase = pBoxNext;
- }
- pBoxNew1 -= nBox;
- pBox = pBoxNew1;
- }
- }
- if (dx < 0)
- {
- /* Sort boxes from right to left */
- pBoxNew2 = ALLOCATE_LOCAL_ARRAY(BoxRec, nBox);
- if (pBoxNew2)
- {
- pBoxBase = pBoxNext = pBox;
- while (pBoxBase < pBox + nBox)
- {
- while ((pBoxNext < pBox + nBox) &&
- (pBoxNext->y1 == pBoxBase->y1))
- pBoxNext++;
- pBoxTmp = pBoxNext;
- while (pBoxTmp != pBoxBase)
- *pBoxNew2++ = *--pBoxTmp;
- pBoxBase = pBoxNext;
- }
- pBoxNew2 -= nBox;
- pBox = pBoxNew2;
- }
- }
- }
- while (nBox--)
- {
- (*pGC->ops->CopyArea)(pDrawable, pDrawable, pGC,
- pBox->x1 + dx, pBox->y1 + dy,
- pBox->x2 - pBox->x1, pBox->y2 - pBox->y1,
- pBox->x1, pBox->y1);
- pBox++;
- }
- FreeScratchGC(pGC);
- REGION_DESTROY(pRgnDst);
- DEALLOCATE_LOCAL(pBoxNew2);
- DEALLOCATE_LOCAL(pBoxNew1);
- }
- _X_EXPORT Bool
- miInitializeBanking(
- ScreenPtr pScreen,
- unsigned int xsize,
- unsigned int ysize,
- unsigned int width,
- miBankInfoPtr pBankInfo
- )
- {
- miBankScreenPtr pScreenPriv;
- unsigned long nBitsPerBank, nBitsPerScanline, nPixelsPerScanlinePadUnit;
- unsigned long BankBase, ServerPad;
- unsigned int type, iBank, nBanks, maxRects, we, nBankBPP;
- int i;
- if (!pBankInfo || !pBankInfo->BankSize)
- return TRUE; /* No banking required */
- /* Sanity checks */
- if (!pScreen || !xsize || !ysize || (xsize > width) ||
- !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
- !pBankInfo->SetSourceAndDestinationBanks ||
- !pBankInfo->pBankA || !pBankInfo->pBankB ||
- !pBankInfo->nBankDepth)
- return FALSE;
- /*
- * DDX *must* have registered a pixmap format whose depth is
- * pBankInfo->nBankDepth. This is not necessarily the rootDepth
- * pixmap format.
- */
- i = 0;
- while (screenInfo.formats[i].depth != pBankInfo->nBankDepth)
- if (++i >= screenInfo.numPixmapFormats)
- return FALSE;
- nBankBPP = screenInfo.formats[i].bitsPerPixel;
- i = 0;
- while (screenInfo.formats[i].depth != pScreen->rootDepth)
- if (++i >= screenInfo.numPixmapFormats)
- return FALSE;
- if (nBankBPP > screenInfo.formats[i].bitsPerPixel)
- return FALSE;
- /* Determine banking type */
- if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
- return FALSE;
- /* Internal data */
- nBitsPerBank = pBankInfo->BankSize * 8;
- ServerPad = PixmapBytePad(1, pBankInfo->nBankDepth) * 8;
- if (nBitsPerBank % ServerPad)
- return FALSE;
- nBitsPerScanline = PixmapBytePad(width, pBankInfo->nBankDepth) * 8;
- nBanks = ((nBitsPerScanline * (ysize - 1)) +
- (nBankBPP * xsize) + nBitsPerBank - 1) / nBitsPerBank;
- nPixelsPerScanlinePadUnit = miLCM(ServerPad, nBankBPP) / nBankBPP;
- /* Private areas */
- if (miBankGeneration != serverGeneration)
- {
- if (((miBankScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
- ((miBankGCIndex = AllocateGCPrivateIndex()) < 0))
- return FALSE;
- miBankGeneration = serverGeneration;
- }
- if (!AllocateGCPrivate(pScreen, miBankGCIndex,
- (nBanks * sizeof(RegionPtr)) +
- (sizeof(miBankGCRec) - sizeof(RegionPtr))))
- return FALSE;
- if (!(pScreenPriv = (miBankScreenPtr)calloc(1, sizeof(miBankScreenRec))))
- return FALSE;
- if (!(pScreenPriv->pBanks = /* Allocate and clear */
- (RegionPtr *)calloc(nBanks, sizeof(RegionPtr))))
- {
- free(pScreenPriv);
- return FALSE;
- }
- /*
- * Translate banks into clipping regions which are themselves clipped
- * against the screen. This also ensures that pixels with imbedded bank
- * boundaries are off-screen.
- */
- BankBase = 0;
- maxRects = 0;
- we = 0;
- for (iBank = 0; iBank < nBanks; iBank++)
- {
- xRectangle pRects[3], *pRect = pRects;
- unsigned int xb, yb, xe, ye;
- xb = ((BankBase + nBankBPP - 1) % nBitsPerScanline) / nBankBPP;
- yb = (BankBase + nBankBPP - 1) / nBitsPerScanline;
- if (xb >= xsize)
- {
- xb = we = 0;
- yb++;
- }
- if (yb >= ysize)
- {
- we = 0;
- break;
- }
- if (we)
- break;
- BankBase += nBitsPerBank;
- we = (BankBase % nBitsPerScanline) % nBankBPP;
- xe = (BankBase % nBitsPerScanline) / nBankBPP;
- ye = BankBase / nBitsPerScanline;
- if (xe >= xsize)
- {
- we = xe = 0;
- ye++;
- }
- if (ye >= ysize)
- {
- we = xe = 0;
- ye = ysize;
- }
- if (yb == ye)
- {
- if (xb >= xe)
- continue;
- pRect->x = xb;
- pRect->y = yb;
- pRect->width = xe - xb;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
- else
- {
- if (xb)
- {
- pRect->x = xb;
- pRect->y = yb++;
- pRect->width = xsize - xb;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
- if (yb < ye)
- {
- pRect->x = 0;
- pRect->y = yb;
- pRect->width = xsize;
- pRect->height = ye - yb;
- maxRects += min(pRect->height, 3) + 1;
- pRect++;
- }
- if (xe)
- {
- pRect->x = 0;
- pRect->y = ye;
- pRect->width = xe;
- pRect->height = 1;
- maxRects += 2;
- pRect++;
- }
- }
- pScreenPriv->pBanks[iBank] =
- RECTS_TO_REGION(pRect - pRects, pRects, 0);
- if (!pScreenPriv->pBanks[iBank] ||
- REGION_NAR(pScreenPriv->pBanks[iBank]))
- {
- we = 1;
- break;
- }
- }
- if (we && (iBank < nBanks))
- {
- for (i = iBank; i >= 0; i--)
- if (pScreenPriv->pBanks[i])
- REGION_DESTROY(pScreenPriv->pBanks[i]);
- free(pScreenPriv->pBanks);
- free(pScreenPriv);
- return FALSE;
- }
- /* Open for business */
- pScreenPriv->type = type;
- pScreenPriv->nBanks = nBanks;
- pScreenPriv->maxRects = maxRects;
- pScreenPriv->nBankBPP = nBankBPP;
- pScreenPriv->BankInfo = *pBankInfo;
- pScreenPriv->nBitsPerBank = nBitsPerBank;
- pScreenPriv->nBitsPerScanline = nBitsPerScanline;
- pScreenPriv->nPixelsPerScanlinePadUnit = nPixelsPerScanlinePadUnit;
- SCREEN_WRAP(CreateScreenResources, miBankCreateScreenResources);
- SCREEN_WRAP(ModifyPixmapHeader, miBankModifyPixmapHeader);
- SCREEN_WRAP(CloseScreen, miBankCloseScreen);
- SCREEN_WRAP(GetImage, miBankGetImage);
- SCREEN_WRAP(GetSpans, miBankGetSpans);
- SCREEN_WRAP(CreateGC, miBankCreateGC);
- SCREEN_WRAP(PaintWindowBackground, miBankPaintWindow);
- SCREEN_WRAP(PaintWindowBorder, miBankPaintWindow);
- SCREEN_WRAP(CopyWindow, miBankCopyWindow);
- BANK_SCRPRIVLVAL = (pointer)pScreenPriv;
- return TRUE;
- }
- /* This is used to force GC revalidation when the banking type is changed */
- /*ARGSUSED*/
- static int
- miBankNewSerialNumber(
- WindowPtr pWin,
- pointer unused
- )
- {
- pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- return WT_WALKCHILDREN;
- }
- /* This entry modifies the banking interface */
- _X_EXPORT Bool
- miModifyBanking(
- ScreenPtr pScreen,
- miBankInfoPtr pBankInfo
- )
- {
- unsigned int type;
- if (!pScreen)
- return FALSE;
- if (miBankGeneration == serverGeneration)
- {
- SCREEN_INIT;
- if (pScreenPriv)
- {
- if (!pBankInfo || !pBankInfo->BankSize ||
- !pBankInfo->pBankA || !pBankInfo->pBankB ||
- !pBankInfo->SetSourceBank || !pBankInfo->SetDestinationBank ||
- !pBankInfo->SetSourceAndDestinationBanks)
- return FALSE;
- /* BankSize and nBankDepth cannot, as yet, be changed */
- if ((pScreenPriv->BankInfo.BankSize != pBankInfo->BankSize) ||
- (pScreenPriv->BankInfo.nBankDepth != pBankInfo->nBankDepth))
- return FALSE;
- if ((type = miBankDeriveType(pScreen, pBankInfo)) == BANK_NOBANK)
- return FALSE;
- /* Reset banking info */
- pScreenPriv->BankInfo = *pBankInfo;
- if (type != pScreenPriv->type)
- {
- /*
- * Banking type is changing. Revalidate all window GC's.
- */
- pScreenPriv->type = type;
- WalkTree(pScreen, miBankNewSerialNumber, 0);
- }
- return TRUE;
- }
- }
- if (!pBankInfo || !pBankInfo->BankSize)
- return TRUE; /* No change requested */
- return FALSE;
- }
- /*
- * Given various screen attributes, determine the minimum scanline width such
- * that each scanline is server and DDX padded and any pixels with imbedded
- * bank boundaries are off-screen. This function returns -1 if such a width
- * cannot exist. This function exists because the DDX needs to be able to
- * determine this width before initializing a frame buffer.
- */
- int
- miScanLineWidth(
- unsigned int xsize, /* pixels */
- unsigned int ysize, /* pixels */
- unsigned int width, /* pixels */
- unsigned long BankSize, /* char's */
- PixmapFormatRec *pBankFormat,
- unsigned int nWidthUnit /* bits */
- )
- {
- unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
- unsigned long minBitsPerScanline, maxBitsPerScanline;
- /* Sanity checks */
- if (!nWidthUnit || !pBankFormat)
- return -1;
- nBitsPerBank = BankSize * 8;
- if (nBitsPerBank % pBankFormat->scanlinePad)
- return -1;
- if (xsize > width)
- width = xsize;
- nBitsPerScanlinePadUnit = miLCM(pBankFormat->scanlinePad, nWidthUnit);
- nBitsPerScanline =
- (((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
- nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
- width = nBitsPerScanline / pBankFormat->bitsPerPixel;
- if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
- return (int)width;
- /*
- * Scanlines will be server-pad aligned at this point. They will also be
- * a multiple of nWidthUnit bits long. Ensure that pixels with imbedded
- * bank boundaries are off-screen.
- *
- * It seems reasonable to limit total frame buffer size to 1/16 of the
- * theoretical maximum address space size. On a machine with 32-bit
- * addresses (to 8-bit quantities) this turns out to be 256MB. Not only
- * does this provide a simple limiting condition for the loops below, but
- * it also prevents unsigned long wraparounds.
- */
- if (!ysize)
- return -1;
- minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
- if (minBitsPerScanline > nBitsPerBank)
- return -1;
- if (ysize == 1)
- return (int)width;
- maxBitsPerScanline =
- (((unsigned long)(-1) >> 1) - minBitsPerScanline) / (ysize - 1);
- while (nBitsPerScanline <= maxBitsPerScanline)
- {
- unsigned long BankBase, BankUnit;
- BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
- nBitsPerBank;
- if (!(BankUnit % nBitsPerScanline))
- return (int)width;
- for (BankBase = BankUnit; ; BankBase += nBitsPerBank)
- {
- unsigned long x, y;
- y = BankBase / nBitsPerScanline;
- if (y >= ysize)
- return (int)width;
- x = BankBase % nBitsPerScanline;
- if (!(x % pBankFormat->bitsPerPixel))
- continue;
- if (x < minBitsPerScanline)
- {
- /*
- * Skip ahead certain widths by dividing the excess scanline
- * amongst the y's.
- */
- y *= nBitsPerScanlinePadUnit;
- nBitsPerScanline +=
- ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
- width = nBitsPerScanline / pBankFormat->bitsPerPixel;
- break;
- }
- if (BankBase != BankUnit)
- continue;
- if (!(nBitsPerScanline % x))
- return (int)width;
- BankBase = ((nBitsPerScanline - minBitsPerScanline) /
- (nBitsPerScanline - x)) * BankUnit;
- }
- }
- return -1;
- }
|