colormap.c 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556
  1. /***********************************************************
  2. Copyright 1987, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included in
  9. all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  14. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  15. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. Except as contained in this notice, the name of The Open Group shall not be
  17. used in advertising or otherwise to promote the sale, use or other dealings
  18. in this Software without prior written authorization from The Open Group.
  19. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  20. All Rights Reserved
  21. Permission to use, copy, modify, and distribute this software and its
  22. documentation for any purpose and without fee is hereby granted,
  23. provided that the above copyright notice appear in all copies and that
  24. both that copyright notice and this permission notice appear in
  25. supporting documentation, and that the name of Digital not be
  26. used in advertising or publicity pertaining to distribution of the
  27. software without specific, written prior permission.
  28. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34. SOFTWARE.
  35. ******************************************************************/
  36. #ifdef HAVE_DIX_CONFIG_H
  37. #include <dix-config.h>
  38. #endif
  39. #include <X11/X.h>
  40. #include <X11/Xproto.h>
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <strings.h>
  44. #include "misc.h"
  45. #include "dix.h"
  46. #include "colormapst.h"
  47. #include "os.h"
  48. #include "scrnintstr.h"
  49. #include "resource.h"
  50. #include "windowstr.h"
  51. extern XID clientErrorValue;
  52. extern int colormapPrivateCount;
  53. static Pixel FindBestPixel(EntryPtr /*pentFirst */ ,
  54. int /*size */ ,
  55. xrgb * /*prgb */ ,
  56. int /*channel */
  57. );
  58. static int AllComp(EntryPtr /*pent */ ,
  59. xrgb * /*prgb */
  60. );
  61. static int RedComp(EntryPtr /*pent */ ,
  62. xrgb * /*prgb */
  63. );
  64. static int GreenComp(EntryPtr /*pent */ ,
  65. xrgb * /*prgb */
  66. );
  67. static int BlueComp(EntryPtr /*pent */ ,
  68. xrgb * /*prgb */
  69. );
  70. static void FreePixels(register ColormapPtr /*pmap */ ,
  71. register int /*client */
  72. );
  73. static void CopyFree(int /*channel */ ,
  74. int /*client */ ,
  75. ColormapPtr /*pmapSrc */ ,
  76. ColormapPtr /*pmapDst */
  77. );
  78. static void FreeCell(ColormapPtr /*pmap */ ,
  79. Pixel /*i */ ,
  80. int /*channel */
  81. );
  82. static void UpdateColors(ColormapPtr /*pmap */
  83. );
  84. static int AllocDirect(int /*client */ ,
  85. ColormapPtr /*pmap */ ,
  86. int /*c */ ,
  87. int /*r */ ,
  88. int /*g */ ,
  89. int /*b */ ,
  90. Bool /*contig */ ,
  91. Pixel * /*pixels */ ,
  92. Pixel * /*prmask */ ,
  93. Pixel * /*pgmask */ ,
  94. Pixel * /*pbmask */
  95. );
  96. static int AllocPseudo(int /*client */ ,
  97. ColormapPtr /*pmap */ ,
  98. int /*c */ ,
  99. int /*r */ ,
  100. Bool /*contig */ ,
  101. Pixel * /*pixels */ ,
  102. Pixel * /*pmask */ ,
  103. Pixel ** /*pppixFirst */
  104. );
  105. static Bool AllocCP(ColormapPtr /*pmap */ ,
  106. EntryPtr /*pentFirst */ ,
  107. int /*count */ ,
  108. int /*planes */ ,
  109. Bool /*contig */ ,
  110. Pixel * /*pixels */ ,
  111. Pixel * /*pMask */
  112. );
  113. static Bool AllocShared(ColormapPtr /*pmap */ ,
  114. Pixel * /*ppix */ ,
  115. int /*c */ ,
  116. int /*r */ ,
  117. int /*g */ ,
  118. int /*b */ ,
  119. Pixel /*rmask */ ,
  120. Pixel /*gmask */ ,
  121. Pixel /*bmask */ ,
  122. Pixel * /*ppixFirst */
  123. );
  124. static int FreeCo(ColormapPtr /*pmap */ ,
  125. int /*client */ ,
  126. int /*color */ ,
  127. int /*npixIn */ ,
  128. Pixel * /*ppixIn */ ,
  129. Pixel /*mask */
  130. );
  131. static int TellNoMap(WindowPtr /*pwin */ ,
  132. Colormap * /*pmid */
  133. );
  134. static void FindColorInRootCmap(ColormapPtr /* pmap */ ,
  135. EntryPtr /* pentFirst */ ,
  136. int /* size */ ,
  137. xrgb * /* prgb */ ,
  138. Pixel * /* pPixel */ ,
  139. int /* channel */ ,
  140. ColorCompareProcPtr /* comp */
  141. );
  142. #define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
  143. #define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
  144. #define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
  145. #define ALPHAMASK(vis) 0
  146. #define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
  147. /* GetNextBitsOrBreak(bits, mask, base) --
  148. * (Suggestion: First read the macro, then read this explanation.
  149. *
  150. * Either generate the next value to OR in to a pixel or break out of this
  151. * while loop
  152. *
  153. * This macro is used when we're trying to generate all 2^n combinations of
  154. * bits in mask. What we're doing here is counting in binary, except that
  155. * the bits we use to count may not be contiguous. This macro will be
  156. * called 2^n times, returning a different value in bits each time. Then
  157. * it will cause us to break out of a surrounding loop. (It will always be
  158. * called from within a while loop.)
  159. * On call: mask is the value we want to find all the combinations for
  160. * base has 1 bit set where the least significant bit of mask is set
  161. *
  162. * For example,if mask is 01010, base should be 0010 and we count like this:
  163. * 00010 (see this isn't so hard),
  164. * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
  165. * we add that to bits getting (0100 + 0100) =
  166. * 01000 for our next value.
  167. * then we add 0010 to get
  168. * 01010 and we're done (easy as 1, 2, 3)
  169. */
  170. #define GetNextBitsOrBreak(bits, mask, base) \
  171. if((bits) == (mask)) \
  172. break; \
  173. (bits) += (base); \
  174. while((bits) & ~(mask)) \
  175. (bits) += ((bits) & ~(mask));
  176. /* ID of server as client */
  177. #define SERVER_ID 0
  178. typedef struct _colorResource {
  179. Colormap mid;
  180. int client;
  181. } colorResource;
  182. /* Invariants:
  183. * refcnt == 0 means entry is empty
  184. * refcnt > 0 means entry is useable by many clients, so it can't be changed
  185. * refcnt == AllocPrivate means entry owned by one client only
  186. * fShared should only be set if refcnt == AllocPrivate, and only in red map
  187. */
  188. /**
  189. * Create and initialize the color map
  190. *
  191. * \param mid resource to use for this colormap
  192. * \param alloc 1 iff all entries are allocated writable
  193. */
  194. _X_EXPORT int
  195. CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
  196. ColormapPtr *ppcmap, int alloc, int client)
  197. {
  198. int class, size;
  199. unsigned long sizebytes;
  200. ColormapPtr pmap;
  201. EntryPtr pent;
  202. int i;
  203. Pixel *ppix, **pptr;
  204. class = pVisual->class;
  205. if (!(class & DynamicClass) && (alloc != AllocNone) &&
  206. (client != SERVER_ID))
  207. return (BadMatch);
  208. size = pVisual->ColormapEntries;
  209. sizebytes = (size * sizeof(Entry)) +
  210. (MAXCLIENTS * sizeof(Pixel *)) + (MAXCLIENTS * sizeof(int));
  211. if ((class | DynamicClass) == DirectColor)
  212. sizebytes *= 3;
  213. sizebytes += sizeof(ColormapRec);
  214. pmap = malloc(sizebytes);
  215. if (!pmap)
  216. return (BadAlloc);
  217. #if defined(_XSERVER64)
  218. pmap->pad0 = 0;
  219. pmap->pad1 = 0;
  220. #if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
  221. pmap->pad2 = 0;
  222. #endif
  223. #endif
  224. pmap->red = (EntryPtr) ((char *) pmap + sizeof(ColormapRec));
  225. sizebytes = size * sizeof(Entry);
  226. pmap->clientPixelsRed = (Pixel **) ((char *) pmap->red + sizebytes);
  227. pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
  228. (MAXCLIENTS * sizeof(Pixel *)));
  229. pmap->mid = mid;
  230. pmap->flags = 0; /* start out with all flags clear */
  231. if (mid == pScreen->defColormap)
  232. pmap->flags |= IsDefault;
  233. pmap->pScreen = pScreen;
  234. pmap->pVisual = pVisual;
  235. pmap->class = class;
  236. if ((class | DynamicClass) == DirectColor)
  237. size = NUMRED(pVisual);
  238. pmap->freeRed = size;
  239. bzero((char *) pmap->red, (int) sizebytes);
  240. bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
  241. for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
  242. --pptr >= pmap->clientPixelsRed;)
  243. *pptr = (Pixel *) NULL;
  244. if (alloc == AllocAll) {
  245. if (class & DynamicClass)
  246. pmap->flags |= AllAllocated;
  247. for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
  248. pent->refcnt = AllocPrivate;
  249. pmap->freeRed = 0;
  250. ppix = malloc(size * sizeof(Pixel));
  251. if (!ppix) {
  252. free(pmap);
  253. return (BadAlloc);
  254. }
  255. pmap->clientPixelsRed[client] = ppix;
  256. for (i = 0; i < size; i++)
  257. ppix[i] = i;
  258. pmap->numPixelsRed[client] = size;
  259. }
  260. if ((class | DynamicClass) == DirectColor) {
  261. pmap->freeGreen = NUMGREEN(pVisual);
  262. pmap->green = (EntryPtr) ((char *) pmap->numPixelsRed +
  263. (MAXCLIENTS * sizeof(int)));
  264. pmap->clientPixelsGreen = (Pixel **) ((char *) pmap->green + sizebytes);
  265. pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
  266. (MAXCLIENTS * sizeof(Pixel *)));
  267. pmap->freeBlue = NUMBLUE(pVisual);
  268. pmap->blue = (EntryPtr) ((char *) pmap->numPixelsGreen +
  269. (MAXCLIENTS * sizeof(int)));
  270. pmap->clientPixelsBlue = (Pixel **) ((char *) pmap->blue + sizebytes);
  271. pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
  272. (MAXCLIENTS * sizeof(Pixel *)));
  273. bzero((char *) pmap->green, (int) sizebytes);
  274. bzero((char *) pmap->blue, (int) sizebytes);
  275. memmove((char *) pmap->clientPixelsGreen,
  276. (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
  277. memmove((char *) pmap->clientPixelsBlue,
  278. (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
  279. bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
  280. bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
  281. /* If every cell is allocated, mark its refcnt */
  282. if (alloc == AllocAll) {
  283. size = pmap->freeGreen;
  284. for (pent = &pmap->green[size - 1]; pent >= pmap->green; pent--)
  285. pent->refcnt = AllocPrivate;
  286. pmap->freeGreen = 0;
  287. ppix = malloc(size * sizeof(Pixel));
  288. if (!ppix) {
  289. free(pmap->clientPixelsRed[client]);
  290. free(pmap);
  291. return (BadAlloc);
  292. }
  293. pmap->clientPixelsGreen[client] = ppix;
  294. for (i = 0; i < size; i++)
  295. ppix[i] = i;
  296. pmap->numPixelsGreen[client] = size;
  297. size = pmap->freeBlue;
  298. for (pent = &pmap->blue[size - 1]; pent >= pmap->blue; pent--)
  299. pent->refcnt = AllocPrivate;
  300. pmap->freeBlue = 0;
  301. ppix = malloc(size * sizeof(Pixel));
  302. if (!ppix) {
  303. free(pmap->clientPixelsGreen[client]);
  304. free(pmap->clientPixelsRed[client]);
  305. free(pmap);
  306. return (BadAlloc);
  307. }
  308. pmap->clientPixelsBlue[client] = ppix;
  309. for (i = 0; i < size; i++)
  310. ppix[i] = i;
  311. pmap->numPixelsBlue[client] = size;
  312. }
  313. }
  314. if (!AddResource(mid, RT_COLORMAP, (pointer) pmap))
  315. return (BadAlloc);
  316. /* If the device wants a chance to initialize the colormap in any way,
  317. * this is it. In specific, if this is a Static colormap, this is the
  318. * time to fill in the colormap's values */
  319. pmap->flags |= BeingCreated;
  320. /*
  321. * Allocate the array of devPrivate's for this colormap.
  322. */
  323. if (colormapPrivateCount == 0)
  324. pmap->devPrivates = NULL;
  325. else {
  326. pmap->devPrivates =
  327. calloc(sizeof(DevUnion), colormapPrivateCount);
  328. if (!pmap->devPrivates) {
  329. FreeResource(mid, RT_NONE);
  330. return BadAlloc;
  331. }
  332. }
  333. if (!(*pScreen->CreateColormap) (pmap)) {
  334. FreeResource(mid, RT_NONE);
  335. return BadAlloc;
  336. }
  337. pmap->flags &= ~BeingCreated;
  338. *ppcmap = pmap;
  339. return (Success);
  340. }
  341. /**
  342. *
  343. * \param value must conform to DeleteType
  344. */
  345. int
  346. FreeColormap(pointer value, XID mid)
  347. {
  348. int i;
  349. EntryPtr pent;
  350. ColormapPtr pmap = (ColormapPtr) value;
  351. if (CLIENT_ID(mid) != SERVER_ID) {
  352. (*pmap->pScreen->UninstallColormap) (pmap);
  353. WalkTree(pmap->pScreen, (VisitWindowProcPtr) TellNoMap, (pointer) &mid);
  354. }
  355. /* This is the device's chance to undo anything it needs to, especially
  356. * to free any storage it allocated */
  357. (*pmap->pScreen->DestroyColormap) (pmap);
  358. if (pmap->clientPixelsRed) {
  359. for (i = 0; i < MAXCLIENTS; i++)
  360. free(pmap->clientPixelsRed[i]);
  361. }
  362. if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) {
  363. for (pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
  364. pent >= pmap->red; pent--) {
  365. if (pent->fShared) {
  366. if (--pent->co.shco.red->refcnt == 0)
  367. free(pent->co.shco.red);
  368. if (--pent->co.shco.green->refcnt == 0)
  369. free(pent->co.shco.green);
  370. if (--pent->co.shco.blue->refcnt == 0)
  371. free(pent->co.shco.blue);
  372. }
  373. }
  374. }
  375. if ((pmap->class | DynamicClass) == DirectColor) {
  376. for (i = 0; i < MAXCLIENTS; i++) {
  377. free(pmap->clientPixelsGreen[i]);
  378. free(pmap->clientPixelsBlue[i]);
  379. }
  380. }
  381. if (pmap->devPrivates)
  382. free(pmap->devPrivates);
  383. free(pmap);
  384. return (Success);
  385. }
  386. /* Tell window that pmid has disappeared */
  387. static int
  388. TellNoMap(WindowPtr pwin, Colormap * pmid)
  389. {
  390. xEvent xE;
  391. if (wColormap(pwin) == *pmid) {
  392. /* This should be call to DeliverEvent */
  393. xE.u.u.type = ColormapNotify;
  394. xE.u.colormap.window = pwin->drawable.id;
  395. xE.u.colormap.colormap = None;
  396. xE.u.colormap.new = TRUE;
  397. xE.u.colormap.state = ColormapUninstalled;
  398. DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
  399. if (pwin->optional) {
  400. pwin->optional->colormap = None;
  401. CheckWindowOptionalNeed(pwin);
  402. }
  403. }
  404. return (WT_WALKCHILDREN);
  405. }
  406. /* Tell window that pmid got uninstalled */
  407. _X_EXPORT int
  408. TellLostMap(WindowPtr pwin, pointer value)
  409. {
  410. Colormap *pmid = (Colormap *) value;
  411. xEvent xE;
  412. if (wColormap(pwin) == *pmid) {
  413. /* This should be call to DeliverEvent */
  414. xE.u.u.type = ColormapNotify;
  415. xE.u.colormap.window = pwin->drawable.id;
  416. xE.u.colormap.colormap = *pmid;
  417. xE.u.colormap.new = FALSE;
  418. xE.u.colormap.state = ColormapUninstalled;
  419. DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
  420. }
  421. return (WT_WALKCHILDREN);
  422. }
  423. /* Tell window that pmid got installed */
  424. _X_EXPORT int
  425. TellGainedMap(WindowPtr pwin, pointer value)
  426. {
  427. Colormap *pmid = (Colormap *) value;
  428. xEvent xE;
  429. if (wColormap(pwin) == *pmid) {
  430. /* This should be call to DeliverEvent */
  431. xE.u.u.type = ColormapNotify;
  432. xE.u.colormap.window = pwin->drawable.id;
  433. xE.u.colormap.colormap = *pmid;
  434. xE.u.colormap.new = FALSE;
  435. xE.u.colormap.state = ColormapInstalled;
  436. DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
  437. }
  438. return (WT_WALKCHILDREN);
  439. }
  440. int
  441. CopyColormapAndFree(Colormap mid, ColormapPtr pSrc, int client)
  442. {
  443. ColormapPtr pmap = (ColormapPtr) NULL;
  444. int result, alloc, size;
  445. Colormap midSrc;
  446. ScreenPtr pScreen;
  447. VisualPtr pVisual;
  448. pScreen = pSrc->pScreen;
  449. pVisual = pSrc->pVisual;
  450. midSrc = pSrc->mid;
  451. alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
  452. AllocAll : AllocNone;
  453. size = pVisual->ColormapEntries;
  454. /* If the create returns non-0, it failed */
  455. result = CreateColormap(mid, pScreen, pVisual, &pmap, alloc, client);
  456. if (result != Success)
  457. return (result);
  458. if (alloc == AllocAll) {
  459. memmove((char *) pmap->red, (char *) pSrc->red, size * sizeof(Entry));
  460. if ((pmap->class | DynamicClass) == DirectColor) {
  461. memmove((char *) pmap->green, (char *) pSrc->green,
  462. size * sizeof(Entry));
  463. memmove((char *) pmap->blue, (char *) pSrc->blue,
  464. size * sizeof(Entry));
  465. }
  466. pSrc->flags &= ~AllAllocated;
  467. FreePixels(pSrc, client);
  468. UpdateColors(pmap);
  469. return (Success);
  470. }
  471. CopyFree(REDMAP, client, pSrc, pmap);
  472. if ((pmap->class | DynamicClass) == DirectColor) {
  473. CopyFree(GREENMAP, client, pSrc, pmap);
  474. CopyFree(BLUEMAP, client, pSrc, pmap);
  475. }
  476. if (pmap->class & DynamicClass)
  477. UpdateColors(pmap);
  478. /* XXX should worry about removing any RT_CMAPENTRY resource */
  479. return (Success);
  480. }
  481. /* Helper routine for freeing large numbers of cells from a map */
  482. static void
  483. CopyFree(int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
  484. {
  485. int z, npix;
  486. EntryPtr pentSrcFirst, pentDstFirst;
  487. EntryPtr pentSrc, pentDst;
  488. Pixel *ppix;
  489. int nalloc;
  490. switch (channel) {
  491. default: /* so compiler can see that everything gets initialized */
  492. case REDMAP:
  493. ppix = (pmapSrc->clientPixelsRed)[client];
  494. npix = (pmapSrc->numPixelsRed)[client];
  495. pentSrcFirst = pmapSrc->red;
  496. pentDstFirst = pmapDst->red;
  497. break;
  498. case GREENMAP:
  499. ppix = (pmapSrc->clientPixelsGreen)[client];
  500. npix = (pmapSrc->numPixelsGreen)[client];
  501. pentSrcFirst = pmapSrc->green;
  502. pentDstFirst = pmapDst->green;
  503. break;
  504. case BLUEMAP:
  505. ppix = (pmapSrc->clientPixelsBlue)[client];
  506. npix = (pmapSrc->numPixelsBlue)[client];
  507. pentSrcFirst = pmapSrc->blue;
  508. pentDstFirst = pmapDst->blue;
  509. break;
  510. }
  511. nalloc = 0;
  512. if (pmapSrc->class & DynamicClass) {
  513. for (z = npix; --z >= 0; ppix++) {
  514. /* Copy entries */
  515. pentSrc = pentSrcFirst + *ppix;
  516. pentDst = pentDstFirst + *ppix;
  517. if (pentDst->refcnt > 0) {
  518. pentDst->refcnt++;
  519. }
  520. else {
  521. *pentDst = *pentSrc;
  522. nalloc++;
  523. if (pentSrc->refcnt > 0)
  524. pentDst->refcnt = 1;
  525. else
  526. pentSrc->fShared = FALSE;
  527. }
  528. FreeCell(pmapSrc, *ppix, channel);
  529. }
  530. }
  531. /* Note that FreeCell has already fixed pmapSrc->free{Color} */
  532. switch (channel) {
  533. case REDMAP:
  534. pmapDst->freeRed -= nalloc;
  535. (pmapDst->clientPixelsRed)[client] = (pmapSrc->clientPixelsRed)[client];
  536. (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
  537. (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
  538. (pmapSrc->numPixelsRed)[client] = 0;
  539. break;
  540. case GREENMAP:
  541. pmapDst->freeGreen -= nalloc;
  542. (pmapDst->clientPixelsGreen)[client] =
  543. (pmapSrc->clientPixelsGreen)[client];
  544. (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
  545. (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
  546. (pmapSrc->numPixelsGreen)[client] = 0;
  547. break;
  548. case BLUEMAP:
  549. pmapDst->freeBlue -= nalloc;
  550. pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
  551. pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
  552. pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
  553. pmapSrc->numPixelsBlue[client] = 0;
  554. break;
  555. }
  556. }
  557. /* Free the ith entry in a color map. Must handle freeing of
  558. * colors allocated through AllocColorPlanes */
  559. static void
  560. FreeCell(ColormapPtr pmap, Pixel i, int channel)
  561. {
  562. EntryPtr pent;
  563. int *pCount;
  564. switch (channel) {
  565. default: /* so compiler can see that everything gets initialized */
  566. case PSEUDOMAP:
  567. case REDMAP:
  568. pent = (EntryPtr) & pmap->red[i];
  569. pCount = &pmap->freeRed;
  570. break;
  571. case GREENMAP:
  572. pent = (EntryPtr) & pmap->green[i];
  573. pCount = &pmap->freeGreen;
  574. break;
  575. case BLUEMAP:
  576. pent = (EntryPtr) & pmap->blue[i];
  577. pCount = &pmap->freeBlue;
  578. break;
  579. }
  580. /* If it's not privately allocated and it's not time to free it, just
  581. * decrement the count */
  582. if (pent->refcnt > 1)
  583. pent->refcnt--;
  584. else {
  585. /* If the color type is shared, find the sharedcolor. If decremented
  586. * refcnt is 0, free the shared cell. */
  587. if (pent->fShared) {
  588. if (--pent->co.shco.red->refcnt == 0)
  589. free(pent->co.shco.red);
  590. if (--pent->co.shco.green->refcnt == 0)
  591. free(pent->co.shco.green);
  592. if (--pent->co.shco.blue->refcnt == 0)
  593. free(pent->co.shco.blue);
  594. pent->fShared = FALSE;
  595. }
  596. pent->refcnt = 0;
  597. *pCount += 1;
  598. }
  599. }
  600. static void
  601. UpdateColors(ColormapPtr pmap)
  602. {
  603. xColorItem *defs;
  604. xColorItem *pdef;
  605. EntryPtr pent;
  606. VisualPtr pVisual;
  607. int i, n, size;
  608. pVisual = pmap->pVisual;
  609. size = pVisual->ColormapEntries;
  610. defs = (xColorItem *) ALLOCATE_LOCAL(size * sizeof(xColorItem));
  611. if (!defs)
  612. return;
  613. n = 0;
  614. pdef = defs;
  615. if (pmap->class == DirectColor) {
  616. for (i = 0; i < size; i++) {
  617. if (!pmap->red[i].refcnt &&
  618. !pmap->green[i].refcnt && !pmap->blue[i].refcnt)
  619. continue;
  620. pdef->pixel = ((Pixel) i << pVisual->offsetRed) |
  621. ((Pixel) i << pVisual->offsetGreen) |
  622. ((Pixel) i << pVisual->offsetBlue);
  623. pdef->red = pmap->red[i].co.local.red;
  624. pdef->green = pmap->green[i].co.local.green;
  625. pdef->blue = pmap->blue[i].co.local.blue;
  626. pdef->flags = DoRed | DoGreen | DoBlue;
  627. pdef++;
  628. n++;
  629. }
  630. }
  631. else {
  632. for (i = 0, pent = pmap->red; i < size; i++, pent++) {
  633. if (!pent->refcnt)
  634. continue;
  635. pdef->pixel = i;
  636. if (pent->fShared) {
  637. pdef->red = pent->co.shco.red->color;
  638. pdef->green = pent->co.shco.green->color;
  639. pdef->blue = pent->co.shco.blue->color;
  640. }
  641. else {
  642. pdef->red = pent->co.local.red;
  643. pdef->green = pent->co.local.green;
  644. pdef->blue = pent->co.local.blue;
  645. }
  646. pdef->flags = DoRed | DoGreen | DoBlue;
  647. pdef++;
  648. n++;
  649. }
  650. }
  651. if (n)
  652. (*pmap->pScreen->StoreColors) (pmap, n, defs);
  653. DEALLOCATE_LOCAL(defs);
  654. }
  655. /* Get a read-only color from a ColorMap (probably slow for large maps)
  656. * Returns by changing the value in pred, pgreen, pblue and pPix
  657. */
  658. _X_EXPORT int
  659. AllocColor(ColormapPtr pmap,
  660. unsigned short *pred, unsigned short *pgreen, unsigned short *pblue,
  661. Pixel * pPix, int client)
  662. {
  663. Pixel pixR, pixG, pixB;
  664. int entries;
  665. xrgb rgb;
  666. int class;
  667. VisualPtr pVisual;
  668. int npix;
  669. Pixel *ppix;
  670. pVisual = pmap->pVisual;
  671. (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
  672. rgb.red = *pred;
  673. rgb.green = *pgreen;
  674. rgb.blue = *pblue;
  675. class = pmap->class;
  676. entries = pVisual->ColormapEntries;
  677. /* If the colormap is being created, then we want to be able to change
  678. * the colormap, even if it's a static type. Otherwise, we'd never be
  679. * able to initialize static colormaps
  680. */
  681. if (pmap->flags & BeingCreated)
  682. class |= DynamicClass;
  683. /* If this is one of the static storage classes, and we're not initializing
  684. * it, the best we can do is to find the closest color entry to the
  685. * requested one and return that.
  686. */
  687. switch (class) {
  688. case StaticColor:
  689. case StaticGray:
  690. /* Look up all three components in the same pmap */
  691. *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
  692. *pred = pmap->red[pixR].co.local.red;
  693. *pgreen = pmap->red[pixR].co.local.green;
  694. *pblue = pmap->red[pixR].co.local.blue;
  695. npix = pmap->numPixelsRed[client];
  696. ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
  697. (npix + 1) * sizeof(Pixel));
  698. if (!ppix)
  699. return (BadAlloc);
  700. ppix[npix] = pixR;
  701. pmap->clientPixelsRed[client] = ppix;
  702. pmap->numPixelsRed[client]++;
  703. break;
  704. case TrueColor:
  705. /* Look up each component in its own map, then OR them together */
  706. pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
  707. pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
  708. pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
  709. *pPix = (pixR << pVisual->offsetRed) |
  710. (pixG << pVisual->offsetGreen) |
  711. (pixB << pVisual->offsetBlue) | ALPHAMASK(pVisual);
  712. *pred = pmap->red[pixR].co.local.red;
  713. *pgreen = pmap->green[pixG].co.local.green;
  714. *pblue = pmap->blue[pixB].co.local.blue;
  715. npix = pmap->numPixelsRed[client];
  716. ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
  717. (npix + 1) * sizeof(Pixel));
  718. if (!ppix)
  719. return (BadAlloc);
  720. ppix[npix] = pixR;
  721. pmap->clientPixelsRed[client] = ppix;
  722. npix = pmap->numPixelsGreen[client];
  723. ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
  724. (npix + 1) * sizeof(Pixel));
  725. if (!ppix)
  726. return (BadAlloc);
  727. ppix[npix] = pixG;
  728. pmap->clientPixelsGreen[client] = ppix;
  729. npix = pmap->numPixelsBlue[client];
  730. ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
  731. (npix + 1) * sizeof(Pixel));
  732. if (!ppix)
  733. return (BadAlloc);
  734. ppix[npix] = pixB;
  735. pmap->clientPixelsBlue[client] = ppix;
  736. pmap->numPixelsRed[client]++;
  737. pmap->numPixelsGreen[client]++;
  738. pmap->numPixelsBlue[client]++;
  739. break;
  740. case GrayScale:
  741. case PseudoColor:
  742. if (pmap->mid != pmap->pScreen->defColormap &&
  743. pmap->pVisual->vid == pmap->pScreen->rootVisual) {
  744. ColormapPtr prootmap = (ColormapPtr)
  745. SecurityLookupIDByType(clients[client],
  746. pmap->pScreen->defColormap,
  747. RT_COLORMAP, SecurityReadAccess);
  748. if (pmap->class == prootmap->class)
  749. FindColorInRootCmap(prootmap, prootmap->red, entries, &rgb,
  750. pPix, PSEUDOMAP, AllComp);
  751. }
  752. if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
  753. client, AllComp) != Success)
  754. return (BadAlloc);
  755. break;
  756. case DirectColor:
  757. if (pmap->mid != pmap->pScreen->defColormap &&
  758. pmap->pVisual->vid == pmap->pScreen->rootVisual) {
  759. ColormapPtr prootmap = (ColormapPtr)
  760. SecurityLookupIDByType(clients[client],
  761. pmap->pScreen->defColormap,
  762. RT_COLORMAP, SecurityReadAccess);
  763. if (pmap->class == prootmap->class) {
  764. pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
  765. FindColorInRootCmap(prootmap, prootmap->red, entries, &rgb,
  766. &pixR, REDMAP, RedComp);
  767. pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
  768. FindColorInRootCmap(prootmap, prootmap->green, entries, &rgb,
  769. &pixG, GREENMAP, GreenComp);
  770. pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
  771. FindColorInRootCmap(prootmap, prootmap->blue, entries, &rgb,
  772. &pixB, BLUEMAP, BlueComp);
  773. *pPix = pixR | pixG | pixB;
  774. }
  775. }
  776. pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
  777. if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
  778. client, RedComp) != Success)
  779. return (BadAlloc);
  780. pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
  781. if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
  782. GREENMAP, client, GreenComp) != Success) {
  783. (void) FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel) 0);
  784. return (BadAlloc);
  785. }
  786. pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
  787. if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
  788. client, BlueComp) != Success) {
  789. (void) FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel) 0);
  790. (void) FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel) 0);
  791. return (BadAlloc);
  792. }
  793. *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual);
  794. break;
  795. }
  796. /* if this is the client's first pixel in this colormap, tell the
  797. * resource manager that the client has pixels in this colormap which
  798. * should be freed when the client dies */
  799. if ((pmap->numPixelsRed[client] == 1) &&
  800. (CLIENT_ID(pmap->mid) != client) && !(pmap->flags & BeingCreated)) {
  801. colorResource *pcr;
  802. pcr = malloc(sizeof(colorResource));
  803. if (!pcr) {
  804. (void) FreeColors(pmap, client, 1, pPix, (Pixel) 0);
  805. return (BadAlloc);
  806. }
  807. pcr->mid = pmap->mid;
  808. pcr->client = client;
  809. if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
  810. return (BadAlloc);
  811. }
  812. return (Success);
  813. }
  814. /*
  815. * FakeAllocColor -- fake an AllocColor request by
  816. * returning a free pixel if availible, otherwise returning
  817. * the closest matching pixel. This is used by the mi
  818. * software sprite code to recolor cursors. A nice side-effect
  819. * is that this routine will never return failure.
  820. */
  821. _X_EXPORT void
  822. FakeAllocColor(register ColormapPtr pmap, register xColorItem * item)
  823. {
  824. Pixel pixR, pixG, pixB;
  825. Pixel temp;
  826. int entries;
  827. xrgb rgb;
  828. int class;
  829. VisualPtr pVisual;
  830. pVisual = pmap->pVisual;
  831. rgb.red = item->red;
  832. rgb.green = item->green;
  833. rgb.blue = item->blue;
  834. (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
  835. class = pmap->class;
  836. entries = pVisual->ColormapEntries;
  837. switch (class) {
  838. case GrayScale:
  839. case PseudoColor:
  840. item->pixel = 0;
  841. if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
  842. -1, AllComp) == Success) {
  843. item->pixel = temp;
  844. break;
  845. }
  846. /* fall through ... */
  847. case StaticColor:
  848. case StaticGray:
  849. item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
  850. break;
  851. case DirectColor:
  852. /* Look up each component in its own map, then OR them together */
  853. pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed;
  854. pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  855. pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  856. if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
  857. -1, RedComp) != Success)
  858. pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
  859. << pVisual->offsetRed;
  860. if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
  861. GREENMAP, -1, GreenComp) != Success)
  862. pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
  863. GREENMAP) << pVisual->offsetGreen;
  864. if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
  865. -1, BlueComp) != Success)
  866. pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
  867. << pVisual->offsetBlue;
  868. item->pixel = pixR | pixG | pixB;
  869. break;
  870. case TrueColor:
  871. /* Look up each component in its own map, then OR them together */
  872. pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
  873. pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
  874. pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
  875. item->pixel = (pixR << pVisual->offsetRed) |
  876. (pixG << pVisual->offsetGreen) | (pixB << pVisual->offsetBlue);
  877. break;
  878. }
  879. }
  880. /* free a pixel value obtained from FakeAllocColor */
  881. _X_EXPORT void
  882. FakeFreeColor(register ColormapPtr pmap, Pixel pixel)
  883. {
  884. VisualPtr pVisual;
  885. Pixel pixR, pixG, pixB;
  886. switch (pmap->class) {
  887. case GrayScale:
  888. case PseudoColor:
  889. if (pmap->red[pixel].refcnt == AllocTemporary)
  890. pmap->red[pixel].refcnt = 0;
  891. break;
  892. case DirectColor:
  893. pVisual = pmap->pVisual;
  894. pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed;
  895. pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  896. pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  897. if (pmap->red[pixR].refcnt == AllocTemporary)
  898. pmap->red[pixR].refcnt = 0;
  899. if (pmap->green[pixG].refcnt == AllocTemporary)
  900. pmap->green[pixG].refcnt = 0;
  901. if (pmap->blue[pixB].refcnt == AllocTemporary)
  902. pmap->blue[pixB].refcnt = 0;
  903. break;
  904. }
  905. }
  906. typedef unsigned short BigNumUpper;
  907. typedef unsigned long BigNumLower;
  908. #define BIGNUMLOWERBITS 24
  909. #define BIGNUMUPPERBITS 16
  910. #define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
  911. #define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
  912. #define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
  913. #define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
  914. typedef struct _bignum {
  915. BigNumUpper upper;
  916. BigNumLower lower;
  917. } BigNumRec, *BigNumPtr;
  918. #define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
  919. ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
  920. #define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
  921. ((r)->lower = LOWERPART(u)))
  922. #define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
  923. ((r)->lower = BIGNUMLOWER-1))
  924. static void
  925. BigNumAdd(BigNumPtr x, BigNumPtr y, BigNumPtr r)
  926. {
  927. BigNumLower lower, carry = 0;
  928. lower = x->lower + y->lower;
  929. if (lower >= BIGNUMLOWER) {
  930. lower -= BIGNUMLOWER;
  931. carry = 1;
  932. }
  933. r->lower = lower;
  934. r->upper = x->upper + y->upper + carry;
  935. }
  936. static Pixel
  937. FindBestPixel(EntryPtr pentFirst, int size, xrgb * prgb, int channel)
  938. {
  939. EntryPtr pent;
  940. Pixel pixel, final;
  941. long dr, dg, db;
  942. unsigned long sq;
  943. BigNumRec minval, sum, temp;
  944. final = 0;
  945. MaxBigNum(&minval);
  946. /* look for the minimal difference */
  947. for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) {
  948. dr = dg = db = 0;
  949. switch (channel) {
  950. case PSEUDOMAP:
  951. dg = (long) pent->co.local.green - prgb->green;
  952. db = (long) pent->co.local.blue - prgb->blue;
  953. case REDMAP:
  954. dr = (long) pent->co.local.red - prgb->red;
  955. break;
  956. case GREENMAP:
  957. dg = (long) pent->co.local.green - prgb->green;
  958. break;
  959. case BLUEMAP:
  960. db = (long) pent->co.local.blue - prgb->blue;
  961. break;
  962. }
  963. sq = dr * dr;
  964. UnsignedToBigNum(sq, &sum);
  965. sq = dg * dg;
  966. UnsignedToBigNum(sq, &temp);
  967. BigNumAdd(&sum, &temp, &sum);
  968. sq = db * db;
  969. UnsignedToBigNum(sq, &temp);
  970. BigNumAdd(&sum, &temp, &sum);
  971. if (BigNumGreater(&minval, &sum)) {
  972. final = pixel;
  973. minval = sum;
  974. }
  975. }
  976. return (final);
  977. }
  978. static void
  979. FindColorInRootCmap(ColormapPtr pmap, EntryPtr pentFirst, int size,
  980. xrgb * prgb, Pixel * pPixel, int channel,
  981. ColorCompareProcPtr comp)
  982. {
  983. EntryPtr pent;
  984. Pixel pixel;
  985. int count;
  986. if ((pixel = *pPixel) >= size)
  987. pixel = 0;
  988. for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) {
  989. if (pent->refcnt > 0 && (*comp) (pent, prgb)) {
  990. switch (channel) {
  991. case REDMAP:
  992. pixel <<= pmap->pVisual->offsetRed;
  993. break;
  994. case GREENMAP:
  995. pixel <<= pmap->pVisual->offsetGreen;
  996. break;
  997. case BLUEMAP:
  998. pixel <<= pmap->pVisual->offsetBlue;
  999. break;
  1000. default: /* PSEUDOMAP */
  1001. break;
  1002. }
  1003. *pPixel = pixel;
  1004. }
  1005. }
  1006. }
  1007. /* Tries to find a color in pmap that exactly matches the one requested in prgb
  1008. * if it can't it allocates one.
  1009. * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
  1010. * load *pPixel with that value, otherwise set it to 0
  1011. */
  1012. int
  1013. FindColor(ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb * prgb,
  1014. Pixel * pPixel, int channel, int client, ColorCompareProcPtr comp)
  1015. {
  1016. EntryPtr pent;
  1017. Bool foundFree;
  1018. Pixel pixel, Free = 0;
  1019. int npix, count, *nump = NULL;
  1020. Pixel **pixp = NULL, *ppix;
  1021. xColorItem def;
  1022. foundFree = FALSE;
  1023. if ((pixel = *pPixel) >= size)
  1024. pixel = 0;
  1025. /* see if there is a match, and also look for a free entry */
  1026. for (pent = pentFirst + pixel, count = size; --count >= 0;) {
  1027. if (pent->refcnt > 0) {
  1028. if ((*comp) (pent, prgb)) {
  1029. if (client >= 0)
  1030. pent->refcnt++;
  1031. *pPixel = pixel;
  1032. switch (channel) {
  1033. case REDMAP:
  1034. *pPixel <<= pmap->pVisual->offsetRed;
  1035. case PSEUDOMAP:
  1036. break;
  1037. case GREENMAP:
  1038. *pPixel <<= pmap->pVisual->offsetGreen;
  1039. break;
  1040. case BLUEMAP:
  1041. *pPixel <<= pmap->pVisual->offsetBlue;
  1042. break;
  1043. }
  1044. goto gotit;
  1045. }
  1046. }
  1047. else if (!foundFree && pent->refcnt == 0) {
  1048. Free = pixel;
  1049. foundFree = TRUE;
  1050. /* If we're initializing the colormap, then we are looking for
  1051. * the first free cell we can find, not to minimize the number
  1052. * of entries we use. So don't look any further. */
  1053. if (pmap->flags & BeingCreated)
  1054. break;
  1055. }
  1056. pixel++;
  1057. if (pixel >= size) {
  1058. pent = pentFirst;
  1059. pixel = 0;
  1060. }
  1061. else
  1062. pent++;
  1063. }
  1064. /* If we got here, we didn't find a match. If we also didn't find
  1065. * a free entry, we're out of luck. Otherwise, we'll usurp a free
  1066. * entry and fill it in */
  1067. if (!foundFree)
  1068. return (BadAlloc);
  1069. pent = pentFirst + Free;
  1070. pent->fShared = FALSE;
  1071. pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
  1072. switch (channel) {
  1073. case PSEUDOMAP:
  1074. pent->co.local.red = prgb->red;
  1075. pent->co.local.green = prgb->green;
  1076. pent->co.local.blue = prgb->blue;
  1077. def.red = prgb->red;
  1078. def.green = prgb->green;
  1079. def.blue = prgb->blue;
  1080. def.flags = (DoRed | DoGreen | DoBlue);
  1081. if (client >= 0)
  1082. pmap->freeRed--;
  1083. def.pixel = Free;
  1084. break;
  1085. case REDMAP:
  1086. pent->co.local.red = prgb->red;
  1087. def.red = prgb->red;
  1088. def.green = pmap->green[0].co.local.green;
  1089. def.blue = pmap->blue[0].co.local.blue;
  1090. def.flags = DoRed;
  1091. if (client >= 0)
  1092. pmap->freeRed--;
  1093. def.pixel = Free << pmap->pVisual->offsetRed;
  1094. break;
  1095. case GREENMAP:
  1096. pent->co.local.green = prgb->green;
  1097. def.red = pmap->red[0].co.local.red;
  1098. def.green = prgb->green;
  1099. def.blue = pmap->blue[0].co.local.blue;
  1100. def.flags = DoGreen;
  1101. if (client >= 0)
  1102. pmap->freeGreen--;
  1103. def.pixel = Free << pmap->pVisual->offsetGreen;
  1104. break;
  1105. case BLUEMAP:
  1106. pent->co.local.blue = prgb->blue;
  1107. def.red = pmap->red[0].co.local.red;
  1108. def.green = pmap->green[0].co.local.green;
  1109. def.blue = prgb->blue;
  1110. def.flags = DoBlue;
  1111. if (client >= 0)
  1112. pmap->freeBlue--;
  1113. def.pixel = Free << pmap->pVisual->offsetBlue;
  1114. break;
  1115. }
  1116. (*pmap->pScreen->StoreColors) (pmap, 1, &def);
  1117. pixel = Free;
  1118. *pPixel = def.pixel;
  1119. gotit:
  1120. if (pmap->flags & BeingCreated || client == -1)
  1121. return (Success);
  1122. /* Now remember the pixel, for freeing later */
  1123. switch (channel) {
  1124. case PSEUDOMAP:
  1125. case REDMAP:
  1126. nump = pmap->numPixelsRed;
  1127. pixp = pmap->clientPixelsRed;
  1128. break;
  1129. case GREENMAP:
  1130. nump = pmap->numPixelsGreen;
  1131. pixp = pmap->clientPixelsGreen;
  1132. break;
  1133. case BLUEMAP:
  1134. nump = pmap->numPixelsBlue;
  1135. pixp = pmap->clientPixelsBlue;
  1136. break;
  1137. }
  1138. npix = nump[client];
  1139. ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel));
  1140. if (!ppix) {
  1141. pent->refcnt--;
  1142. if (!pent->fShared)
  1143. switch (channel) {
  1144. case PSEUDOMAP:
  1145. case REDMAP:
  1146. pmap->freeRed++;
  1147. break;
  1148. case GREENMAP:
  1149. pmap->freeGreen++;
  1150. break;
  1151. case BLUEMAP:
  1152. pmap->freeBlue++;
  1153. break;
  1154. }
  1155. return (BadAlloc);
  1156. }
  1157. ppix[npix] = pixel;
  1158. pixp[client] = ppix;
  1159. nump[client]++;
  1160. return (Success);
  1161. }
  1162. /* Comparison functions -- passed to FindColor to determine if an
  1163. * entry is already the color we're looking for or not */
  1164. static int
  1165. AllComp(EntryPtr pent, xrgb * prgb)
  1166. {
  1167. if ((pent->co.local.red == prgb->red) &&
  1168. (pent->co.local.green == prgb->green) &&
  1169. (pent->co.local.blue == prgb->blue))
  1170. return (1);
  1171. return (0);
  1172. }
  1173. static int
  1174. RedComp(EntryPtr pent, xrgb * prgb)
  1175. {
  1176. if (pent->co.local.red == prgb->red)
  1177. return (1);
  1178. return (0);
  1179. }
  1180. static int
  1181. GreenComp(EntryPtr pent, xrgb * prgb)
  1182. {
  1183. if (pent->co.local.green == prgb->green)
  1184. return (1);
  1185. return (0);
  1186. }
  1187. static int
  1188. BlueComp(EntryPtr pent, xrgb * prgb)
  1189. {
  1190. if (pent->co.local.blue == prgb->blue)
  1191. return (1);
  1192. return (0);
  1193. }
  1194. /* Read the color value of a cell */
  1195. _X_EXPORT int
  1196. QueryColors(ColormapPtr pmap, int count, Pixel * ppixIn, xrgb * prgbList)
  1197. {
  1198. Pixel *ppix, pixel;
  1199. xrgb *prgb;
  1200. VisualPtr pVisual;
  1201. EntryPtr pent;
  1202. Pixel i;
  1203. int errVal = Success;
  1204. pVisual = pmap->pVisual;
  1205. if ((pmap->class | DynamicClass) == DirectColor) {
  1206. int numred, numgreen, numblue;
  1207. Pixel rgbbad;
  1208. numred = NUMRED(pVisual);
  1209. numgreen = NUMGREEN(pVisual);
  1210. numblue = NUMBLUE(pVisual);
  1211. rgbbad = ~RGBMASK(pVisual);
  1212. for (ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) {
  1213. pixel = *ppix;
  1214. if (pixel & rgbbad) {
  1215. clientErrorValue = pixel;
  1216. errVal = BadValue;
  1217. continue;
  1218. }
  1219. i = (pixel & pVisual->redMask) >> pVisual->offsetRed;
  1220. if (i >= numred) {
  1221. clientErrorValue = pixel;
  1222. errVal = BadValue;
  1223. continue;
  1224. }
  1225. prgb->red = pmap->red[i].co.local.red;
  1226. i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  1227. if (i >= numgreen) {
  1228. clientErrorValue = pixel;
  1229. errVal = BadValue;
  1230. continue;
  1231. }
  1232. prgb->green = pmap->green[i].co.local.green;
  1233. i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  1234. if (i >= numblue) {
  1235. clientErrorValue = pixel;
  1236. errVal = BadValue;
  1237. continue;
  1238. }
  1239. prgb->blue = pmap->blue[i].co.local.blue;
  1240. }
  1241. }
  1242. else {
  1243. for (ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) {
  1244. pixel = *ppix;
  1245. if (pixel >= pVisual->ColormapEntries) {
  1246. clientErrorValue = pixel;
  1247. errVal = BadValue;
  1248. }
  1249. else {
  1250. pent = (EntryPtr) & pmap->red[pixel];
  1251. if (pent->fShared) {
  1252. prgb->red = pent->co.shco.red->color;
  1253. prgb->green = pent->co.shco.green->color;
  1254. prgb->blue = pent->co.shco.blue->color;
  1255. }
  1256. else {
  1257. prgb->red = pent->co.local.red;
  1258. prgb->green = pent->co.local.green;
  1259. prgb->blue = pent->co.local.blue;
  1260. }
  1261. }
  1262. }
  1263. }
  1264. return (errVal);
  1265. }
  1266. static void
  1267. FreePixels(register ColormapPtr pmap, register int client)
  1268. {
  1269. Pixel *ppix, *ppixStart;
  1270. int class, n;
  1271. class = pmap->class;
  1272. ppixStart = pmap->clientPixelsRed[client];
  1273. if (class & DynamicClass) {
  1274. n = pmap->numPixelsRed[client];
  1275. for (ppix = ppixStart; --n >= 0;) {
  1276. FreeCell(pmap, *ppix, REDMAP);
  1277. ppix++;
  1278. }
  1279. }
  1280. free(ppixStart);
  1281. pmap->clientPixelsRed[client] = (Pixel *) NULL;
  1282. pmap->numPixelsRed[client] = 0;
  1283. if ((class | DynamicClass) == DirectColor) {
  1284. ppixStart = pmap->clientPixelsGreen[client];
  1285. if (class & DynamicClass)
  1286. for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
  1287. FreeCell(pmap, *ppix++, GREENMAP);
  1288. free(ppixStart);
  1289. pmap->clientPixelsGreen[client] = (Pixel *) NULL;
  1290. pmap->numPixelsGreen[client] = 0;
  1291. ppixStart = pmap->clientPixelsBlue[client];
  1292. if (class & DynamicClass)
  1293. for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0;)
  1294. FreeCell(pmap, *ppix++, BLUEMAP);
  1295. free(ppixStart);
  1296. pmap->clientPixelsBlue[client] = (Pixel *) NULL;
  1297. pmap->numPixelsBlue[client] = 0;
  1298. }
  1299. }
  1300. /**
  1301. * Frees all of a client's colors and cells.
  1302. *
  1303. * \param value must conform to DeleteType
  1304. * \unused fakeid
  1305. */
  1306. int
  1307. FreeClientPixels(pointer value, XID fakeid)
  1308. {
  1309. ColormapPtr pmap;
  1310. colorResource *pcr = (colorResource *) value;
  1311. pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP);
  1312. if (pmap)
  1313. FreePixels(pmap, pcr->client);
  1314. free(pcr);
  1315. return Success;
  1316. }
  1317. int
  1318. AllocColorCells(int client, ColormapPtr pmap, int colors, int planes,
  1319. Bool contig, Pixel * ppix, Pixel * masks)
  1320. {
  1321. Pixel rmask, gmask, bmask, *ppixFirst, r, g, b;
  1322. int n, class;
  1323. int ok;
  1324. int oldcount;
  1325. colorResource *pcr = (colorResource *) NULL;
  1326. class = pmap->class;
  1327. if (!(class & DynamicClass))
  1328. return (BadAlloc); /* Shouldn't try on this type */
  1329. oldcount = pmap->numPixelsRed[client];
  1330. if (pmap->class == DirectColor)
  1331. oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
  1332. if (!oldcount && (CLIENT_ID(pmap->mid) != client)) {
  1333. pcr = malloc(sizeof(colorResource));
  1334. if (!pcr)
  1335. return (BadAlloc);
  1336. }
  1337. if (pmap->class == DirectColor) {
  1338. ok = AllocDirect(client, pmap, colors, planes, planes, planes,
  1339. contig, ppix, &rmask, &gmask, &bmask);
  1340. if (ok == Success) {
  1341. for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) {
  1342. while (!(rmask & r))
  1343. r += r;
  1344. while (!(gmask & g))
  1345. g += g;
  1346. while (!(bmask & b))
  1347. b += b;
  1348. *masks++ = r | g | b;
  1349. }
  1350. }
  1351. }
  1352. else {
  1353. ok = AllocPseudo(client, pmap, colors, planes, contig, ppix, &rmask,
  1354. &ppixFirst);
  1355. if (ok == Success) {
  1356. for (r = 1, n = planes; --n >= 0; r += r) {
  1357. while (!(rmask & r))
  1358. r += r;
  1359. *masks++ = r;
  1360. }
  1361. }
  1362. }
  1363. /* if this is the client's first pixels in this colormap, tell the
  1364. * resource manager that the client has pixels in this colormap which
  1365. * should be freed when the client dies */
  1366. if ((ok == Success) && pcr) {
  1367. pcr->mid = pmap->mid;
  1368. pcr->client = client;
  1369. if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
  1370. ok = BadAlloc;
  1371. }
  1372. else if (pcr)
  1373. free(pcr);
  1374. return (ok);
  1375. }
  1376. int
  1377. AllocColorPlanes(int client, ColormapPtr pmap, int colors,
  1378. int r, int g, int b, Bool contig, Pixel * pixels,
  1379. Pixel * prmask, Pixel * pgmask, Pixel * pbmask)
  1380. {
  1381. int ok;
  1382. Pixel mask, *ppixFirst;
  1383. Pixel shift;
  1384. int i;
  1385. int class;
  1386. int oldcount;
  1387. colorResource *pcr = (colorResource *) NULL;
  1388. class = pmap->class;
  1389. if (!(class & DynamicClass))
  1390. return (BadAlloc); /* Shouldn't try on this type */
  1391. oldcount = pmap->numPixelsRed[client];
  1392. if (class == DirectColor)
  1393. oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
  1394. if (!oldcount && (CLIENT_ID(pmap->mid) != client)) {
  1395. pcr = malloc(sizeof(colorResource));
  1396. if (!pcr)
  1397. return (BadAlloc);
  1398. }
  1399. if (class == DirectColor) {
  1400. ok = AllocDirect(client, pmap, colors, r, g, b, contig, pixels,
  1401. prmask, pgmask, pbmask);
  1402. }
  1403. else {
  1404. /* Allocate the proper pixels */
  1405. /* XXX This is sort of bad, because of contig is set, we force all
  1406. * r + g + b bits to be contiguous. Should only force contiguity
  1407. * per mask
  1408. */
  1409. ok = AllocPseudo(client, pmap, colors, r + g + b, contig, pixels,
  1410. &mask, &ppixFirst);
  1411. if (ok == Success) {
  1412. /* now split that mask into three */
  1413. *prmask = *pgmask = *pbmask = 0;
  1414. shift = 1;
  1415. for (i = r; --i >= 0; shift += shift) {
  1416. while (!(mask & shift))
  1417. shift += shift;
  1418. *prmask |= shift;
  1419. }
  1420. for (i = g; --i >= 0; shift += shift) {
  1421. while (!(mask & shift))
  1422. shift += shift;
  1423. *pgmask |= shift;
  1424. }
  1425. for (i = b; --i >= 0; shift += shift) {
  1426. while (!(mask & shift))
  1427. shift += shift;
  1428. *pbmask |= shift;
  1429. }
  1430. /* set up the shared color cells */
  1431. if (!AllocShared(pmap, pixels, colors, r, g, b,
  1432. *prmask, *pgmask, *pbmask, ppixFirst)) {
  1433. (void) FreeColors(pmap, client, colors, pixels, mask);
  1434. ok = BadAlloc;
  1435. }
  1436. }
  1437. }
  1438. /* if this is the client's first pixels in this colormap, tell the
  1439. * resource manager that the client has pixels in this colormap which
  1440. * should be freed when the client dies */
  1441. if ((ok == Success) && pcr) {
  1442. pcr->mid = pmap->mid;
  1443. pcr->client = client;
  1444. if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
  1445. ok = BadAlloc;
  1446. }
  1447. else if (pcr)
  1448. free(pcr);
  1449. return (ok);
  1450. }
  1451. static int
  1452. AllocDirect(int client, ColormapPtr pmap, int c, int r, int g, int b,
  1453. Bool contig, Pixel * pixels, Pixel * prmask, Pixel * pgmask,
  1454. Pixel * pbmask)
  1455. {
  1456. Pixel *ppixRed, *ppixGreen, *ppixBlue;
  1457. Pixel *ppix, *pDst, *p;
  1458. int npix, npixR, npixG, npixB;
  1459. Bool okR, okG, okB;
  1460. Pixel *rpix = 0, *gpix = 0, *bpix = 0;
  1461. npixR = c << r;
  1462. npixG = c << g;
  1463. npixB = c << b;
  1464. if ((r >= 32) || (g >= 32) || (b >= 32) ||
  1465. (npixR > pmap->freeRed) || (npixR < c) ||
  1466. (npixG > pmap->freeGreen) || (npixG < c) ||
  1467. (npixB > pmap->freeBlue) || (npixB < c))
  1468. return BadAlloc;
  1469. /* start out with empty pixels */
  1470. for (p = pixels; p < pixels + c; p++)
  1471. *p = 0;
  1472. ppixRed = (Pixel *) ALLOCATE_LOCAL(npixR * sizeof(Pixel));
  1473. ppixGreen = (Pixel *) ALLOCATE_LOCAL(npixG * sizeof(Pixel));
  1474. ppixBlue = (Pixel *) ALLOCATE_LOCAL(npixB * sizeof(Pixel));
  1475. if (!ppixRed || !ppixGreen || !ppixBlue) {
  1476. if (ppixBlue)
  1477. DEALLOCATE_LOCAL(ppixBlue);
  1478. if (ppixGreen)
  1479. DEALLOCATE_LOCAL(ppixGreen);
  1480. if (ppixRed)
  1481. DEALLOCATE_LOCAL(ppixRed);
  1482. return (BadAlloc);
  1483. }
  1484. okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
  1485. okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
  1486. okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
  1487. if (okR && okG && okB) {
  1488. rpix = (Pixel *) realloc(pmap->clientPixelsRed[client],
  1489. (pmap->numPixelsRed[client] + (c << r)) *
  1490. sizeof(Pixel));
  1491. if (rpix)
  1492. pmap->clientPixelsRed[client] = rpix;
  1493. gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
  1494. (pmap->numPixelsGreen[client] + (c << g)) *
  1495. sizeof(Pixel));
  1496. if (gpix)
  1497. pmap->clientPixelsGreen[client] = gpix;
  1498. bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
  1499. (pmap->numPixelsBlue[client] + (c << b)) *
  1500. sizeof(Pixel));
  1501. if (bpix)
  1502. pmap->clientPixelsBlue[client] = bpix;
  1503. }
  1504. if (!okR || !okG || !okB || !rpix || !gpix || !bpix) {
  1505. if (okR)
  1506. for (ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
  1507. pmap->red[*ppix].refcnt = 0;
  1508. if (okG)
  1509. for (ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
  1510. pmap->green[*ppix].refcnt = 0;
  1511. if (okB)
  1512. for (ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
  1513. pmap->blue[*ppix].refcnt = 0;
  1514. DEALLOCATE_LOCAL(ppixBlue);
  1515. DEALLOCATE_LOCAL(ppixGreen);
  1516. DEALLOCATE_LOCAL(ppixRed);
  1517. return (BadAlloc);
  1518. }
  1519. *prmask <<= pmap->pVisual->offsetRed;
  1520. *pgmask <<= pmap->pVisual->offsetGreen;
  1521. *pbmask <<= pmap->pVisual->offsetBlue;
  1522. ppix = rpix + pmap->numPixelsRed[client];
  1523. for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) {
  1524. *ppix++ = *p;
  1525. if (p < ppixRed + c)
  1526. *pDst++ |= *p << pmap->pVisual->offsetRed;
  1527. }
  1528. pmap->numPixelsRed[client] += npixR;
  1529. pmap->freeRed -= npixR;
  1530. ppix = gpix + pmap->numPixelsGreen[client];
  1531. for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) {
  1532. *ppix++ = *p;
  1533. if (p < ppixGreen + c)
  1534. *pDst++ |= *p << pmap->pVisual->offsetGreen;
  1535. }
  1536. pmap->numPixelsGreen[client] += npixG;
  1537. pmap->freeGreen -= npixG;
  1538. ppix = bpix + pmap->numPixelsBlue[client];
  1539. for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) {
  1540. *ppix++ = *p;
  1541. if (p < ppixBlue + c)
  1542. *pDst++ |= *p << pmap->pVisual->offsetBlue;
  1543. }
  1544. pmap->numPixelsBlue[client] += npixB;
  1545. pmap->freeBlue -= npixB;
  1546. for (pDst = pixels; pDst < pixels + c; pDst++)
  1547. *pDst |= ALPHAMASK(pmap->pVisual);
  1548. DEALLOCATE_LOCAL(ppixBlue);
  1549. DEALLOCATE_LOCAL(ppixGreen);
  1550. DEALLOCATE_LOCAL(ppixRed);
  1551. return (Success);
  1552. }
  1553. static int
  1554. AllocPseudo(int client, ColormapPtr pmap, int c, int r, Bool contig,
  1555. Pixel * pixels, Pixel * pmask, Pixel ** pppixFirst)
  1556. {
  1557. Pixel *ppix, *p, *pDst, *ppixTemp;
  1558. int npix;
  1559. Bool ok;
  1560. npix = c << r;
  1561. if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
  1562. return (BadAlloc);
  1563. if (!(ppixTemp = (Pixel *) ALLOCATE_LOCAL(npix * sizeof(Pixel))))
  1564. return (BadAlloc);
  1565. ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
  1566. if (ok) {
  1567. /* all the allocated pixels are added to the client pixel list,
  1568. * but only the unique ones are returned to the client */
  1569. ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
  1570. (pmap->numPixelsRed[client] +
  1571. npix) * sizeof(Pixel));
  1572. if (!ppix) {
  1573. for (p = ppixTemp; p < ppixTemp + npix; p++)
  1574. pmap->red[*p].refcnt = 0;
  1575. return (BadAlloc);
  1576. }
  1577. pmap->clientPixelsRed[client] = ppix;
  1578. ppix += pmap->numPixelsRed[client];
  1579. *pppixFirst = ppix;
  1580. pDst = pixels;
  1581. for (p = ppixTemp; p < ppixTemp + npix; p++) {
  1582. *ppix++ = *p;
  1583. if (p < ppixTemp + c)
  1584. *pDst++ = *p;
  1585. }
  1586. pmap->numPixelsRed[client] += npix;
  1587. pmap->freeRed -= npix;
  1588. }
  1589. DEALLOCATE_LOCAL(ppixTemp);
  1590. return (ok ? Success : BadAlloc);
  1591. }
  1592. /* Allocates count << planes pixels from colormap pmap for client. If
  1593. * contig, then the plane mask is made of consecutive bits. Returns
  1594. * all count << pixels in the array pixels. The first count of those
  1595. * pixels are the unique pixels. *pMask has the mask to Or with the
  1596. * unique pixels to get the rest of them.
  1597. *
  1598. * Returns True iff all pixels could be allocated
  1599. * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
  1600. * (see AllocShared for why we care)
  1601. */
  1602. static Bool
  1603. AllocCP(ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
  1604. Bool contig, Pixel * pixels, Pixel * pMask)
  1605. {
  1606. EntryPtr ent;
  1607. Pixel pixel, base, entries, maxp, save;
  1608. int dplanes, found;
  1609. Pixel *ppix;
  1610. Pixel mask;
  1611. Pixel finalmask;
  1612. dplanes = pmap->pVisual->nplanes;
  1613. /* Easy case. Allocate pixels only */
  1614. if (planes == 0) {
  1615. /* allocate writable entries */
  1616. ppix = pixels;
  1617. ent = pentFirst;
  1618. pixel = 0;
  1619. while (--count >= 0) {
  1620. /* Just find count unallocated cells */
  1621. while (ent->refcnt) {
  1622. ent++;
  1623. pixel++;
  1624. }
  1625. ent->refcnt = AllocPrivate;
  1626. *ppix++ = pixel;
  1627. ent->fShared = FALSE;
  1628. }
  1629. *pMask = 0;
  1630. return (TRUE);
  1631. }
  1632. else if (planes > dplanes) {
  1633. return (FALSE);
  1634. }
  1635. /* General case count pixels * 2 ^ planes cells to be allocated */
  1636. /* make room for new pixels */
  1637. ent = pentFirst;
  1638. /* first try for contiguous planes, since it's fastest */
  1639. for (mask = (((Pixel) 1) << planes) - 1, base = 1, dplanes -= (planes - 1);
  1640. --dplanes >= 0; mask += mask, base += base) {
  1641. ppix = pixels;
  1642. found = 0;
  1643. pixel = 0;
  1644. entries = pmap->pVisual->ColormapEntries - mask;
  1645. while (pixel < entries) {
  1646. save = pixel;
  1647. maxp = pixel + mask + base;
  1648. /* check if all are free */
  1649. while (pixel != maxp && ent[pixel].refcnt == 0)
  1650. pixel += base;
  1651. if (pixel == maxp) {
  1652. /* this one works */
  1653. *ppix++ = save;
  1654. found++;
  1655. if (found == count) {
  1656. /* found enough, allocate them all */
  1657. while (--count >= 0) {
  1658. pixel = pixels[count];
  1659. maxp = pixel + mask;
  1660. while (1) {
  1661. ent[pixel].refcnt = AllocPrivate;
  1662. ent[pixel].fShared = FALSE;
  1663. if (pixel == maxp)
  1664. break;
  1665. pixel += base;
  1666. *ppix++ = pixel;
  1667. }
  1668. }
  1669. *pMask = mask;
  1670. return (TRUE);
  1671. }
  1672. }
  1673. pixel = save + 1;
  1674. if (pixel & mask)
  1675. pixel += mask;
  1676. }
  1677. }
  1678. dplanes = pmap->pVisual->nplanes;
  1679. if (contig || planes == 1 || dplanes < 3)
  1680. return (FALSE);
  1681. /* this will be very slow for large maps, need a better algorithm */
  1682. /*
  1683. we can generate the smallest and largest numbers that fits in dplanes
  1684. bits and contain exactly planes bits set as follows. First, we need to
  1685. check that it is possible to generate such a mask at all.
  1686. (Non-contiguous masks need one more bit than contiguous masks). Then
  1687. the smallest such mask consists of the rightmost planes-1 bits set, then
  1688. a zero, then a one in position planes + 1. The formula is
  1689. (3 << (planes-1)) -1
  1690. The largest such masks consists of the leftmost planes-1 bits set, then
  1691. a zero, then a one bit in position dplanes-planes-1. If dplanes is
  1692. smaller than 32 (the number of bits in a word) then the formula is:
  1693. (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
  1694. If dplanes = 32, then we can't calculate (1<<dplanes) and we have
  1695. to use:
  1696. ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
  1697. << Thank you, Loretta>>>
  1698. */
  1699. finalmask =
  1700. (((((Pixel) 1) << (planes - 1)) - 1) << (dplanes - planes + 1)) +
  1701. (((Pixel) 1) << (dplanes - planes - 1));
  1702. for (mask = (((Pixel) 3) << (planes - 1)) - 1; mask <= finalmask; mask++) {
  1703. /* next 3 magic statements count number of ones (HAKMEM #169) */
  1704. pixel = (mask >> 1) & 033333333333;
  1705. pixel = mask - pixel - ((pixel >> 1) & 033333333333);
  1706. if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
  1707. continue;
  1708. ppix = pixels;
  1709. found = 0;
  1710. entries = pmap->pVisual->ColormapEntries - mask;
  1711. base = lowbit(mask);
  1712. for (pixel = 0; pixel < entries; pixel++) {
  1713. if (pixel & mask)
  1714. continue;
  1715. maxp = 0;
  1716. /* check if all are free */
  1717. while (ent[pixel + maxp].refcnt == 0) {
  1718. GetNextBitsOrBreak(maxp, mask, base);
  1719. }
  1720. if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
  1721. continue;
  1722. /* this one works */
  1723. *ppix++ = pixel;
  1724. found++;
  1725. if (found < count)
  1726. continue;
  1727. /* found enough, allocate them all */
  1728. while (--count >= 0) {
  1729. pixel = (pixels)[count];
  1730. maxp = 0;
  1731. while (1) {
  1732. ent[pixel + maxp].refcnt = AllocPrivate;
  1733. ent[pixel + maxp].fShared = FALSE;
  1734. GetNextBitsOrBreak(maxp, mask, base);
  1735. *ppix++ = pixel + maxp;
  1736. }
  1737. }
  1738. *pMask = mask;
  1739. return (TRUE);
  1740. }
  1741. }
  1742. return (FALSE);
  1743. }
  1744. /**
  1745. *
  1746. * \param ppixFirst First of the client's new pixels
  1747. */
  1748. static Bool
  1749. AllocShared(ColormapPtr pmap, Pixel * ppix, int c, int r, int g, int b,
  1750. Pixel rmask, Pixel gmask, Pixel bmask, Pixel * ppixFirst)
  1751. {
  1752. Pixel *pptr, *cptr;
  1753. int npix, z, npixClientNew, npixShared;
  1754. Pixel basemask, base, bits, common;
  1755. SHAREDCOLOR *pshared, **ppshared, **psharedList;
  1756. npixClientNew = c << (r + g + b);
  1757. npixShared = (c << r) + (c << g) + (c << b);
  1758. psharedList = (SHAREDCOLOR **) ALLOCATE_LOCAL(npixShared *
  1759. sizeof(SHAREDCOLOR *));
  1760. if (!psharedList)
  1761. return FALSE;
  1762. ppshared = psharedList;
  1763. for (z = npixShared; --z >= 0;) {
  1764. if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR)))) {
  1765. for (z++; z < npixShared; z++)
  1766. free(ppshared[z]);
  1767. return FALSE;
  1768. }
  1769. }
  1770. for (pptr = ppix, npix = c; --npix >= 0; pptr++) {
  1771. basemask = ~(gmask | bmask);
  1772. common = *pptr & basemask;
  1773. if (rmask) {
  1774. bits = 0;
  1775. base = lowbit(rmask);
  1776. while (1) {
  1777. pshared = *ppshared++;
  1778. pshared->refcnt = 1 << (g + b);
  1779. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1780. if ((*cptr & basemask) == (common | bits)) {
  1781. pmap->red[*cptr].fShared = TRUE;
  1782. pmap->red[*cptr].co.shco.red = pshared;
  1783. }
  1784. }
  1785. GetNextBitsOrBreak(bits, rmask, base);
  1786. }
  1787. }
  1788. else {
  1789. pshared = *ppshared++;
  1790. pshared->refcnt = 1 << (g + b);
  1791. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1792. if ((*cptr & basemask) == common) {
  1793. pmap->red[*cptr].fShared = TRUE;
  1794. pmap->red[*cptr].co.shco.red = pshared;
  1795. }
  1796. }
  1797. }
  1798. basemask = ~(rmask | bmask);
  1799. common = *pptr & basemask;
  1800. if (gmask) {
  1801. bits = 0;
  1802. base = lowbit(gmask);
  1803. while (1) {
  1804. pshared = *ppshared++;
  1805. pshared->refcnt = 1 << (r + b);
  1806. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1807. if ((*cptr & basemask) == (common | bits)) {
  1808. pmap->red[*cptr].co.shco.green = pshared;
  1809. }
  1810. }
  1811. GetNextBitsOrBreak(bits, gmask, base);
  1812. }
  1813. }
  1814. else {
  1815. pshared = *ppshared++;
  1816. pshared->refcnt = 1 << (g + b);
  1817. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1818. if ((*cptr & basemask) == common) {
  1819. pmap->red[*cptr].co.shco.green = pshared;
  1820. }
  1821. }
  1822. }
  1823. basemask = ~(rmask | gmask);
  1824. common = *pptr & basemask;
  1825. if (bmask) {
  1826. bits = 0;
  1827. base = lowbit(bmask);
  1828. while (1) {
  1829. pshared = *ppshared++;
  1830. pshared->refcnt = 1 << (r + g);
  1831. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1832. if ((*cptr & basemask) == (common | bits)) {
  1833. pmap->red[*cptr].co.shco.blue = pshared;
  1834. }
  1835. }
  1836. GetNextBitsOrBreak(bits, bmask, base);
  1837. }
  1838. }
  1839. else {
  1840. pshared = *ppshared++;
  1841. pshared->refcnt = 1 << (g + b);
  1842. for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
  1843. if ((*cptr & basemask) == common) {
  1844. pmap->red[*cptr].co.shco.blue = pshared;
  1845. }
  1846. }
  1847. }
  1848. }
  1849. DEALLOCATE_LOCAL(psharedList);
  1850. return TRUE;
  1851. }
  1852. /** FreeColors
  1853. * Free colors and/or cells (probably slow for large numbers)
  1854. */
  1855. _X_EXPORT int
  1856. FreeColors(ColormapPtr pmap, int client, int count, Pixel * pixels, Pixel mask)
  1857. {
  1858. int rval, result, class;
  1859. Pixel rmask;
  1860. class = pmap->class;
  1861. if (pmap->flags & AllAllocated)
  1862. return (BadAccess);
  1863. if ((class | DynamicClass) == DirectColor) {
  1864. rmask = mask & RGBMASK(pmap->pVisual);
  1865. result = FreeCo(pmap, client, REDMAP, count, pixels,
  1866. mask & pmap->pVisual->redMask);
  1867. /* If any of the three calls fails, we must report that, if more
  1868. * than one fails, it's ok that we report the last one */
  1869. rval = FreeCo(pmap, client, GREENMAP, count, pixels,
  1870. mask & pmap->pVisual->greenMask);
  1871. if (rval != Success)
  1872. result = rval;
  1873. rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
  1874. mask & pmap->pVisual->blueMask);
  1875. if (rval != Success)
  1876. result = rval;
  1877. }
  1878. else {
  1879. rmask = mask & ((((Pixel) 1) << pmap->pVisual->nplanes) - 1);
  1880. result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
  1881. }
  1882. if ((mask != rmask) && count) {
  1883. clientErrorValue = *pixels | mask;
  1884. result = BadValue;
  1885. }
  1886. /* XXX should worry about removing any RT_CMAPENTRY resource */
  1887. return (result);
  1888. }
  1889. /**
  1890. * Helper for FreeColors -- frees all combinations of *newpixels and mask bits
  1891. * which the client has allocated in channel colormap cells of pmap.
  1892. * doesn't change newpixels if it doesn't need to
  1893. *
  1894. * \param pmap which colormap head
  1895. * \param color which sub-map, eg, RED, BLUE, PSEUDO
  1896. * \param npixIn number of pixels passed in
  1897. * \param ppixIn number of base pixels
  1898. * \param mask mask client gave us
  1899. */
  1900. static int
  1901. FreeCo(ColormapPtr pmap, int client, int color, int npixIn, Pixel * ppixIn,
  1902. Pixel mask)
  1903. {
  1904. Pixel *ppixClient, pixTest;
  1905. int npixClient, npixNew, npix;
  1906. Pixel bits, base, cmask, rgbbad;
  1907. Pixel *pptr, *cptr;
  1908. int n, zapped;
  1909. int errVal = Success;
  1910. int offset, numents;
  1911. if (npixIn == 0)
  1912. return (errVal);
  1913. bits = 0;
  1914. zapped = 0;
  1915. base = lowbit(mask);
  1916. switch (color) {
  1917. case REDMAP:
  1918. cmask = pmap->pVisual->redMask;
  1919. rgbbad = ~RGBMASK(pmap->pVisual);
  1920. offset = pmap->pVisual->offsetRed;
  1921. numents = (cmask >> offset) + 1;
  1922. ppixClient = pmap->clientPixelsRed[client];
  1923. npixClient = pmap->numPixelsRed[client];
  1924. break;
  1925. case GREENMAP:
  1926. cmask = pmap->pVisual->greenMask;
  1927. rgbbad = ~RGBMASK(pmap->pVisual);
  1928. offset = pmap->pVisual->offsetGreen;
  1929. numents = (cmask >> offset) + 1;
  1930. ppixClient = pmap->clientPixelsGreen[client];
  1931. npixClient = pmap->numPixelsGreen[client];
  1932. break;
  1933. case BLUEMAP:
  1934. cmask = pmap->pVisual->blueMask;
  1935. rgbbad = ~RGBMASK(pmap->pVisual);
  1936. offset = pmap->pVisual->offsetBlue;
  1937. numents = (cmask >> offset) + 1;
  1938. ppixClient = pmap->clientPixelsBlue[client];
  1939. npixClient = pmap->numPixelsBlue[client];
  1940. break;
  1941. default: /* so compiler can see that everything gets initialized */
  1942. case PSEUDOMAP:
  1943. cmask = ~((Pixel) 0);
  1944. rgbbad = 0;
  1945. offset = 0;
  1946. numents = pmap->pVisual->ColormapEntries;
  1947. ppixClient = pmap->clientPixelsRed[client];
  1948. npixClient = pmap->numPixelsRed[client];
  1949. break;
  1950. }
  1951. /* zap all pixels which match */
  1952. while (1) {
  1953. /* go through pixel list */
  1954. for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) {
  1955. pixTest = ((*pptr | bits) & cmask) >> offset;
  1956. if ((pixTest >= numents) || (*pptr & rgbbad)) {
  1957. clientErrorValue = *pptr | bits;
  1958. errVal = BadValue;
  1959. continue;
  1960. }
  1961. /* find match in client list */
  1962. for (cptr = ppixClient, npix = npixClient;
  1963. --npix >= 0 && *cptr != pixTest; cptr++);
  1964. if (npix >= 0) {
  1965. if (pmap->class & DynamicClass) {
  1966. FreeCell(pmap, pixTest, color);
  1967. }
  1968. *cptr = ~((Pixel) 0);
  1969. zapped++;
  1970. }
  1971. else
  1972. errVal = BadAccess;
  1973. }
  1974. /* generate next bits value */
  1975. GetNextBitsOrBreak(bits, mask, base);
  1976. }
  1977. /* delete freed pixels from client pixel list */
  1978. if (zapped) {
  1979. npixNew = npixClient - zapped;
  1980. if (npixNew) {
  1981. /* Since the list can only get smaller, we can do a copy in
  1982. * place and then realloc to a smaller size */
  1983. pptr = cptr = ppixClient;
  1984. /* If we have all the new pixels, we don't have to examine the
  1985. * rest of the old ones */
  1986. for (npix = 0; npix < npixNew; cptr++) {
  1987. if (*cptr != ~((Pixel) 0)) {
  1988. *pptr++ = *cptr;
  1989. npix++;
  1990. }
  1991. }
  1992. pptr = (Pixel *) realloc(ppixClient, npixNew * sizeof(Pixel));
  1993. if (pptr)
  1994. ppixClient = pptr;
  1995. npixClient = npixNew;
  1996. }
  1997. else {
  1998. npixClient = 0;
  1999. free(ppixClient);
  2000. ppixClient = (Pixel *) NULL;
  2001. }
  2002. switch (color) {
  2003. case PSEUDOMAP:
  2004. case REDMAP:
  2005. pmap->clientPixelsRed[client] = ppixClient;
  2006. pmap->numPixelsRed[client] = npixClient;
  2007. break;
  2008. case GREENMAP:
  2009. pmap->clientPixelsGreen[client] = ppixClient;
  2010. pmap->numPixelsGreen[client] = npixClient;
  2011. break;
  2012. case BLUEMAP:
  2013. pmap->clientPixelsBlue[client] = ppixClient;
  2014. pmap->numPixelsBlue[client] = npixClient;
  2015. break;
  2016. }
  2017. }
  2018. return (errVal);
  2019. }
  2020. /* Redefine color values */
  2021. _X_EXPORT int
  2022. StoreColors(ColormapPtr pmap, int count, xColorItem * defs)
  2023. {
  2024. Pixel pix;
  2025. xColorItem *pdef;
  2026. EntryPtr pent, pentT, pentLast;
  2027. VisualPtr pVisual;
  2028. SHAREDCOLOR *pred, *pgreen, *pblue;
  2029. int n, ChgRed, ChgGreen, ChgBlue, idef;
  2030. int class, errVal = Success;
  2031. int ok;
  2032. class = pmap->class;
  2033. if (!(class & DynamicClass) && !(pmap->flags & BeingCreated)) {
  2034. return (BadAccess);
  2035. }
  2036. pVisual = pmap->pVisual;
  2037. idef = 0;
  2038. if ((class | DynamicClass) == DirectColor) {
  2039. int numred, numgreen, numblue;
  2040. Pixel rgbbad;
  2041. numred = NUMRED(pVisual);
  2042. numgreen = NUMGREEN(pVisual);
  2043. numblue = NUMBLUE(pVisual);
  2044. rgbbad = ~RGBMASK(pVisual);
  2045. for (pdef = defs, n = 0; n < count; pdef++, n++) {
  2046. ok = TRUE;
  2047. (*pmap->pScreen->ResolveColor)
  2048. (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
  2049. if (pdef->pixel & rgbbad) {
  2050. errVal = BadValue;
  2051. clientErrorValue = pdef->pixel;
  2052. continue;
  2053. }
  2054. pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
  2055. if (pix >= numred) {
  2056. errVal = BadValue;
  2057. ok = FALSE;
  2058. }
  2059. else if (pmap->red[pix].refcnt != AllocPrivate) {
  2060. errVal = BadAccess;
  2061. ok = FALSE;
  2062. }
  2063. else if (pdef->flags & DoRed) {
  2064. pmap->red[pix].co.local.red = pdef->red;
  2065. }
  2066. else {
  2067. pdef->red = pmap->red[pix].co.local.red;
  2068. }
  2069. pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
  2070. if (pix >= numgreen) {
  2071. errVal = BadValue;
  2072. ok = FALSE;
  2073. }
  2074. else if (pmap->green[pix].refcnt != AllocPrivate) {
  2075. errVal = BadAccess;
  2076. ok = FALSE;
  2077. }
  2078. else if (pdef->flags & DoGreen) {
  2079. pmap->green[pix].co.local.green = pdef->green;
  2080. }
  2081. else {
  2082. pdef->green = pmap->green[pix].co.local.green;
  2083. }
  2084. pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
  2085. if (pix >= numblue) {
  2086. errVal = BadValue;
  2087. ok = FALSE;
  2088. }
  2089. else if (pmap->blue[pix].refcnt != AllocPrivate) {
  2090. errVal = BadAccess;
  2091. ok = FALSE;
  2092. }
  2093. else if (pdef->flags & DoBlue) {
  2094. pmap->blue[pix].co.local.blue = pdef->blue;
  2095. }
  2096. else {
  2097. pdef->blue = pmap->blue[pix].co.local.blue;
  2098. }
  2099. /* If this is an o.k. entry, then it gets added to the list
  2100. * to be sent to the hardware. If not, skip it. Once we've
  2101. * skipped one, we have to copy all the others.
  2102. */
  2103. if (ok) {
  2104. if (idef != n)
  2105. defs[idef] = defs[n];
  2106. idef++;
  2107. }
  2108. else
  2109. clientErrorValue = pdef->pixel;
  2110. }
  2111. }
  2112. else {
  2113. for (pdef = defs, n = 0; n < count; pdef++, n++) {
  2114. ok = TRUE;
  2115. if (pdef->pixel >= pVisual->ColormapEntries) {
  2116. clientErrorValue = pdef->pixel;
  2117. errVal = BadValue;
  2118. ok = FALSE;
  2119. }
  2120. else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) {
  2121. errVal = BadAccess;
  2122. ok = FALSE;
  2123. }
  2124. /* If this is an o.k. entry, then it gets added to the list
  2125. * to be sent to the hardware. If not, skip it. Once we've
  2126. * skipped one, we have to copy all the others.
  2127. */
  2128. if (ok) {
  2129. if (idef != n)
  2130. defs[idef] = defs[n];
  2131. idef++;
  2132. }
  2133. else
  2134. continue;
  2135. (*pmap->pScreen->ResolveColor)
  2136. (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
  2137. pent = &pmap->red[pdef->pixel];
  2138. if (pdef->flags & DoRed) {
  2139. if (pent->fShared) {
  2140. pent->co.shco.red->color = pdef->red;
  2141. if (pent->co.shco.red->refcnt > 1)
  2142. ok = FALSE;
  2143. }
  2144. else
  2145. pent->co.local.red = pdef->red;
  2146. }
  2147. else {
  2148. if (pent->fShared)
  2149. pdef->red = pent->co.shco.red->color;
  2150. else
  2151. pdef->red = pent->co.local.red;
  2152. }
  2153. if (pdef->flags & DoGreen) {
  2154. if (pent->fShared) {
  2155. pent->co.shco.green->color = pdef->green;
  2156. if (pent->co.shco.green->refcnt > 1)
  2157. ok = FALSE;
  2158. }
  2159. else
  2160. pent->co.local.green = pdef->green;
  2161. }
  2162. else {
  2163. if (pent->fShared)
  2164. pdef->green = pent->co.shco.green->color;
  2165. else
  2166. pdef->green = pent->co.local.green;
  2167. }
  2168. if (pdef->flags & DoBlue) {
  2169. if (pent->fShared) {
  2170. pent->co.shco.blue->color = pdef->blue;
  2171. if (pent->co.shco.blue->refcnt > 1)
  2172. ok = FALSE;
  2173. }
  2174. else
  2175. pent->co.local.blue = pdef->blue;
  2176. }
  2177. else {
  2178. if (pent->fShared)
  2179. pdef->blue = pent->co.shco.blue->color;
  2180. else
  2181. pdef->blue = pent->co.local.blue;
  2182. }
  2183. if (!ok) {
  2184. /* have to run through the colormap and change anybody who
  2185. * shares this value */
  2186. pred = pent->co.shco.red;
  2187. pgreen = pent->co.shco.green;
  2188. pblue = pent->co.shco.blue;
  2189. ChgRed = pdef->flags & DoRed;
  2190. ChgGreen = pdef->flags & DoGreen;
  2191. ChgBlue = pdef->flags & DoBlue;
  2192. pentLast = pmap->red + pVisual->ColormapEntries;
  2193. for (pentT = pmap->red; pentT < pentLast; pentT++) {
  2194. if (pentT->fShared && (pentT != pent)) {
  2195. xColorItem defChg;
  2196. /* There are, alas, devices in this world too dumb
  2197. * to read their own hardware colormaps. Sick, but
  2198. * true. So we're going to be really nice and load
  2199. * the xColorItem with the proper value for all the
  2200. * fields. We will only set the flags for those
  2201. * fields that actually change. Smart devices can
  2202. * arrange to change only those fields. Dumb devices
  2203. * can rest assured that we have provided for them,
  2204. * and can change all three fields */
  2205. defChg.flags = 0;
  2206. if (ChgRed && pentT->co.shco.red == pred) {
  2207. defChg.flags |= DoRed;
  2208. }
  2209. if (ChgGreen && pentT->co.shco.green == pgreen) {
  2210. defChg.flags |= DoGreen;
  2211. }
  2212. if (ChgBlue && pentT->co.shco.blue == pblue) {
  2213. defChg.flags |= DoBlue;
  2214. }
  2215. if (defChg.flags != 0) {
  2216. defChg.pixel = pentT - pmap->red;
  2217. defChg.red = pentT->co.shco.red->color;
  2218. defChg.green = pentT->co.shco.green->color;
  2219. defChg.blue = pentT->co.shco.blue->color;
  2220. (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
  2221. }
  2222. }
  2223. }
  2224. }
  2225. }
  2226. }
  2227. /* Note that we use idef, the count of acceptable entries, and not
  2228. * count, the count of proposed entries */
  2229. if (idef != 0)
  2230. (*pmap->pScreen->StoreColors) (pmap, idef, defs);
  2231. return (errVal);
  2232. }
  2233. int
  2234. IsMapInstalled(Colormap map, WindowPtr pWin)
  2235. {
  2236. Colormap *pmaps;
  2237. int imap, nummaps, found;
  2238. pmaps =
  2239. (Colormap *) ALLOCATE_LOCAL(pWin->drawable.pScreen->maxInstalledCmaps *
  2240. sizeof(Colormap));
  2241. if (!pmaps)
  2242. return (FALSE);
  2243. nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
  2244. (pWin->drawable.pScreen, pmaps);
  2245. found = FALSE;
  2246. for (imap = 0; imap < nummaps; imap++) {
  2247. if (pmaps[imap] == map) {
  2248. found = TRUE;
  2249. break;
  2250. }
  2251. }
  2252. DEALLOCATE_LOCAL(pmaps);
  2253. return (found);
  2254. }