1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ******************************************************************/
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
52 #include <X11/Xproto.h>
58 #include "dixstruct.h"
59 #include "colormapst.h"
61 #include "scrnintstr.h"
63 #include "windowstr.h"
67 static Pixel
FindBestPixel(EntryPtr
/*pentFirst */ ,
73 static int AllComp(EntryPtr
/*pent */ ,
77 static int RedComp(EntryPtr
/*pent */ ,
81 static int GreenComp(EntryPtr
/*pent */ ,
85 static int BlueComp(EntryPtr
/*pent */ ,
89 static void FreePixels(ColormapPtr
/*pmap */ ,
93 static void CopyFree(int /*channel */ ,
95 ColormapPtr
/*pmapSrc */ ,
96 ColormapPtr
/*pmapDst */
99 static void FreeCell(ColormapPtr
/*pmap */ ,
104 static void UpdateColors(ColormapPtr
/*pmap */
107 static int AllocDirect(int /*client */ ,
108 ColormapPtr
/*pmap */ ,
114 Pixel
* /*pixels */ ,
115 Pixel
* /*prmask */ ,
116 Pixel
* /*pgmask */ ,
120 static int AllocPseudo(int /*client */ ,
121 ColormapPtr
/*pmap */ ,
125 Pixel
* /*pixels */ ,
127 Pixel
** /*pppixFirst */
130 static Bool
AllocCP(ColormapPtr
/*pmap */ ,
131 EntryPtr
/*pentFirst */ ,
135 Pixel
* /*pixels */ ,
139 static Bool
AllocShared(ColormapPtr
/*pmap */ ,
148 Pixel
* /*ppixFirst */
151 static int FreeCo(ColormapPtr
/*pmap */ ,
155 Pixel
* /*ppixIn */ ,
159 static int TellNoMap(WindowPtr
/*pwin */ ,
163 static void FindColorInRootCmap(ColormapPtr
/* pmap */ ,
164 EntryPtr
/* pentFirst */ ,
167 Pixel
* /* pPixel */ ,
169 ColorCompareProcPtr
/* comp */
172 #define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
173 #define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
174 #define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
176 #define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \
177 (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask))
179 #define ALPHAMASK(vis) 0
182 #define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
184 /* GetNextBitsOrBreak(bits, mask, base) --
185 * (Suggestion: First read the macro, then read this explanation.
187 * Either generate the next value to OR in to a pixel or break out of this
190 * This macro is used when we're trying to generate all 2^n combinations of
191 * bits in mask. What we're doing here is counting in binary, except that
192 * the bits we use to count may not be contiguous. This macro will be
193 * called 2^n times, returning a different value in bits each time. Then
194 * it will cause us to break out of a surrounding loop. (It will always be
195 * called from within a while loop.)
196 * On call: mask is the value we want to find all the combinations for
197 * base has 1 bit set where the least significant bit of mask is set
199 * For example,if mask is 01010, base should be 0010 and we count like this:
200 * 00010 (see this isn't so hard),
201 * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
202 * we add that to bits getting (0100 + 0100) =
203 * 01000 for our next value.
204 * then we add 0010 to get
205 * 01010 and we're done (easy as 1, 2, 3)
207 #define GetNextBitsOrBreak(bits, mask, base) \
208 if((bits) == (mask)) \
211 while((bits) & ~(mask)) \
212 (bits) += ((bits) & ~(mask));
213 /* ID of server as client */
216 typedef struct _colorResource
{
222 * refcnt == 0 means entry is empty
223 * refcnt > 0 means entry is useable by many clients, so it can't be changed
224 * refcnt == AllocPrivate means entry owned by one client only
225 * fShared should only be set if refcnt == AllocPrivate, and only in red map
229 * Create and initialize the color map
231 * \param mid resource to use for this colormap
232 * \param alloc 1 iff all entries are allocated writable
235 CreateColormap(Colormap mid
, ScreenPtr pScreen
, VisualPtr pVisual
,
236 ColormapPtr
*ppcmap
, int alloc
, int client
)
239 unsigned long sizebytes
;
245 class = pVisual
->class;
246 if (!(class & DynamicClass
) && (alloc
!= AllocNone
) &&
247 (client
!= SERVER_ID
))
250 size
= pVisual
->ColormapEntries
;
251 sizebytes
= (size
* sizeof(Entry
)) +
252 (MAXCLIENTS
* sizeof(Pixel
*)) + (MAXCLIENTS
* sizeof(int));
253 if ((class | DynamicClass
) == DirectColor
)
255 sizebytes
+= sizeof(ColormapRec
);
256 if (mid
== pScreen
->defColormap
) {
257 pmap
= malloc(sizebytes
);
260 if (!dixAllocatePrivates(&pmap
->devPrivates
, PRIVATE_COLORMAP
)) {
266 pmap
= _dixAllocateObjectWithPrivates(sizebytes
, sizebytes
,
267 offsetof(ColormapRec
,
273 pmap
->red
= (EntryPtr
) ((char *) pmap
+ sizeof(ColormapRec
));
274 sizebytes
= size
* sizeof(Entry
);
275 pmap
->clientPixelsRed
= (Pixel
**) ((char *) pmap
->red
+ sizebytes
);
276 pmap
->numPixelsRed
= (int *) ((char *) pmap
->clientPixelsRed
+
277 (MAXCLIENTS
* sizeof(Pixel
*)));
279 pmap
->flags
= 0; /* start out with all flags clear */
280 if (mid
== pScreen
->defColormap
)
281 pmap
->flags
|= IsDefault
;
282 pmap
->pScreen
= pScreen
;
283 pmap
->pVisual
= pVisual
;
285 if ((class | DynamicClass
) == DirectColor
)
286 size
= NUMRED(pVisual
);
287 pmap
->freeRed
= size
;
288 memset((char *) pmap
->red
, 0, (int) sizebytes
);
289 memset((char *) pmap
->numPixelsRed
, 0, MAXCLIENTS
* sizeof(int));
290 for (pptr
= &pmap
->clientPixelsRed
[MAXCLIENTS
];
291 --pptr
>= pmap
->clientPixelsRed
;)
292 *pptr
= (Pixel
*) NULL
;
293 if (alloc
== AllocAll
) {
294 if (class & DynamicClass
)
295 pmap
->flags
|= AllAllocated
;
296 for (pent
= &pmap
->red
[size
- 1]; pent
>= pmap
->red
; pent
--)
297 pent
->refcnt
= AllocPrivate
;
299 ppix
= malloc(size
* sizeof(Pixel
));
304 pmap
->clientPixelsRed
[client
] = ppix
;
305 for (i
= 0; i
< size
; i
++)
307 pmap
->numPixelsRed
[client
] = size
;
310 if ((class | DynamicClass
) == DirectColor
) {
311 pmap
->freeGreen
= NUMGREEN(pVisual
);
312 pmap
->green
= (EntryPtr
) ((char *) pmap
->numPixelsRed
+
313 (MAXCLIENTS
* sizeof(int)));
314 pmap
->clientPixelsGreen
= (Pixel
**) ((char *) pmap
->green
+ sizebytes
);
315 pmap
->numPixelsGreen
= (int *) ((char *) pmap
->clientPixelsGreen
+
316 (MAXCLIENTS
* sizeof(Pixel
*)));
317 pmap
->freeBlue
= NUMBLUE(pVisual
);
318 pmap
->blue
= (EntryPtr
) ((char *) pmap
->numPixelsGreen
+
319 (MAXCLIENTS
* sizeof(int)));
320 pmap
->clientPixelsBlue
= (Pixel
**) ((char *) pmap
->blue
+ sizebytes
);
321 pmap
->numPixelsBlue
= (int *) ((char *) pmap
->clientPixelsBlue
+
322 (MAXCLIENTS
* sizeof(Pixel
*)));
324 memset((char *) pmap
->green
, 0, (int) sizebytes
);
325 memset((char *) pmap
->blue
, 0, (int) sizebytes
);
327 memmove((char *) pmap
->clientPixelsGreen
,
328 (char *) pmap
->clientPixelsRed
, MAXCLIENTS
* sizeof(Pixel
*));
329 memmove((char *) pmap
->clientPixelsBlue
,
330 (char *) pmap
->clientPixelsRed
, MAXCLIENTS
* sizeof(Pixel
*));
331 memset((char *) pmap
->numPixelsGreen
, 0, MAXCLIENTS
* sizeof(int));
332 memset((char *) pmap
->numPixelsBlue
, 0, MAXCLIENTS
* sizeof(int));
334 /* If every cell is allocated, mark its refcnt */
335 if (alloc
== AllocAll
) {
336 size
= pmap
->freeGreen
;
337 for (pent
= &pmap
->green
[size
- 1]; pent
>= pmap
->green
; pent
--)
338 pent
->refcnt
= AllocPrivate
;
340 ppix
= malloc(size
* sizeof(Pixel
));
342 free(pmap
->clientPixelsRed
[client
]);
346 pmap
->clientPixelsGreen
[client
] = ppix
;
347 for (i
= 0; i
< size
; i
++)
349 pmap
->numPixelsGreen
[client
] = size
;
351 size
= pmap
->freeBlue
;
352 for (pent
= &pmap
->blue
[size
- 1]; pent
>= pmap
->blue
; pent
--)
353 pent
->refcnt
= AllocPrivate
;
355 ppix
= malloc(size
* sizeof(Pixel
));
357 free(pmap
->clientPixelsGreen
[client
]);
358 free(pmap
->clientPixelsRed
[client
]);
362 pmap
->clientPixelsBlue
[client
] = ppix
;
363 for (i
= 0; i
< size
; i
++)
365 pmap
->numPixelsBlue
[client
] = size
;
368 pmap
->flags
|= BeingCreated
;
370 if (!AddResource(mid
, RT_COLORMAP
, (pointer
) pmap
))
374 * Security creation/labeling check
376 i
= XaceHook(XACE_RESOURCE_ACCESS
, clients
[client
], mid
, RT_COLORMAP
,
377 pmap
, RT_NONE
, NULL
, DixCreateAccess
);
379 FreeResource(mid
, RT_NONE
);
383 /* If the device wants a chance to initialize the colormap in any way,
384 * this is it. In specific, if this is a Static colormap, this is the
385 * time to fill in the colormap's values */
386 if (!(*pScreen
->CreateColormap
) (pmap
)) {
387 FreeResource(mid
, RT_NONE
);
390 pmap
->flags
&= ~BeingCreated
;
397 * \param value must conform to DeleteType
400 FreeColormap(pointer value
, XID mid
)
404 ColormapPtr pmap
= (ColormapPtr
) value
;
406 if (CLIENT_ID(mid
) != SERVER_ID
) {
407 (*pmap
->pScreen
->UninstallColormap
) (pmap
);
408 WalkTree(pmap
->pScreen
, (VisitWindowProcPtr
) TellNoMap
, (pointer
) &mid
);
411 /* This is the device's chance to undo anything it needs to, especially
412 * to free any storage it allocated */
413 (*pmap
->pScreen
->DestroyColormap
) (pmap
);
415 if (pmap
->clientPixelsRed
) {
416 for (i
= 0; i
< MAXCLIENTS
; i
++)
417 free(pmap
->clientPixelsRed
[i
]);
420 if ((pmap
->class == PseudoColor
) || (pmap
->class == GrayScale
)) {
421 for (pent
= &pmap
->red
[pmap
->pVisual
->ColormapEntries
- 1];
422 pent
>= pmap
->red
; pent
--) {
424 if (--pent
->co
.shco
.red
->refcnt
== 0)
425 free(pent
->co
.shco
.red
);
426 if (--pent
->co
.shco
.green
->refcnt
== 0)
427 free(pent
->co
.shco
.green
);
428 if (--pent
->co
.shco
.blue
->refcnt
== 0)
429 free(pent
->co
.shco
.blue
);
433 if ((pmap
->class | DynamicClass
) == DirectColor
) {
434 for (i
= 0; i
< MAXCLIENTS
; i
++) {
435 free(pmap
->clientPixelsGreen
[i
]);
436 free(pmap
->clientPixelsBlue
[i
]);
440 if (pmap
->flags
& IsDefault
) {
441 dixFreePrivates(pmap
->devPrivates
, PRIVATE_COLORMAP
);
445 dixFreeObjectWithPrivates(pmap
, PRIVATE_COLORMAP
);
449 /* Tell window that pmid has disappeared */
451 TellNoMap(WindowPtr pwin
, Colormap
* pmid
)
453 if (wColormap(pwin
) == *pmid
) {
454 /* This should be call to DeliverEvent */
456 .u
.colormap
.window
= pwin
->drawable
.id
,
457 .u
.colormap
.colormap
= None
,
458 .u
.colormap
.new = TRUE
,
459 .u
.colormap
.state
= ColormapUninstalled
461 xE
.u
.u
.type
= ColormapNotify
;
463 if (noPanoramiXExtension
|| !pwin
->drawable
.pScreen
->myNum
)
465 DeliverEvents(pwin
, &xE
, 1, (WindowPtr
) NULL
);
466 if (pwin
->optional
) {
467 pwin
->optional
->colormap
= None
;
468 CheckWindowOptionalNeed(pwin
);
472 return WT_WALKCHILDREN
;
475 /* Tell window that pmid got uninstalled */
477 TellLostMap(WindowPtr pwin
, pointer value
)
479 Colormap
*pmid
= (Colormap
*) value
;
482 if (!noPanoramiXExtension
&& pwin
->drawable
.pScreen
->myNum
)
483 return WT_STOPWALKING
;
485 if (wColormap(pwin
) == *pmid
) {
486 /* This should be call to DeliverEvent */
488 .u
.colormap
.window
= pwin
->drawable
.id
,
489 .u
.colormap
.colormap
= *pmid
,
490 .u
.colormap
.new = FALSE
,
491 .u
.colormap
.state
= ColormapUninstalled
493 xE
.u
.u
.type
= ColormapNotify
;
494 DeliverEvents(pwin
, &xE
, 1, (WindowPtr
) NULL
);
497 return WT_WALKCHILDREN
;
500 /* Tell window that pmid got installed */
502 TellGainedMap(WindowPtr pwin
, pointer value
)
504 Colormap
*pmid
= (Colormap
*) value
;
507 if (!noPanoramiXExtension
&& pwin
->drawable
.pScreen
->myNum
)
508 return WT_STOPWALKING
;
510 if (wColormap(pwin
) == *pmid
) {
511 /* This should be call to DeliverEvent */
513 .u
.colormap
.window
= pwin
->drawable
.id
,
514 .u
.colormap
.colormap
= *pmid
,
515 .u
.colormap
.new = FALSE
,
516 .u
.colormap
.state
= ColormapInstalled
518 xE
.u
.u
.type
= ColormapNotify
;
519 DeliverEvents(pwin
, &xE
, 1, (WindowPtr
) NULL
);
522 return WT_WALKCHILDREN
;
526 CopyColormapAndFree(Colormap mid
, ColormapPtr pSrc
, int client
)
528 ColormapPtr pmap
= (ColormapPtr
) NULL
;
529 int result
, alloc
, size
;
534 pScreen
= pSrc
->pScreen
;
535 pVisual
= pSrc
->pVisual
;
537 alloc
= ((pSrc
->flags
& AllAllocated
) && CLIENT_ID(midSrc
) == client
) ?
538 AllocAll
: AllocNone
;
539 size
= pVisual
->ColormapEntries
;
541 /* If the create returns non-0, it failed */
542 result
= CreateColormap(mid
, pScreen
, pVisual
, &pmap
, alloc
, client
);
543 if (result
!= Success
)
545 if (alloc
== AllocAll
) {
546 memmove((char *) pmap
->red
, (char *) pSrc
->red
, size
* sizeof(Entry
));
547 if ((pmap
->class | DynamicClass
) == DirectColor
) {
548 memmove((char *) pmap
->green
, (char *) pSrc
->green
,
549 size
* sizeof(Entry
));
550 memmove((char *) pmap
->blue
, (char *) pSrc
->blue
,
551 size
* sizeof(Entry
));
553 pSrc
->flags
&= ~AllAllocated
;
554 FreePixels(pSrc
, client
);
559 CopyFree(REDMAP
, client
, pSrc
, pmap
);
560 if ((pmap
->class | DynamicClass
) == DirectColor
) {
561 CopyFree(GREENMAP
, client
, pSrc
, pmap
);
562 CopyFree(BLUEMAP
, client
, pSrc
, pmap
);
564 if (pmap
->class & DynamicClass
)
566 /* XXX should worry about removing any RT_CMAPENTRY resource */
570 /* Helper routine for freeing large numbers of cells from a map */
572 CopyFree(int channel
, int client
, ColormapPtr pmapSrc
, ColormapPtr pmapDst
)
575 EntryPtr pentSrcFirst
, pentDstFirst
;
576 EntryPtr pentSrc
, pentDst
;
581 default: /* so compiler can see that everything gets initialized */
583 ppix
= (pmapSrc
->clientPixelsRed
)[client
];
584 npix
= (pmapSrc
->numPixelsRed
)[client
];
585 pentSrcFirst
= pmapSrc
->red
;
586 pentDstFirst
= pmapDst
->red
;
589 ppix
= (pmapSrc
->clientPixelsGreen
)[client
];
590 npix
= (pmapSrc
->numPixelsGreen
)[client
];
591 pentSrcFirst
= pmapSrc
->green
;
592 pentDstFirst
= pmapDst
->green
;
595 ppix
= (pmapSrc
->clientPixelsBlue
)[client
];
596 npix
= (pmapSrc
->numPixelsBlue
)[client
];
597 pentSrcFirst
= pmapSrc
->blue
;
598 pentDstFirst
= pmapDst
->blue
;
602 if (pmapSrc
->class & DynamicClass
) {
603 for (z
= npix
; --z
>= 0; ppix
++) {
605 pentSrc
= pentSrcFirst
+ *ppix
;
606 pentDst
= pentDstFirst
+ *ppix
;
607 if (pentDst
->refcnt
> 0) {
613 if (pentSrc
->refcnt
> 0)
616 pentSrc
->fShared
= FALSE
;
618 FreeCell(pmapSrc
, *ppix
, channel
);
622 /* Note that FreeCell has already fixed pmapSrc->free{Color} */
625 pmapDst
->freeRed
-= nalloc
;
626 (pmapDst
->clientPixelsRed
)[client
] = (pmapSrc
->clientPixelsRed
)[client
];
627 (pmapSrc
->clientPixelsRed
)[client
] = (Pixel
*) NULL
;
628 (pmapDst
->numPixelsRed
)[client
] = (pmapSrc
->numPixelsRed
)[client
];
629 (pmapSrc
->numPixelsRed
)[client
] = 0;
632 pmapDst
->freeGreen
-= nalloc
;
633 (pmapDst
->clientPixelsGreen
)[client
] =
634 (pmapSrc
->clientPixelsGreen
)[client
];
635 (pmapSrc
->clientPixelsGreen
)[client
] = (Pixel
*) NULL
;
636 (pmapDst
->numPixelsGreen
)[client
] = (pmapSrc
->numPixelsGreen
)[client
];
637 (pmapSrc
->numPixelsGreen
)[client
] = 0;
640 pmapDst
->freeBlue
-= nalloc
;
641 pmapDst
->clientPixelsBlue
[client
] = pmapSrc
->clientPixelsBlue
[client
];
642 pmapSrc
->clientPixelsBlue
[client
] = (Pixel
*) NULL
;
643 pmapDst
->numPixelsBlue
[client
] = pmapSrc
->numPixelsBlue
[client
];
644 pmapSrc
->numPixelsBlue
[client
] = 0;
649 /* Free the ith entry in a color map. Must handle freeing of
650 * colors allocated through AllocColorPlanes */
652 FreeCell(ColormapPtr pmap
, Pixel i
, int channel
)
658 default: /* so compiler can see that everything gets initialized */
661 pent
= (EntryPtr
) &pmap
->red
[i
];
662 pCount
= &pmap
->freeRed
;
665 pent
= (EntryPtr
) &pmap
->green
[i
];
666 pCount
= &pmap
->freeGreen
;
669 pent
= (EntryPtr
) &pmap
->blue
[i
];
670 pCount
= &pmap
->freeBlue
;
673 /* If it's not privately allocated and it's not time to free it, just
674 * decrement the count */
675 if (pent
->refcnt
> 1)
678 /* If the color type is shared, find the sharedcolor. If decremented
679 * refcnt is 0, free the shared cell. */
681 if (--pent
->co
.shco
.red
->refcnt
== 0)
682 free(pent
->co
.shco
.red
);
683 if (--pent
->co
.shco
.green
->refcnt
== 0)
684 free(pent
->co
.shco
.green
);
685 if (--pent
->co
.shco
.blue
->refcnt
== 0)
686 free(pent
->co
.shco
.blue
);
687 pent
->fShared
= FALSE
;
695 UpdateColors(ColormapPtr pmap
)
703 pVisual
= pmap
->pVisual
;
704 size
= pVisual
->ColormapEntries
;
705 defs
= malloc(size
* sizeof(xColorItem
));
710 if (pmap
->class == DirectColor
) {
711 for (i
= 0; i
< size
; i
++) {
712 if (!pmap
->red
[i
].refcnt
&&
713 !pmap
->green
[i
].refcnt
&& !pmap
->blue
[i
].refcnt
)
715 pdef
->pixel
= ((Pixel
) i
<< pVisual
->offsetRed
) |
716 ((Pixel
) i
<< pVisual
->offsetGreen
) |
717 ((Pixel
) i
<< pVisual
->offsetBlue
);
718 pdef
->red
= pmap
->red
[i
].co
.local
.red
;
719 pdef
->green
= pmap
->green
[i
].co
.local
.green
;
720 pdef
->blue
= pmap
->blue
[i
].co
.local
.blue
;
721 pdef
->flags
= DoRed
| DoGreen
| DoBlue
;
727 for (i
= 0, pent
= pmap
->red
; i
< size
; i
++, pent
++) {
732 pdef
->red
= pent
->co
.shco
.red
->color
;
733 pdef
->green
= pent
->co
.shco
.green
->color
;
734 pdef
->blue
= pent
->co
.shco
.blue
->color
;
737 pdef
->red
= pent
->co
.local
.red
;
738 pdef
->green
= pent
->co
.local
.green
;
739 pdef
->blue
= pent
->co
.local
.blue
;
741 pdef
->flags
= DoRed
| DoGreen
| DoBlue
;
747 (*pmap
->pScreen
->StoreColors
) (pmap
, n
, defs
);
751 /* Get a read-only color from a ColorMap (probably slow for large maps)
752 * Returns by changing the value in pred, pgreen, pblue and pPix
755 AllocColor(ColormapPtr pmap
,
756 unsigned short *pred
, unsigned short *pgreen
, unsigned short *pblue
,
757 Pixel
* pPix
, int client
)
759 Pixel pixR
, pixG
, pixB
;
767 pVisual
= pmap
->pVisual
;
768 (*pmap
->pScreen
->ResolveColor
) (pred
, pgreen
, pblue
, pVisual
);
773 entries
= pVisual
->ColormapEntries
;
775 /* If the colormap is being created, then we want to be able to change
776 * the colormap, even if it's a static type. Otherwise, we'd never be
777 * able to initialize static colormaps
779 if (pmap
->flags
& BeingCreated
)
780 class |= DynamicClass
;
782 /* If this is one of the static storage classes, and we're not initializing
783 * it, the best we can do is to find the closest color entry to the
784 * requested one and return that.
789 /* Look up all three components in the same pmap */
790 *pPix
= pixR
= FindBestPixel(pmap
->red
, entries
, &rgb
, PSEUDOMAP
);
791 *pred
= pmap
->red
[pixR
].co
.local
.red
;
792 *pgreen
= pmap
->red
[pixR
].co
.local
.green
;
793 *pblue
= pmap
->red
[pixR
].co
.local
.blue
;
794 npix
= pmap
->numPixelsRed
[client
];
795 ppix
= (Pixel
*) realloc(pmap
->clientPixelsRed
[client
],
796 (npix
+ 1) * sizeof(Pixel
));
800 pmap
->clientPixelsRed
[client
] = ppix
;
801 pmap
->numPixelsRed
[client
]++;
805 /* Look up each component in its own map, then OR them together */
806 pixR
= FindBestPixel(pmap
->red
, NUMRED(pVisual
), &rgb
, REDMAP
);
807 pixG
= FindBestPixel(pmap
->green
, NUMGREEN(pVisual
), &rgb
, GREENMAP
);
808 pixB
= FindBestPixel(pmap
->blue
, NUMBLUE(pVisual
), &rgb
, BLUEMAP
);
809 *pPix
= (pixR
<< pVisual
->offsetRed
) |
810 (pixG
<< pVisual
->offsetGreen
) |
811 (pixB
<< pVisual
->offsetBlue
) | ALPHAMASK(pVisual
);
813 *pred
= pmap
->red
[pixR
].co
.local
.red
;
814 *pgreen
= pmap
->green
[pixG
].co
.local
.green
;
815 *pblue
= pmap
->blue
[pixB
].co
.local
.blue
;
816 npix
= pmap
->numPixelsRed
[client
];
817 ppix
= (Pixel
*) realloc(pmap
->clientPixelsRed
[client
],
818 (npix
+ 1) * sizeof(Pixel
));
822 pmap
->clientPixelsRed
[client
] = ppix
;
823 npix
= pmap
->numPixelsGreen
[client
];
824 ppix
= (Pixel
*) realloc(pmap
->clientPixelsGreen
[client
],
825 (npix
+ 1) * sizeof(Pixel
));
829 pmap
->clientPixelsGreen
[client
] = ppix
;
830 npix
= pmap
->numPixelsBlue
[client
];
831 ppix
= (Pixel
*) realloc(pmap
->clientPixelsBlue
[client
],
832 (npix
+ 1) * sizeof(Pixel
));
836 pmap
->clientPixelsBlue
[client
] = ppix
;
837 pmap
->numPixelsRed
[client
]++;
838 pmap
->numPixelsGreen
[client
]++;
839 pmap
->numPixelsBlue
[client
]++;
844 if (pmap
->mid
!= pmap
->pScreen
->defColormap
&&
845 pmap
->pVisual
->vid
== pmap
->pScreen
->rootVisual
) {
846 ColormapPtr prootmap
;
848 dixLookupResourceByType((pointer
*) &prootmap
,
849 pmap
->pScreen
->defColormap
, RT_COLORMAP
,
850 clients
[client
], DixReadAccess
);
852 if (pmap
->class == prootmap
->class)
853 FindColorInRootCmap(prootmap
, prootmap
->red
, entries
, &rgb
,
854 pPix
, PSEUDOMAP
, AllComp
);
856 if (FindColor(pmap
, pmap
->red
, entries
, &rgb
, pPix
, PSEUDOMAP
,
857 client
, AllComp
) != Success
)
862 if (pmap
->mid
!= pmap
->pScreen
->defColormap
&&
863 pmap
->pVisual
->vid
== pmap
->pScreen
->rootVisual
) {
864 ColormapPtr prootmap
;
866 dixLookupResourceByType((pointer
*) &prootmap
,
867 pmap
->pScreen
->defColormap
, RT_COLORMAP
,
868 clients
[client
], DixReadAccess
);
870 if (pmap
->class == prootmap
->class) {
871 pixR
= (*pPix
& pVisual
->redMask
) >> pVisual
->offsetRed
;
872 FindColorInRootCmap(prootmap
, prootmap
->red
, entries
, &rgb
,
873 &pixR
, REDMAP
, RedComp
);
874 pixG
= (*pPix
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
875 FindColorInRootCmap(prootmap
, prootmap
->green
, entries
, &rgb
,
876 &pixG
, GREENMAP
, GreenComp
);
877 pixB
= (*pPix
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
878 FindColorInRootCmap(prootmap
, prootmap
->blue
, entries
, &rgb
,
879 &pixB
, BLUEMAP
, BlueComp
);
880 *pPix
= pixR
| pixG
| pixB
;
884 pixR
= (*pPix
& pVisual
->redMask
) >> pVisual
->offsetRed
;
885 if (FindColor(pmap
, pmap
->red
, NUMRED(pVisual
), &rgb
, &pixR
, REDMAP
,
886 client
, RedComp
) != Success
)
888 pixG
= (*pPix
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
889 if (FindColor(pmap
, pmap
->green
, NUMGREEN(pVisual
), &rgb
, &pixG
,
890 GREENMAP
, client
, GreenComp
) != Success
) {
891 (void) FreeCo(pmap
, client
, REDMAP
, 1, &pixR
, (Pixel
) 0);
894 pixB
= (*pPix
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
895 if (FindColor(pmap
, pmap
->blue
, NUMBLUE(pVisual
), &rgb
, &pixB
, BLUEMAP
,
896 client
, BlueComp
) != Success
) {
897 (void) FreeCo(pmap
, client
, GREENMAP
, 1, &pixG
, (Pixel
) 0);
898 (void) FreeCo(pmap
, client
, REDMAP
, 1, &pixR
, (Pixel
) 0);
901 *pPix
= pixR
| pixG
| pixB
| ALPHAMASK(pVisual
);
906 /* if this is the client's first pixel in this colormap, tell the
907 * resource manager that the client has pixels in this colormap which
908 * should be freed when the client dies */
909 if ((pmap
->numPixelsRed
[client
] == 1) &&
910 (CLIENT_ID(pmap
->mid
) != client
) && !(pmap
->flags
& BeingCreated
)) {
913 pcr
= malloc(sizeof(colorResource
));
915 (void) FreeColors(pmap
, client
, 1, pPix
, (Pixel
) 0);
918 pcr
->mid
= pmap
->mid
;
919 pcr
->client
= client
;
920 if (!AddResource(FakeClientID(client
), RT_CMAPENTRY
, (pointer
) pcr
))
927 * FakeAllocColor -- fake an AllocColor request by
928 * returning a free pixel if availible, otherwise returning
929 * the closest matching pixel. This is used by the mi
930 * software sprite code to recolor cursors. A nice side-effect
931 * is that this routine will never return failure.
935 FakeAllocColor(ColormapPtr pmap
, xColorItem
* item
)
937 Pixel pixR
, pixG
, pixB
;
944 pVisual
= pmap
->pVisual
;
946 rgb
.green
= item
->green
;
947 rgb
.blue
= item
->blue
;
948 (*pmap
->pScreen
->ResolveColor
) (&rgb
.red
, &rgb
.green
, &rgb
.blue
, pVisual
);
950 entries
= pVisual
->ColormapEntries
;
957 if (FindColor(pmap
, pmap
->red
, entries
, &rgb
, &temp
, PSEUDOMAP
,
958 -1, AllComp
) == Success
) {
962 /* fall through ... */
965 item
->pixel
= FindBestPixel(pmap
->red
, entries
, &rgb
, PSEUDOMAP
);
969 /* Look up each component in its own map, then OR them together */
970 pixR
= (item
->pixel
& pVisual
->redMask
) >> pVisual
->offsetRed
;
971 pixG
= (item
->pixel
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
972 pixB
= (item
->pixel
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
973 if (FindColor(pmap
, pmap
->red
, NUMRED(pVisual
), &rgb
, &pixR
, REDMAP
,
974 -1, RedComp
) != Success
)
975 pixR
= FindBestPixel(pmap
->red
, NUMRED(pVisual
), &rgb
, REDMAP
)
976 << pVisual
->offsetRed
;
977 if (FindColor(pmap
, pmap
->green
, NUMGREEN(pVisual
), &rgb
, &pixG
,
978 GREENMAP
, -1, GreenComp
) != Success
)
979 pixG
= FindBestPixel(pmap
->green
, NUMGREEN(pVisual
), &rgb
,
980 GREENMAP
) << pVisual
->offsetGreen
;
981 if (FindColor(pmap
, pmap
->blue
, NUMBLUE(pVisual
), &rgb
, &pixB
, BLUEMAP
,
982 -1, BlueComp
) != Success
)
983 pixB
= FindBestPixel(pmap
->blue
, NUMBLUE(pVisual
), &rgb
, BLUEMAP
)
984 << pVisual
->offsetBlue
;
985 item
->pixel
= pixR
| pixG
| pixB
;
989 /* Look up each component in its own map, then OR them together */
990 pixR
= FindBestPixel(pmap
->red
, NUMRED(pVisual
), &rgb
, REDMAP
);
991 pixG
= FindBestPixel(pmap
->green
, NUMGREEN(pVisual
), &rgb
, GREENMAP
);
992 pixB
= FindBestPixel(pmap
->blue
, NUMBLUE(pVisual
), &rgb
, BLUEMAP
);
993 item
->pixel
= (pixR
<< pVisual
->offsetRed
) |
994 (pixG
<< pVisual
->offsetGreen
) | (pixB
<< pVisual
->offsetBlue
);
999 /* free a pixel value obtained from FakeAllocColor */
1001 FakeFreeColor(ColormapPtr pmap
, Pixel pixel
)
1004 Pixel pixR
, pixG
, pixB
;
1006 switch (pmap
->class) {
1009 if (pmap
->red
[pixel
].refcnt
== AllocTemporary
)
1010 pmap
->red
[pixel
].refcnt
= 0;
1013 pVisual
= pmap
->pVisual
;
1014 pixR
= (pixel
& pVisual
->redMask
) >> pVisual
->offsetRed
;
1015 pixG
= (pixel
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
1016 pixB
= (pixel
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
1017 if (pmap
->red
[pixR
].refcnt
== AllocTemporary
)
1018 pmap
->red
[pixR
].refcnt
= 0;
1019 if (pmap
->green
[pixG
].refcnt
== AllocTemporary
)
1020 pmap
->green
[pixG
].refcnt
= 0;
1021 if (pmap
->blue
[pixB
].refcnt
== AllocTemporary
)
1022 pmap
->blue
[pixB
].refcnt
= 0;
1027 typedef unsigned short BigNumUpper
;
1028 typedef unsigned long BigNumLower
;
1030 #define BIGNUMLOWERBITS 24
1031 #define BIGNUMUPPERBITS 16
1032 #define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
1033 #define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
1034 #define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
1035 #define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
1037 typedef struct _bignum
{
1040 } BigNumRec
, *BigNumPtr
;
1042 #define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
1043 ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
1045 #define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
1046 ((r)->lower = LOWERPART(u)))
1048 #define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
1049 ((r)->lower = BIGNUMLOWER-1))
1052 BigNumAdd(BigNumPtr x
, BigNumPtr y
, BigNumPtr r
)
1054 BigNumLower lower
, carry
= 0;
1056 lower
= x
->lower
+ y
->lower
;
1057 if (lower
>= BIGNUMLOWER
) {
1058 lower
-= BIGNUMLOWER
;
1062 r
->upper
= x
->upper
+ y
->upper
+ carry
;
1066 FindBestPixel(EntryPtr pentFirst
, int size
, xrgb
* prgb
, int channel
)
1072 BigNumRec minval
, sum
, temp
;
1076 /* look for the minimal difference */
1077 for (pent
= pentFirst
, pixel
= 0; pixel
< size
; pent
++, pixel
++) {
1081 dg
= (long) pent
->co
.local
.green
- prgb
->green
;
1082 db
= (long) pent
->co
.local
.blue
- prgb
->blue
;
1084 dr
= (long) pent
->co
.local
.red
- prgb
->red
;
1087 dg
= (long) pent
->co
.local
.green
- prgb
->green
;
1090 db
= (long) pent
->co
.local
.blue
- prgb
->blue
;
1094 UnsignedToBigNum(sq
, &sum
);
1096 UnsignedToBigNum(sq
, &temp
);
1097 BigNumAdd(&sum
, &temp
, &sum
);
1099 UnsignedToBigNum(sq
, &temp
);
1100 BigNumAdd(&sum
, &temp
, &sum
);
1101 if (BigNumGreater(&minval
, &sum
)) {
1110 FindColorInRootCmap(ColormapPtr pmap
, EntryPtr pentFirst
, int size
,
1111 xrgb
* prgb
, Pixel
* pPixel
, int channel
,
1112 ColorCompareProcPtr comp
)
1118 if ((pixel
= *pPixel
) >= size
)
1120 for (pent
= pentFirst
+ pixel
, count
= size
; --count
>= 0; pent
++, pixel
++) {
1121 if (pent
->refcnt
> 0 && (*comp
) (pent
, prgb
)) {
1124 pixel
<<= pmap
->pVisual
->offsetRed
;
1127 pixel
<<= pmap
->pVisual
->offsetGreen
;
1130 pixel
<<= pmap
->pVisual
->offsetBlue
;
1132 default: /* PSEUDOMAP */
1140 /* Tries to find a color in pmap that exactly matches the one requested in prgb
1141 * if it can't it allocates one.
1142 * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
1143 * load *pPixel with that value, otherwise set it to 0
1146 FindColor(ColormapPtr pmap
, EntryPtr pentFirst
, int size
, xrgb
* prgb
,
1147 Pixel
* pPixel
, int channel
, int client
, ColorCompareProcPtr comp
)
1151 Pixel pixel
, Free
= 0;
1152 int npix
, count
, *nump
= NULL
;
1153 Pixel
**pixp
= NULL
, *ppix
;
1158 if ((pixel
= *pPixel
) >= size
)
1160 /* see if there is a match, and also look for a free entry */
1161 for (pent
= pentFirst
+ pixel
, count
= size
; --count
>= 0;) {
1162 if (pent
->refcnt
> 0) {
1163 if ((*comp
) (pent
, prgb
)) {
1169 *pPixel
<<= pmap
->pVisual
->offsetRed
;
1173 *pPixel
<<= pmap
->pVisual
->offsetGreen
;
1176 *pPixel
<<= pmap
->pVisual
->offsetBlue
;
1182 else if (!foundFree
&& pent
->refcnt
== 0) {
1185 /* If we're initializing the colormap, then we are looking for
1186 * the first free cell we can find, not to minimize the number
1187 * of entries we use. So don't look any further. */
1188 if (pmap
->flags
& BeingCreated
)
1192 if (pixel
>= size
) {
1200 /* If we got here, we didn't find a match. If we also didn't find
1201 * a free entry, we're out of luck. Otherwise, we'll usurp a free
1202 * entry and fill it in */
1205 pent
= pentFirst
+ Free
;
1206 pent
->fShared
= FALSE
;
1207 pent
->refcnt
= (client
>= 0) ? 1 : AllocTemporary
;
1211 pent
->co
.local
.red
= prgb
->red
;
1212 pent
->co
.local
.green
= prgb
->green
;
1213 pent
->co
.local
.blue
= prgb
->blue
;
1214 def
.red
= prgb
->red
;
1215 def
.green
= prgb
->green
;
1216 def
.blue
= prgb
->blue
;
1217 def
.flags
= (DoRed
| DoGreen
| DoBlue
);
1224 pent
->co
.local
.red
= prgb
->red
;
1225 def
.red
= prgb
->red
;
1226 def
.green
= pmap
->green
[0].co
.local
.green
;
1227 def
.blue
= pmap
->blue
[0].co
.local
.blue
;
1231 def
.pixel
= Free
<< pmap
->pVisual
->offsetRed
;
1235 pent
->co
.local
.green
= prgb
->green
;
1236 def
.red
= pmap
->red
[0].co
.local
.red
;
1237 def
.green
= prgb
->green
;
1238 def
.blue
= pmap
->blue
[0].co
.local
.blue
;
1239 def
.flags
= DoGreen
;
1242 def
.pixel
= Free
<< pmap
->pVisual
->offsetGreen
;
1246 pent
->co
.local
.blue
= prgb
->blue
;
1247 def
.red
= pmap
->red
[0].co
.local
.red
;
1248 def
.green
= pmap
->green
[0].co
.local
.green
;
1249 def
.blue
= prgb
->blue
;
1253 def
.pixel
= Free
<< pmap
->pVisual
->offsetBlue
;
1256 (*pmap
->pScreen
->StoreColors
) (pmap
, 1, &def
);
1258 *pPixel
= def
.pixel
;
1261 if (pmap
->flags
& BeingCreated
|| client
== -1)
1263 /* Now remember the pixel, for freeing later */
1267 nump
= pmap
->numPixelsRed
;
1268 pixp
= pmap
->clientPixelsRed
;
1272 nump
= pmap
->numPixelsGreen
;
1273 pixp
= pmap
->clientPixelsGreen
;
1277 nump
= pmap
->numPixelsBlue
;
1278 pixp
= pmap
->clientPixelsBlue
;
1281 npix
= nump
[client
];
1282 ppix
= (Pixel
*) realloc(pixp
[client
], (npix
+ 1) * sizeof(Pixel
));
1301 pixp
[client
] = ppix
;
1307 /* Comparison functions -- passed to FindColor to determine if an
1308 * entry is already the color we're looking for or not */
1310 AllComp(EntryPtr pent
, xrgb
* prgb
)
1312 if ((pent
->co
.local
.red
== prgb
->red
) &&
1313 (pent
->co
.local
.green
== prgb
->green
) &&
1314 (pent
->co
.local
.blue
== prgb
->blue
))
1320 RedComp(EntryPtr pent
, xrgb
* prgb
)
1322 if (pent
->co
.local
.red
== prgb
->red
)
1328 GreenComp(EntryPtr pent
, xrgb
* prgb
)
1330 if (pent
->co
.local
.green
== prgb
->green
)
1336 BlueComp(EntryPtr pent
, xrgb
* prgb
)
1338 if (pent
->co
.local
.blue
== prgb
->blue
)
1343 /* Read the color value of a cell */
1346 QueryColors(ColormapPtr pmap
, int count
, Pixel
* ppixIn
, xrgb
* prgbList
,
1354 int errVal
= Success
;
1356 pVisual
= pmap
->pVisual
;
1357 if ((pmap
->class | DynamicClass
) == DirectColor
) {
1358 int numred
, numgreen
, numblue
;
1361 numred
= NUMRED(pVisual
);
1362 numgreen
= NUMGREEN(pVisual
);
1363 numblue
= NUMBLUE(pVisual
);
1364 rgbbad
= ~RGBMASK(pVisual
);
1365 for (ppix
= ppixIn
, prgb
= prgbList
; --count
>= 0; ppix
++, prgb
++) {
1367 if (pixel
& rgbbad
) {
1368 client
->errorValue
= pixel
;
1372 i
= (pixel
& pVisual
->redMask
) >> pVisual
->offsetRed
;
1374 client
->errorValue
= pixel
;
1378 prgb
->red
= pmap
->red
[i
].co
.local
.red
;
1379 i
= (pixel
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
1380 if (i
>= numgreen
) {
1381 client
->errorValue
= pixel
;
1385 prgb
->green
= pmap
->green
[i
].co
.local
.green
;
1386 i
= (pixel
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
1388 client
->errorValue
= pixel
;
1392 prgb
->blue
= pmap
->blue
[i
].co
.local
.blue
;
1396 for (ppix
= ppixIn
, prgb
= prgbList
; --count
>= 0; ppix
++, prgb
++) {
1398 if (pixel
>= pVisual
->ColormapEntries
) {
1399 client
->errorValue
= pixel
;
1403 pent
= (EntryPtr
) &pmap
->red
[pixel
];
1404 if (pent
->fShared
) {
1405 prgb
->red
= pent
->co
.shco
.red
->color
;
1406 prgb
->green
= pent
->co
.shco
.green
->color
;
1407 prgb
->blue
= pent
->co
.shco
.blue
->color
;
1410 prgb
->red
= pent
->co
.local
.red
;
1411 prgb
->green
= pent
->co
.local
.green
;
1412 prgb
->blue
= pent
->co
.local
.blue
;
1421 FreePixels(ColormapPtr pmap
, int client
)
1423 Pixel
*ppix
, *ppixStart
;
1427 class = pmap
->class;
1428 ppixStart
= pmap
->clientPixelsRed
[client
];
1429 if (class & DynamicClass
) {
1430 n
= pmap
->numPixelsRed
[client
];
1431 for (ppix
= ppixStart
; --n
>= 0;) {
1432 FreeCell(pmap
, *ppix
, REDMAP
);
1438 pmap
->clientPixelsRed
[client
] = (Pixel
*) NULL
;
1439 pmap
->numPixelsRed
[client
] = 0;
1440 if ((class | DynamicClass
) == DirectColor
) {
1441 ppixStart
= pmap
->clientPixelsGreen
[client
];
1442 if (class & DynamicClass
)
1443 for (ppix
= ppixStart
, n
= pmap
->numPixelsGreen
[client
]; --n
>= 0;)
1444 FreeCell(pmap
, *ppix
++, GREENMAP
);
1446 pmap
->clientPixelsGreen
[client
] = (Pixel
*) NULL
;
1447 pmap
->numPixelsGreen
[client
] = 0;
1449 ppixStart
= pmap
->clientPixelsBlue
[client
];
1450 if (class & DynamicClass
)
1451 for (ppix
= ppixStart
, n
= pmap
->numPixelsBlue
[client
]; --n
>= 0;)
1452 FreeCell(pmap
, *ppix
++, BLUEMAP
);
1454 pmap
->clientPixelsBlue
[client
] = (Pixel
*) NULL
;
1455 pmap
->numPixelsBlue
[client
] = 0;
1460 * Frees all of a client's colors and cells.
1462 * \param value must conform to DeleteType
1466 FreeClientPixels(pointer value
, XID fakeid
)
1469 colorResource
*pcr
= value
;
1472 rc
= dixLookupResourceByType(&pmap
, pcr
->mid
, RT_COLORMAP
, serverClient
,
1475 FreePixels((ColormapPtr
) pmap
, pcr
->client
);
1481 AllocColorCells(int client
, ColormapPtr pmap
, int colors
, int planes
,
1482 Bool contig
, Pixel
* ppix
, Pixel
* masks
)
1484 Pixel rmask
, gmask
, bmask
, *ppixFirst
, r
, g
, b
;
1488 colorResource
*pcr
= (colorResource
*) NULL
;
1490 class = pmap
->class;
1491 if (!(class & DynamicClass
))
1492 return BadAlloc
; /* Shouldn't try on this type */
1493 oldcount
= pmap
->numPixelsRed
[client
];
1494 if (pmap
->class == DirectColor
)
1495 oldcount
+= pmap
->numPixelsGreen
[client
] + pmap
->numPixelsBlue
[client
];
1496 if (!oldcount
&& (CLIENT_ID(pmap
->mid
) != client
)) {
1497 pcr
= malloc(sizeof(colorResource
));
1502 if (pmap
->class == DirectColor
) {
1503 ok
= AllocDirect(client
, pmap
, colors
, planes
, planes
, planes
,
1504 contig
, ppix
, &rmask
, &gmask
, &bmask
);
1505 if (ok
== Success
) {
1506 for (r
= g
= b
= 1, n
= planes
; --n
>= 0; r
+= r
, g
+= g
, b
+= b
) {
1507 while (!(rmask
& r
))
1509 while (!(gmask
& g
))
1511 while (!(bmask
& b
))
1513 *masks
++ = r
| g
| b
;
1518 ok
= AllocPseudo(client
, pmap
, colors
, planes
, contig
, ppix
, &rmask
,
1520 if (ok
== Success
) {
1521 for (r
= 1, n
= planes
; --n
>= 0; r
+= r
) {
1522 while (!(rmask
& r
))
1529 /* if this is the client's first pixels in this colormap, tell the
1530 * resource manager that the client has pixels in this colormap which
1531 * should be freed when the client dies */
1532 if ((ok
== Success
) && pcr
) {
1533 pcr
->mid
= pmap
->mid
;
1534 pcr
->client
= client
;
1535 if (!AddResource(FakeClientID(client
), RT_CMAPENTRY
, (pointer
) pcr
))
1545 AllocColorPlanes(int client
, ColormapPtr pmap
, int colors
,
1546 int r
, int g
, int b
, Bool contig
, Pixel
* pixels
,
1547 Pixel
* prmask
, Pixel
* pgmask
, Pixel
* pbmask
)
1550 Pixel mask
, *ppixFirst
;
1555 colorResource
*pcr
= (colorResource
*) NULL
;
1557 class = pmap
->class;
1558 if (!(class & DynamicClass
))
1559 return BadAlloc
; /* Shouldn't try on this type */
1560 oldcount
= pmap
->numPixelsRed
[client
];
1561 if (class == DirectColor
)
1562 oldcount
+= pmap
->numPixelsGreen
[client
] + pmap
->numPixelsBlue
[client
];
1563 if (!oldcount
&& (CLIENT_ID(pmap
->mid
) != client
)) {
1564 pcr
= malloc(sizeof(colorResource
));
1569 if (class == DirectColor
) {
1570 ok
= AllocDirect(client
, pmap
, colors
, r
, g
, b
, contig
, pixels
,
1571 prmask
, pgmask
, pbmask
);
1574 /* Allocate the proper pixels */
1575 /* XXX This is sort of bad, because of contig is set, we force all
1576 * r + g + b bits to be contiguous. Should only force contiguity
1579 ok
= AllocPseudo(client
, pmap
, colors
, r
+ g
+ b
, contig
, pixels
,
1582 if (ok
== Success
) {
1583 /* now split that mask into three */
1584 *prmask
= *pgmask
= *pbmask
= 0;
1586 for (i
= r
; --i
>= 0; shift
+= shift
) {
1587 while (!(mask
& shift
))
1591 for (i
= g
; --i
>= 0; shift
+= shift
) {
1592 while (!(mask
& shift
))
1596 for (i
= b
; --i
>= 0; shift
+= shift
) {
1597 while (!(mask
& shift
))
1602 /* set up the shared color cells */
1603 if (!AllocShared(pmap
, pixels
, colors
, r
, g
, b
,
1604 *prmask
, *pgmask
, *pbmask
, ppixFirst
)) {
1605 (void) FreeColors(pmap
, client
, colors
, pixels
, mask
);
1611 /* if this is the client's first pixels in this colormap, tell the
1612 * resource manager that the client has pixels in this colormap which
1613 * should be freed when the client dies */
1614 if ((ok
== Success
) && pcr
) {
1615 pcr
->mid
= pmap
->mid
;
1616 pcr
->client
= client
;
1617 if (!AddResource(FakeClientID(client
), RT_CMAPENTRY
, (pointer
) pcr
))
1627 AllocDirect(int client
, ColormapPtr pmap
, int c
, int r
, int g
, int b
,
1628 Bool contig
, Pixel
* pixels
, Pixel
* prmask
, Pixel
* pgmask
,
1631 Pixel
*ppixRed
, *ppixGreen
, *ppixBlue
;
1632 Pixel
*ppix
, *pDst
, *p
;
1633 int npix
, npixR
, npixG
, npixB
;
1635 Pixel
*rpix
= 0, *gpix
= 0, *bpix
= 0;
1640 if ((r
>= 32) || (g
>= 32) || (b
>= 32) ||
1641 (npixR
> pmap
->freeRed
) || (npixR
< c
) ||
1642 (npixG
> pmap
->freeGreen
) || (npixG
< c
) ||
1643 (npixB
> pmap
->freeBlue
) || (npixB
< c
))
1646 /* start out with empty pixels */
1647 for (p
= pixels
; p
< pixels
+ c
; p
++)
1650 ppixRed
= malloc(npixR
* sizeof(Pixel
));
1651 ppixGreen
= malloc(npixG
* sizeof(Pixel
));
1652 ppixBlue
= malloc(npixB
* sizeof(Pixel
));
1653 if (!ppixRed
|| !ppixGreen
|| !ppixBlue
) {
1660 okR
= AllocCP(pmap
, pmap
->red
, c
, r
, contig
, ppixRed
, prmask
);
1661 okG
= AllocCP(pmap
, pmap
->green
, c
, g
, contig
, ppixGreen
, pgmask
);
1662 okB
= AllocCP(pmap
, pmap
->blue
, c
, b
, contig
, ppixBlue
, pbmask
);
1664 if (okR
&& okG
&& okB
) {
1665 rpix
= (Pixel
*) realloc(pmap
->clientPixelsRed
[client
],
1666 (pmap
->numPixelsRed
[client
] + (c
<< r
)) *
1669 pmap
->clientPixelsRed
[client
] = rpix
;
1670 gpix
= (Pixel
*) realloc(pmap
->clientPixelsGreen
[client
],
1671 (pmap
->numPixelsGreen
[client
] + (c
<< g
)) *
1674 pmap
->clientPixelsGreen
[client
] = gpix
;
1675 bpix
= (Pixel
*) realloc(pmap
->clientPixelsBlue
[client
],
1676 (pmap
->numPixelsBlue
[client
] + (c
<< b
)) *
1679 pmap
->clientPixelsBlue
[client
] = bpix
;
1682 if (!okR
|| !okG
|| !okB
|| !rpix
|| !gpix
|| !bpix
) {
1684 for (ppix
= ppixRed
, npix
= npixR
; --npix
>= 0; ppix
++)
1685 pmap
->red
[*ppix
].refcnt
= 0;
1687 for (ppix
= ppixGreen
, npix
= npixG
; --npix
>= 0; ppix
++)
1688 pmap
->green
[*ppix
].refcnt
= 0;
1690 for (ppix
= ppixBlue
, npix
= npixB
; --npix
>= 0; ppix
++)
1691 pmap
->blue
[*ppix
].refcnt
= 0;
1698 *prmask
<<= pmap
->pVisual
->offsetRed
;
1699 *pgmask
<<= pmap
->pVisual
->offsetGreen
;
1700 *pbmask
<<= pmap
->pVisual
->offsetBlue
;
1702 ppix
= rpix
+ pmap
->numPixelsRed
[client
];
1703 for (pDst
= pixels
, p
= ppixRed
; p
< ppixRed
+ npixR
; p
++) {
1705 if (p
< ppixRed
+ c
)
1706 *pDst
++ |= *p
<< pmap
->pVisual
->offsetRed
;
1708 pmap
->numPixelsRed
[client
] += npixR
;
1709 pmap
->freeRed
-= npixR
;
1711 ppix
= gpix
+ pmap
->numPixelsGreen
[client
];
1712 for (pDst
= pixels
, p
= ppixGreen
; p
< ppixGreen
+ npixG
; p
++) {
1714 if (p
< ppixGreen
+ c
)
1715 *pDst
++ |= *p
<< pmap
->pVisual
->offsetGreen
;
1717 pmap
->numPixelsGreen
[client
] += npixG
;
1718 pmap
->freeGreen
-= npixG
;
1720 ppix
= bpix
+ pmap
->numPixelsBlue
[client
];
1721 for (pDst
= pixels
, p
= ppixBlue
; p
< ppixBlue
+ npixB
; p
++) {
1723 if (p
< ppixBlue
+ c
)
1724 *pDst
++ |= *p
<< pmap
->pVisual
->offsetBlue
;
1726 pmap
->numPixelsBlue
[client
] += npixB
;
1727 pmap
->freeBlue
-= npixB
;
1729 for (pDst
= pixels
; pDst
< pixels
+ c
; pDst
++)
1730 *pDst
|= ALPHAMASK(pmap
->pVisual
);
1740 AllocPseudo(int client
, ColormapPtr pmap
, int c
, int r
, Bool contig
,
1741 Pixel
* pixels
, Pixel
* pmask
, Pixel
** pppixFirst
)
1743 Pixel
*ppix
, *p
, *pDst
, *ppixTemp
;
1748 if ((r
>= 32) || (npix
> pmap
->freeRed
) || (npix
< c
))
1750 if (!(ppixTemp
= malloc(npix
* sizeof(Pixel
))))
1752 ok
= AllocCP(pmap
, pmap
->red
, c
, r
, contig
, ppixTemp
, pmask
);
1756 /* all the allocated pixels are added to the client pixel list,
1757 * but only the unique ones are returned to the client */
1758 ppix
= (Pixel
*) realloc(pmap
->clientPixelsRed
[client
],
1759 (pmap
->numPixelsRed
[client
] +
1760 npix
) * sizeof(Pixel
));
1762 for (p
= ppixTemp
; p
< ppixTemp
+ npix
; p
++)
1763 pmap
->red
[*p
].refcnt
= 0;
1767 pmap
->clientPixelsRed
[client
] = ppix
;
1768 ppix
+= pmap
->numPixelsRed
[client
];
1771 for (p
= ppixTemp
; p
< ppixTemp
+ npix
; p
++) {
1773 if (p
< ppixTemp
+ c
)
1776 pmap
->numPixelsRed
[client
] += npix
;
1777 pmap
->freeRed
-= npix
;
1780 return ok
? Success
: BadAlloc
;
1783 /* Allocates count << planes pixels from colormap pmap for client. If
1784 * contig, then the plane mask is made of consecutive bits. Returns
1785 * all count << pixels in the array pixels. The first count of those
1786 * pixels are the unique pixels. *pMask has the mask to Or with the
1787 * unique pixels to get the rest of them.
1789 * Returns True iff all pixels could be allocated
1790 * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
1791 * (see AllocShared for why we care)
1794 AllocCP(ColormapPtr pmap
, EntryPtr pentFirst
, int count
, int planes
,
1795 Bool contig
, Pixel
* pixels
, Pixel
* pMask
)
1798 Pixel pixel
, base
, entries
, maxp
, save
;
1804 dplanes
= pmap
->pVisual
->nplanes
;
1806 /* Easy case. Allocate pixels only */
1808 /* allocate writable entries */
1812 while (--count
>= 0) {
1813 /* Just find count unallocated cells */
1814 while (ent
->refcnt
) {
1818 ent
->refcnt
= AllocPrivate
;
1820 ent
->fShared
= FALSE
;
1825 else if (planes
> dplanes
) {
1829 /* General case count pixels * 2 ^ planes cells to be allocated */
1831 /* make room for new pixels */
1834 /* first try for contiguous planes, since it's fastest */
1835 for (mask
= (((Pixel
) 1) << planes
) - 1, base
= 1, dplanes
-= (planes
- 1);
1836 --dplanes
>= 0; mask
+= mask
, base
+= base
) {
1840 entries
= pmap
->pVisual
->ColormapEntries
- mask
;
1841 while (pixel
< entries
) {
1843 maxp
= pixel
+ mask
+ base
;
1844 /* check if all are free */
1845 while (pixel
!= maxp
&& ent
[pixel
].refcnt
== 0)
1847 if (pixel
== maxp
) {
1848 /* this one works */
1851 if (found
== count
) {
1852 /* found enough, allocate them all */
1853 while (--count
>= 0) {
1854 pixel
= pixels
[count
];
1855 maxp
= pixel
+ mask
;
1857 ent
[pixel
].refcnt
= AllocPrivate
;
1858 ent
[pixel
].fShared
= FALSE
;
1875 dplanes
= pmap
->pVisual
->nplanes
;
1876 if (contig
|| planes
== 1 || dplanes
< 3)
1879 /* this will be very slow for large maps, need a better algorithm */
1882 we can generate the smallest and largest numbers that fits in dplanes
1883 bits and contain exactly planes bits set as follows. First, we need to
1884 check that it is possible to generate such a mask at all.
1885 (Non-contiguous masks need one more bit than contiguous masks). Then
1886 the smallest such mask consists of the rightmost planes-1 bits set, then
1887 a zero, then a one in position planes + 1. The formula is
1888 (3 << (planes-1)) -1
1889 The largest such masks consists of the leftmost planes-1 bits set, then
1890 a zero, then a one bit in position dplanes-planes-1. If dplanes is
1891 smaller than 32 (the number of bits in a word) then the formula is:
1892 (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
1893 If dplanes = 32, then we can't calculate (1<<dplanes) and we have
1895 ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
1897 << Thank you, Loretta>>>
1902 (((((Pixel
) 1) << (planes
- 1)) - 1) << (dplanes
- planes
+ 1)) +
1903 (((Pixel
) 1) << (dplanes
- planes
- 1));
1904 for (mask
= (((Pixel
) 3) << (planes
- 1)) - 1; mask
<= finalmask
; mask
++) {
1905 /* next 3 magic statements count number of ones (HAKMEM #169) */
1906 pixel
= (mask
>> 1) & 033333333333;
1907 pixel
= mask
- pixel
- ((pixel
>> 1) & 033333333333);
1908 if ((((pixel
+ (pixel
>> 3)) & 030707070707) % 077) != planes
)
1912 entries
= pmap
->pVisual
->ColormapEntries
- mask
;
1913 base
= lowbit(mask
);
1914 for (pixel
= 0; pixel
< entries
; pixel
++) {
1918 /* check if all are free */
1919 while (ent
[pixel
+ maxp
].refcnt
== 0) {
1920 GetNextBitsOrBreak(maxp
, mask
, base
);
1922 if ((maxp
< mask
) || (ent
[pixel
+ mask
].refcnt
!= 0))
1924 /* this one works */
1929 /* found enough, allocate them all */
1930 while (--count
>= 0) {
1931 pixel
= (pixels
)[count
];
1934 ent
[pixel
+ maxp
].refcnt
= AllocPrivate
;
1935 ent
[pixel
+ maxp
].fShared
= FALSE
;
1936 GetNextBitsOrBreak(maxp
, mask
, base
);
1937 *ppix
++ = pixel
+ maxp
;
1950 * \param ppixFirst First of the client's new pixels
1953 AllocShared(ColormapPtr pmap
, Pixel
* ppix
, int c
, int r
, int g
, int b
,
1954 Pixel rmask
, Pixel gmask
, Pixel bmask
, Pixel
* ppixFirst
)
1957 int npix
, z
, npixClientNew
, npixShared
;
1958 Pixel basemask
, base
, bits
, common
;
1959 SHAREDCOLOR
*pshared
, **ppshared
, **psharedList
;
1961 npixClientNew
= c
<< (r
+ g
+ b
);
1962 npixShared
= (c
<< r
) + (c
<< g
) + (c
<< b
);
1963 psharedList
= malloc(npixShared
* sizeof(SHAREDCOLOR
*));
1966 ppshared
= psharedList
;
1967 for (z
= npixShared
; --z
>= 0;) {
1968 if (!(ppshared
[z
] = malloc(sizeof(SHAREDCOLOR
)))) {
1969 for (z
++; z
< npixShared
; z
++)
1975 for (pptr
= ppix
, npix
= c
; --npix
>= 0; pptr
++) {
1976 basemask
= ~(gmask
| bmask
);
1977 common
= *pptr
& basemask
;
1980 base
= lowbit(rmask
);
1982 pshared
= *ppshared
++;
1983 pshared
->refcnt
= 1 << (g
+ b
);
1984 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
1985 if ((*cptr
& basemask
) == (common
| bits
)) {
1986 pmap
->red
[*cptr
].fShared
= TRUE
;
1987 pmap
->red
[*cptr
].co
.shco
.red
= pshared
;
1990 GetNextBitsOrBreak(bits
, rmask
, base
);
1994 pshared
= *ppshared
++;
1995 pshared
->refcnt
= 1 << (g
+ b
);
1996 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
1997 if ((*cptr
& basemask
) == common
) {
1998 pmap
->red
[*cptr
].fShared
= TRUE
;
1999 pmap
->red
[*cptr
].co
.shco
.red
= pshared
;
2003 basemask
= ~(rmask
| bmask
);
2004 common
= *pptr
& basemask
;
2007 base
= lowbit(gmask
);
2009 pshared
= *ppshared
++;
2010 pshared
->refcnt
= 1 << (r
+ b
);
2011 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
2012 if ((*cptr
& basemask
) == (common
| bits
)) {
2013 pmap
->red
[*cptr
].co
.shco
.green
= pshared
;
2016 GetNextBitsOrBreak(bits
, gmask
, base
);
2020 pshared
= *ppshared
++;
2021 pshared
->refcnt
= 1 << (g
+ b
);
2022 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
2023 if ((*cptr
& basemask
) == common
) {
2024 pmap
->red
[*cptr
].co
.shco
.green
= pshared
;
2028 basemask
= ~(rmask
| gmask
);
2029 common
= *pptr
& basemask
;
2032 base
= lowbit(bmask
);
2034 pshared
= *ppshared
++;
2035 pshared
->refcnt
= 1 << (r
+ g
);
2036 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
2037 if ((*cptr
& basemask
) == (common
| bits
)) {
2038 pmap
->red
[*cptr
].co
.shco
.blue
= pshared
;
2041 GetNextBitsOrBreak(bits
, bmask
, base
);
2045 pshared
= *ppshared
++;
2046 pshared
->refcnt
= 1 << (g
+ b
);
2047 for (cptr
= ppixFirst
, z
= npixClientNew
; --z
>= 0; cptr
++) {
2048 if ((*cptr
& basemask
) == common
) {
2049 pmap
->red
[*cptr
].co
.shco
.blue
= pshared
;
2059 * Free colors and/or cells (probably slow for large numbers)
2062 FreeColors(ColormapPtr pmap
, int client
, int count
, Pixel
* pixels
, Pixel mask
)
2064 int rval
, result
, class;
2067 class = pmap
->class;
2068 if (pmap
->flags
& AllAllocated
)
2070 if ((class | DynamicClass
) == DirectColor
) {
2071 rmask
= mask
& RGBMASK(pmap
->pVisual
);
2072 result
= FreeCo(pmap
, client
, REDMAP
, count
, pixels
,
2073 mask
& pmap
->pVisual
->redMask
);
2074 /* If any of the three calls fails, we must report that, if more
2075 * than one fails, it's ok that we report the last one */
2076 rval
= FreeCo(pmap
, client
, GREENMAP
, count
, pixels
,
2077 mask
& pmap
->pVisual
->greenMask
);
2078 if (rval
!= Success
)
2080 rval
= FreeCo(pmap
, client
, BLUEMAP
, count
, pixels
,
2081 mask
& pmap
->pVisual
->blueMask
);
2082 if (rval
!= Success
)
2086 rmask
= mask
& ((((Pixel
) 1) << pmap
->pVisual
->nplanes
) - 1);
2087 result
= FreeCo(pmap
, client
, PSEUDOMAP
, count
, pixels
, rmask
);
2089 if ((mask
!= rmask
) && count
) {
2090 clients
[client
]->errorValue
= *pixels
| mask
;
2093 /* XXX should worry about removing any RT_CMAPENTRY resource */
2098 * Helper for FreeColors -- frees all combinations of *newpixels and mask bits
2099 * which the client has allocated in channel colormap cells of pmap.
2100 * doesn't change newpixels if it doesn't need to
2102 * \param pmap which colormap head
2103 * \param color which sub-map, eg, RED, BLUE, PSEUDO
2104 * \param npixIn number of pixels passed in
2105 * \param ppixIn number of base pixels
2106 * \param mask mask client gave us
2109 FreeCo(ColormapPtr pmap
, int client
, int color
, int npixIn
, Pixel
* ppixIn
,
2112 Pixel
*ppixClient
, pixTest
;
2113 int npixClient
, npixNew
, npix
;
2114 Pixel bits
, base
, cmask
, rgbbad
;
2117 int errVal
= Success
;
2118 int offset
, numents
;
2124 base
= lowbit(mask
);
2128 cmask
= pmap
->pVisual
->redMask
;
2129 rgbbad
= ~RGBMASK(pmap
->pVisual
);
2130 offset
= pmap
->pVisual
->offsetRed
;
2131 numents
= (cmask
>> offset
) + 1;
2132 ppixClient
= pmap
->clientPixelsRed
[client
];
2133 npixClient
= pmap
->numPixelsRed
[client
];
2136 cmask
= pmap
->pVisual
->greenMask
;
2137 rgbbad
= ~RGBMASK(pmap
->pVisual
);
2138 offset
= pmap
->pVisual
->offsetGreen
;
2139 numents
= (cmask
>> offset
) + 1;
2140 ppixClient
= pmap
->clientPixelsGreen
[client
];
2141 npixClient
= pmap
->numPixelsGreen
[client
];
2144 cmask
= pmap
->pVisual
->blueMask
;
2145 rgbbad
= ~RGBMASK(pmap
->pVisual
);
2146 offset
= pmap
->pVisual
->offsetBlue
;
2147 numents
= (cmask
>> offset
) + 1;
2148 ppixClient
= pmap
->clientPixelsBlue
[client
];
2149 npixClient
= pmap
->numPixelsBlue
[client
];
2151 default: /* so compiler can see that everything gets initialized */
2153 cmask
= ~((Pixel
) 0);
2156 numents
= pmap
->pVisual
->ColormapEntries
;
2157 ppixClient
= pmap
->clientPixelsRed
[client
];
2158 npixClient
= pmap
->numPixelsRed
[client
];
2162 /* zap all pixels which match */
2164 /* go through pixel list */
2165 for (pptr
= ppixIn
, n
= npixIn
; --n
>= 0; pptr
++) {
2166 pixTest
= ((*pptr
| bits
) & cmask
) >> offset
;
2167 if ((pixTest
>= numents
) || (*pptr
& rgbbad
)) {
2168 clients
[client
]->errorValue
= *pptr
| bits
;
2173 /* find match in client list */
2174 for (cptr
= ppixClient
, npix
= npixClient
;
2175 --npix
>= 0 && *cptr
!= pixTest
; cptr
++);
2178 if (pmap
->class & DynamicClass
) {
2179 FreeCell(pmap
, pixTest
, color
);
2181 *cptr
= ~((Pixel
) 0);
2187 /* generate next bits value */
2188 GetNextBitsOrBreak(bits
, mask
, base
);
2191 /* delete freed pixels from client pixel list */
2193 npixNew
= npixClient
- zapped
;
2195 /* Since the list can only get smaller, we can do a copy in
2196 * place and then realloc to a smaller size */
2197 pptr
= cptr
= ppixClient
;
2199 /* If we have all the new pixels, we don't have to examine the
2200 * rest of the old ones */
2201 for (npix
= 0; npix
< npixNew
; cptr
++) {
2202 if (*cptr
!= ~((Pixel
) 0)) {
2207 pptr
= (Pixel
*) realloc(ppixClient
, npixNew
* sizeof(Pixel
));
2210 npixClient
= npixNew
;
2215 ppixClient
= (Pixel
*) NULL
;
2220 pmap
->clientPixelsRed
[client
] = ppixClient
;
2221 pmap
->numPixelsRed
[client
] = npixClient
;
2224 pmap
->clientPixelsGreen
[client
] = ppixClient
;
2225 pmap
->numPixelsGreen
[client
] = npixClient
;
2228 pmap
->clientPixelsBlue
[client
] = ppixClient
;
2229 pmap
->numPixelsBlue
[client
] = npixClient
;
2236 /* Redefine color values */
2238 StoreColors(ColormapPtr pmap
, int count
, xColorItem
* defs
, ClientPtr client
)
2242 EntryPtr pent
, pentT
, pentLast
;
2244 SHAREDCOLOR
*pred
, *pgreen
, *pblue
;
2245 int n
, ChgRed
, ChgGreen
, ChgBlue
, idef
;
2246 int class, errVal
= Success
;
2249 class = pmap
->class;
2250 if (!(class & DynamicClass
) && !(pmap
->flags
& BeingCreated
)) {
2253 pVisual
= pmap
->pVisual
;
2256 if ((class | DynamicClass
) == DirectColor
) {
2257 int numred
, numgreen
, numblue
;
2260 numred
= NUMRED(pVisual
);
2261 numgreen
= NUMGREEN(pVisual
);
2262 numblue
= NUMBLUE(pVisual
);
2263 rgbbad
= ~RGBMASK(pVisual
);
2264 for (pdef
= defs
, n
= 0; n
< count
; pdef
++, n
++) {
2266 (*pmap
->pScreen
->ResolveColor
)
2267 (&pdef
->red
, &pdef
->green
, &pdef
->blue
, pmap
->pVisual
);
2269 if (pdef
->pixel
& rgbbad
) {
2271 client
->errorValue
= pdef
->pixel
;
2274 pix
= (pdef
->pixel
& pVisual
->redMask
) >> pVisual
->offsetRed
;
2275 if (pix
>= numred
) {
2279 else if (pmap
->red
[pix
].refcnt
!= AllocPrivate
) {
2283 else if (pdef
->flags
& DoRed
) {
2284 pmap
->red
[pix
].co
.local
.red
= pdef
->red
;
2287 pdef
->red
= pmap
->red
[pix
].co
.local
.red
;
2290 pix
= (pdef
->pixel
& pVisual
->greenMask
) >> pVisual
->offsetGreen
;
2291 if (pix
>= numgreen
) {
2295 else if (pmap
->green
[pix
].refcnt
!= AllocPrivate
) {
2299 else if (pdef
->flags
& DoGreen
) {
2300 pmap
->green
[pix
].co
.local
.green
= pdef
->green
;
2303 pdef
->green
= pmap
->green
[pix
].co
.local
.green
;
2306 pix
= (pdef
->pixel
& pVisual
->blueMask
) >> pVisual
->offsetBlue
;
2307 if (pix
>= numblue
) {
2311 else if (pmap
->blue
[pix
].refcnt
!= AllocPrivate
) {
2315 else if (pdef
->flags
& DoBlue
) {
2316 pmap
->blue
[pix
].co
.local
.blue
= pdef
->blue
;
2319 pdef
->blue
= pmap
->blue
[pix
].co
.local
.blue
;
2321 /* If this is an o.k. entry, then it gets added to the list
2322 * to be sent to the hardware. If not, skip it. Once we've
2323 * skipped one, we have to copy all the others.
2327 defs
[idef
] = defs
[n
];
2331 client
->errorValue
= pdef
->pixel
;
2335 for (pdef
= defs
, n
= 0; n
< count
; pdef
++, n
++) {
2338 if (pdef
->pixel
>= pVisual
->ColormapEntries
) {
2339 client
->errorValue
= pdef
->pixel
;
2343 else if (pmap
->red
[pdef
->pixel
].refcnt
!= AllocPrivate
) {
2348 /* If this is an o.k. entry, then it gets added to the list
2349 * to be sent to the hardware. If not, skip it. Once we've
2350 * skipped one, we have to copy all the others.
2354 defs
[idef
] = defs
[n
];
2360 (*pmap
->pScreen
->ResolveColor
)
2361 (&pdef
->red
, &pdef
->green
, &pdef
->blue
, pmap
->pVisual
);
2363 pent
= &pmap
->red
[pdef
->pixel
];
2365 if (pdef
->flags
& DoRed
) {
2366 if (pent
->fShared
) {
2367 pent
->co
.shco
.red
->color
= pdef
->red
;
2368 if (pent
->co
.shco
.red
->refcnt
> 1)
2372 pent
->co
.local
.red
= pdef
->red
;
2376 pdef
->red
= pent
->co
.shco
.red
->color
;
2378 pdef
->red
= pent
->co
.local
.red
;
2380 if (pdef
->flags
& DoGreen
) {
2381 if (pent
->fShared
) {
2382 pent
->co
.shco
.green
->color
= pdef
->green
;
2383 if (pent
->co
.shco
.green
->refcnt
> 1)
2387 pent
->co
.local
.green
= pdef
->green
;
2391 pdef
->green
= pent
->co
.shco
.green
->color
;
2393 pdef
->green
= pent
->co
.local
.green
;
2395 if (pdef
->flags
& DoBlue
) {
2396 if (pent
->fShared
) {
2397 pent
->co
.shco
.blue
->color
= pdef
->blue
;
2398 if (pent
->co
.shco
.blue
->refcnt
> 1)
2402 pent
->co
.local
.blue
= pdef
->blue
;
2406 pdef
->blue
= pent
->co
.shco
.blue
->color
;
2408 pdef
->blue
= pent
->co
.local
.blue
;
2412 /* have to run through the colormap and change anybody who
2413 * shares this value */
2414 pred
= pent
->co
.shco
.red
;
2415 pgreen
= pent
->co
.shco
.green
;
2416 pblue
= pent
->co
.shco
.blue
;
2417 ChgRed
= pdef
->flags
& DoRed
;
2418 ChgGreen
= pdef
->flags
& DoGreen
;
2419 ChgBlue
= pdef
->flags
& DoBlue
;
2420 pentLast
= pmap
->red
+ pVisual
->ColormapEntries
;
2422 for (pentT
= pmap
->red
; pentT
< pentLast
; pentT
++) {
2423 if (pentT
->fShared
&& (pentT
!= pent
)) {
2426 /* There are, alas, devices in this world too dumb
2427 * to read their own hardware colormaps. Sick, but
2428 * true. So we're going to be really nice and load
2429 * the xColorItem with the proper value for all the
2430 * fields. We will only set the flags for those
2431 * fields that actually change. Smart devices can
2432 * arrange to change only those fields. Dumb devices
2433 * can rest assured that we have provided for them,
2434 * and can change all three fields */
2437 if (ChgRed
&& pentT
->co
.shco
.red
== pred
) {
2438 defChg
.flags
|= DoRed
;
2440 if (ChgGreen
&& pentT
->co
.shco
.green
== pgreen
) {
2441 defChg
.flags
|= DoGreen
;
2443 if (ChgBlue
&& pentT
->co
.shco
.blue
== pblue
) {
2444 defChg
.flags
|= DoBlue
;
2446 if (defChg
.flags
!= 0) {
2447 defChg
.pixel
= pentT
- pmap
->red
;
2448 defChg
.red
= pentT
->co
.shco
.red
->color
;
2449 defChg
.green
= pentT
->co
.shco
.green
->color
;
2450 defChg
.blue
= pentT
->co
.shco
.blue
->color
;
2451 (*pmap
->pScreen
->StoreColors
) (pmap
, 1, &defChg
);
2459 /* Note that we use idef, the count of acceptable entries, and not
2460 * count, the count of proposed entries */
2462 (*pmap
->pScreen
->StoreColors
) (pmap
, idef
, defs
);
2467 IsMapInstalled(Colormap map
, WindowPtr pWin
)
2470 int imap
, nummaps
, found
;
2473 malloc(pWin
->drawable
.pScreen
->maxInstalledCmaps
* sizeof(Colormap
));
2476 nummaps
= (*pWin
->drawable
.pScreen
->ListInstalledColormaps
)
2477 (pWin
->drawable
.pScreen
, pmaps
);
2479 for (imap
= 0; imap
< nummaps
; imap
++) {
2480 if (pmaps
[imap
] == map
) {
2489 struct colormap_lookup_data
{
2495 _colormap_find_resource(pointer value
, XID id
, pointer cdata
)
2497 struct colormap_lookup_data
*cmap_data
= cdata
;
2498 VisualPtr visuals
= cmap_data
->visuals
;
2499 ScreenPtr pScreen
= cmap_data
->pScreen
;
2500 ColormapPtr cmap
= value
;
2503 if (pScreen
!= cmap
->pScreen
)
2506 j
= cmap
->pVisual
- pScreen
->visuals
;
2507 cmap
->pVisual
= &visuals
[j
];
2510 /* something has realloced the visuals, instead of breaking
2511 ABI fix it up here - glx and compsite did this wrong */
2513 ResizeVisualArray(ScreenPtr pScreen
, int new_visual_count
, DepthPtr depth
)
2515 struct colormap_lookup_data cdata
;
2519 int first_new_vid
, first_new_visual
, i
;
2521 first_new_vid
= depth
->numVids
;
2522 first_new_visual
= pScreen
->numVisuals
;
2525 realloc(depth
->vids
, (depth
->numVids
+ new_visual_count
) * sizeof(XID
));
2529 /* its realloced now no going back if we fail the next one */
2532 numVisuals
= pScreen
->numVisuals
+ new_visual_count
;
2533 visuals
= realloc(pScreen
->visuals
, numVisuals
* sizeof(VisualRec
));
2538 cdata
.visuals
= visuals
;
2539 cdata
.pScreen
= pScreen
;
2540 FindClientResourcesByType(serverClient
, RT_COLORMAP
,
2541 _colormap_find_resource
, &cdata
);
2543 pScreen
->visuals
= visuals
;
2545 for (i
= 0; i
< new_visual_count
; i
++) {
2546 vid
= FakeClientID(0);
2547 pScreen
->visuals
[first_new_visual
+ i
].vid
= vid
;
2548 vids
[first_new_vid
+ i
] = vid
;
2551 depth
->numVids
+= new_visual_count
;
2552 pScreen
->numVisuals
+= new_visual_count
;