picture.c revision 4642e01f
1/*
2 *
3 * Copyright © 2000 SuSE, Inc.
4 *
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
9 * documentation, and that the name of SuSE not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission.  SuSE makes no representations about the
12 * suitability of this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 *
15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  Keith Packard, SuSE, Inc.
23 */
24
25#ifdef HAVE_DIX_CONFIG_H
26#include <dix-config.h>
27#endif
28
29#include "misc.h"
30#include "scrnintstr.h"
31#include "os.h"
32#include "regionstr.h"
33#include "validate.h"
34#include "windowstr.h"
35#include "input.h"
36#include "resource.h"
37#include "colormapst.h"
38#include "cursorstr.h"
39#include "dixstruct.h"
40#include "gcstruct.h"
41#include "servermd.h"
42#include "picturestr.h"
43#include "xace.h"
44#include "registry.h"
45
46static int PictureScreenPrivateKeyIndex;
47_X_EXPORT DevPrivateKey PictureScreenPrivateKey = &PictureScreenPrivateKeyIndex;
48static int PictureWindowPrivateKeyIndex;
49DevPrivateKey	PictureWindowPrivateKey = &PictureWindowPrivateKeyIndex;
50static int	PictureGeneration;
51RESTYPE		PictureType;
52RESTYPE		PictFormatType;
53RESTYPE		GlyphSetType;
54int		PictureCmapPolicy = PictureCmapPolicyDefault;
55
56Bool
57PictureDestroyWindow (WindowPtr pWindow)
58{
59    ScreenPtr		pScreen = pWindow->drawable.pScreen;
60    PicturePtr		pPicture;
61    PictureScreenPtr    ps = GetPictureScreen(pScreen);
62    Bool		ret;
63
64    while ((pPicture = GetPictureWindow(pWindow)))
65    {
66	SetPictureWindow(pWindow, pPicture->pNext);
67	if (pPicture->id)
68	    FreeResource (pPicture->id, PictureType);
69	FreePicture ((pointer) pPicture, pPicture->id);
70    }
71    pScreen->DestroyWindow = ps->DestroyWindow;
72    ret = (*pScreen->DestroyWindow) (pWindow);
73    ps->DestroyWindow = pScreen->DestroyWindow;
74    pScreen->DestroyWindow = PictureDestroyWindow;
75    return ret;
76}
77
78Bool
79PictureCloseScreen (int index, ScreenPtr pScreen)
80{
81    PictureScreenPtr    ps = GetPictureScreen(pScreen);
82    Bool                ret;
83    int			n;
84
85    pScreen->CloseScreen = ps->CloseScreen;
86    ret = (*pScreen->CloseScreen) (index, pScreen);
87    PictureResetFilters (pScreen);
88    for (n = 0; n < ps->nformats; n++)
89	if (ps->formats[n].type == PictTypeIndexed)
90	    (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
91    GlyphUninit (pScreen);
92    SetPictureScreen(pScreen, 0);
93    xfree (ps->formats);
94    xfree (ps);
95    return ret;
96}
97
98void
99PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef)
100{
101    ScreenPtr		pScreen = pColormap->pScreen;
102    PictureScreenPtr    ps = GetPictureScreen(pScreen);
103
104    pScreen->StoreColors = ps->StoreColors;
105    (*pScreen->StoreColors) (pColormap, ndef, pdef);
106    ps->StoreColors = pScreen->StoreColors;
107    pScreen->StoreColors = PictureStoreColors;
108
109    if (pColormap->class == PseudoColor || pColormap->class == GrayScale)
110    {
111	PictFormatPtr	format = ps->formats;
112	int		nformats = ps->nformats;
113
114	while (nformats--)
115	{
116	    if (format->type == PictTypeIndexed &&
117		format->index.pColormap == pColormap)
118	    {
119		(*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
120		break;
121	    }
122	    format++;
123	}
124    }
125}
126
127static int
128visualDepth (ScreenPtr pScreen, VisualPtr pVisual)
129{
130    int		d, v;
131    DepthPtr	pDepth;
132
133    for (d = 0; d < pScreen->numDepths; d++)
134    {
135	pDepth = &pScreen->allowedDepths[d];
136	for (v = 0; v < pDepth->numVids; v++)
137	    if (pDepth->vids[v] == pVisual->vid)
138		return pDepth->depth;
139    }
140    return 0;
141}
142
143typedef struct _formatInit {
144    CARD32  format;
145    CARD8   depth;
146} FormatInitRec, *FormatInitPtr;
147
148static int
149addFormat (FormatInitRec    formats[256],
150	   int		    nformat,
151	   CARD32	    format,
152	   CARD8	    depth)
153{
154    int	n;
155
156    for (n = 0; n < nformat; n++)
157	if (formats[n].format == format && formats[n].depth == depth)
158	    return nformat;
159    formats[nformat].format = format;
160    formats[nformat].depth = depth;
161    return ++nformat;
162}
163
164#define Mask(n)	((n) == 32 ? 0xffffffff : ((1 << (n))-1))
165
166PictFormatPtr
167PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
168{
169    int		    nformats, f;
170    PictFormatPtr   pFormats;
171    FormatInitRec   formats[1024];
172    CARD32	    format;
173    CARD8	    depth;
174    VisualPtr	    pVisual;
175    int		    v;
176    int		    bpp;
177    int		    type;
178    int		    r, g, b;
179    int		    d;
180    DepthPtr	    pDepth;
181
182    nformats = 0;
183    /* formats required by protocol */
184    formats[nformats].format = PICT_a1;
185    formats[nformats].depth = 1;
186    nformats++;
187    formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
188					   PICT_TYPE_A,
189					   8, 0, 0, 0);
190    formats[nformats].depth = 8;
191    nformats++;
192    formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
193					   PICT_TYPE_A,
194					   4, 0, 0, 0);
195    formats[nformats].depth = 4;
196    nformats++;
197    formats[nformats].format = PICT_a8r8g8b8;
198    formats[nformats].depth = 32;
199    nformats++;
200    formats[nformats].format = PICT_x8r8g8b8;
201    formats[nformats].depth = 32;
202    nformats++;
203
204    /* now look through the depths and visuals adding other formats */
205    for (v = 0; v < pScreen->numVisuals; v++)
206    {
207	pVisual = &pScreen->visuals[v];
208	depth = visualDepth (pScreen, pVisual);
209	if (!depth)
210	    continue;
211    	bpp = BitsPerPixel (depth);
212	switch (pVisual->class) {
213	case DirectColor:
214	case TrueColor:
215	    r = Ones (pVisual->redMask);
216	    g = Ones (pVisual->greenMask);
217	    b = Ones (pVisual->blueMask);
218	    type = PICT_TYPE_OTHER;
219	    /*
220	     * Current rendering code supports only two direct formats,
221	     * fields must be packed together at the bottom of the pixel
222	     * and must be either RGB or BGR
223	     */
224	    if (pVisual->offsetBlue == 0 &&
225		pVisual->offsetGreen == b &&
226		pVisual->offsetRed == b + g)
227	    {
228		type = PICT_TYPE_ARGB;
229	    }
230	    else if (pVisual->offsetRed == 0 &&
231		     pVisual->offsetGreen == r &&
232		     pVisual->offsetBlue == r + g)
233	    {
234		type = PICT_TYPE_ABGR;
235	    }
236	    if (type != PICT_TYPE_OTHER)
237	    {
238		format = PICT_FORMAT(bpp, type, 0, r, g, b);
239		nformats = addFormat (formats, nformats, format, depth);
240	    }
241	    break;
242	case StaticColor:
243	case PseudoColor:
244	    format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v);
245	    nformats = addFormat (formats, nformats, format, depth);
246	    break;
247	case StaticGray:
248	case GrayScale:
249	    format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v);
250	    nformats = addFormat (formats, nformats, format, depth);
251	    break;
252	}
253    }
254    /*
255     * Walk supported depths and add useful Direct formats
256     */
257    for (d = 0; d < pScreen->numDepths; d++)
258    {
259	pDepth = &pScreen->allowedDepths[d];
260	bpp = BitsPerPixel (pDepth->depth);
261	format = 0;
262	switch (bpp) {
263	case 16:
264	    /* depth 12 formats */
265	    if (pDepth->depth >= 12)
266	    {
267		nformats = addFormat (formats, nformats,
268				      PICT_x4r4g4b4, pDepth->depth);
269		nformats = addFormat (formats, nformats,
270				      PICT_x4b4g4r4, pDepth->depth);
271	    }
272	    /* depth 15 formats */
273	    if (pDepth->depth >= 15)
274	    {
275		nformats = addFormat (formats, nformats,
276				      PICT_x1r5g5b5, pDepth->depth);
277		nformats = addFormat (formats, nformats,
278				      PICT_x1b5g5r5, pDepth->depth);
279	    }
280	    /* depth 16 formats */
281	    if (pDepth->depth >= 16)
282	    {
283		nformats = addFormat (formats, nformats,
284				      PICT_a1r5g5b5, pDepth->depth);
285		nformats = addFormat (formats, nformats,
286				      PICT_a1b5g5r5, pDepth->depth);
287		nformats = addFormat (formats, nformats,
288				      PICT_r5g6b5, pDepth->depth);
289		nformats = addFormat (formats, nformats,
290				      PICT_b5g6r5, pDepth->depth);
291		nformats = addFormat (formats, nformats,
292				      PICT_a4r4g4b4, pDepth->depth);
293		nformats = addFormat (formats, nformats,
294				      PICT_a4b4g4r4, pDepth->depth);
295	    }
296	    break;
297	case 24:
298	    if (pDepth->depth >= 24)
299	    {
300		nformats = addFormat (formats, nformats,
301				      PICT_r8g8b8, pDepth->depth);
302		nformats = addFormat (formats, nformats,
303				      PICT_b8g8r8, pDepth->depth);
304	    }
305	    break;
306	case 32:
307	    if (pDepth->depth >= 24)
308	    {
309		nformats = addFormat (formats, nformats,
310				      PICT_x8r8g8b8, pDepth->depth);
311		nformats = addFormat (formats, nformats,
312				      PICT_x8b8g8r8, pDepth->depth);
313	    }
314	    break;
315	}
316    }
317
318
319    pFormats = xcalloc (nformats, sizeof (PictFormatRec));
320    if (!pFormats)
321	return 0;
322    for (f = 0; f < nformats; f++)
323    {
324        pFormats[f].id = FakeClientID (0);
325	pFormats[f].depth = formats[f].depth;
326	format = formats[f].format;
327	pFormats[f].format = format;
328	switch (PICT_FORMAT_TYPE(format)) {
329	case PICT_TYPE_ARGB:
330	    pFormats[f].type = PictTypeDirect;
331
332	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
333	    if (pFormats[f].direct.alphaMask)
334		pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
335					    PICT_FORMAT_G(format) +
336					    PICT_FORMAT_B(format));
337
338	    pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
339	    pFormats[f].direct.red = (PICT_FORMAT_G(format) +
340				      PICT_FORMAT_B(format));
341
342	    pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
343	    pFormats[f].direct.green = PICT_FORMAT_B(format);
344
345	    pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
346	    pFormats[f].direct.blue = 0;
347	    break;
348
349	case PICT_TYPE_ABGR:
350	    pFormats[f].type = PictTypeDirect;
351
352	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
353	    if (pFormats[f].direct.alphaMask)
354		pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
355					    PICT_FORMAT_G(format) +
356					    PICT_FORMAT_R(format));
357
358	    pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
359	    pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
360				       PICT_FORMAT_R(format));
361
362	    pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
363	    pFormats[f].direct.green = PICT_FORMAT_R(format);
364
365	    pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
366	    pFormats[f].direct.red = 0;
367	    break;
368
369	case PICT_TYPE_A:
370	    pFormats[f].type = PictTypeDirect;
371
372	    pFormats[f].direct.alpha = 0;
373	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
374
375	    /* remaining fields already set to zero */
376	    break;
377
378	case PICT_TYPE_COLOR:
379	case PICT_TYPE_GRAY:
380	    pFormats[f].type = PictTypeIndexed;
381	    pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
382	    break;
383	}
384    }
385    *nformatp = nformats;
386    return pFormats;
387}
388
389static VisualPtr
390PictureFindVisual (ScreenPtr pScreen, VisualID visual)
391{
392    int         i;
393    VisualPtr   pVisual;
394    for (i = 0, pVisual = pScreen->visuals;
395         i < pScreen->numVisuals;
396         i++, pVisual++)
397    {
398        if (pVisual->vid == visual)
399            return pVisual;
400    }
401    return 0;
402}
403
404Bool
405PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
406{
407    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
408
409    if (format->type != PictTypeIndexed || format->index.pColormap)
410	return TRUE;
411
412    if (format->index.vid == pScreen->rootVisual) {
413	format->index.pColormap =
414	    (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
415    } else {
416	VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid);
417	if (CreateColormap(FakeClientID (0), pScreen, pVisual,
418		    &format->index.pColormap, AllocNone, 0)
419		!= Success)
420	    return FALSE;
421    }
422    if (!ps->InitIndexed(pScreen, format))
423	return FALSE;
424    return TRUE;
425}
426
427static Bool
428PictureInitIndexedFormats (ScreenPtr pScreen)
429{
430    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
431    PictFormatPtr	format;
432    int			nformat;
433
434    if (!ps)
435	return FALSE;
436    format = ps->formats;
437    nformat = ps->nformats;
438    while (nformat--)
439	if (!PictureInitIndexedFormat(pScreen, format++))
440	    return FALSE;
441    return TRUE;
442}
443
444Bool
445PictureFinishInit (void)
446{
447    int	    s;
448
449    for (s = 0; s < screenInfo.numScreens; s++)
450    {
451	if (!PictureInitIndexedFormats (screenInfo.screens[s]))
452	    return FALSE;
453	(void) AnimCurInit (screenInfo.screens[s]);
454    }
455
456    return TRUE;
457}
458
459_X_EXPORT Bool
460PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel)
461{
462    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
463
464    if (!ps)
465	return FALSE;
466    ps->subpixel = subpixel;
467    return TRUE;
468
469}
470
471_X_EXPORT int
472PictureGetSubpixelOrder (ScreenPtr pScreen)
473{
474    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
475
476    if (!ps)
477	return SubPixelUnknown;
478    return ps->subpixel;
479}
480
481PictFormatPtr
482PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual)
483{
484    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
485    PictFormatPtr	format;
486    int			nformat;
487    int			type;
488
489    if (!ps)
490	return 0;
491    format = ps->formats;
492    nformat = ps->nformats;
493    switch (pVisual->class) {
494    case StaticGray:
495    case GrayScale:
496    case StaticColor:
497    case PseudoColor:
498	type = PictTypeIndexed;
499	break;
500    case TrueColor:
501    case DirectColor:
502	type = PictTypeDirect;
503	break;
504    default:
505	return 0;
506    }
507    while (nformat--)
508    {
509	if (format->depth == depth && format->type == type)
510	{
511	    if (type == PictTypeIndexed)
512	    {
513		if (format->index.vid == pVisual->vid)
514		    return format;
515	    }
516	    else
517	    {
518		if (format->direct.redMask << format->direct.red ==
519		    pVisual->redMask &&
520		    format->direct.greenMask << format->direct.green ==
521		    pVisual->greenMask &&
522		    format->direct.blueMask << format->direct.blue ==
523		    pVisual->blueMask)
524		{
525		    return format;
526		}
527	    }
528	}
529	format++;
530    }
531    return 0;
532}
533
534PictFormatPtr
535PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f)
536{
537    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
538    PictFormatPtr	format;
539    int			nformat;
540
541    if (!ps)
542	return 0;
543    format = ps->formats;
544    nformat = ps->nformats;
545    while (nformat--)
546    {
547	if (format->depth == depth && format->format == (f & 0xffffff))
548	    return format;
549	format++;
550    }
551    return 0;
552}
553
554int
555PictureParseCmapPolicy (const char *name)
556{
557    if ( strcmp (name, "default" ) == 0)
558	return PictureCmapPolicyDefault;
559    else if ( strcmp (name, "mono" ) == 0)
560	return PictureCmapPolicyMono;
561    else if ( strcmp (name, "gray" ) == 0)
562	return PictureCmapPolicyGray;
563    else if ( strcmp (name, "color" ) == 0)
564	return PictureCmapPolicyColor;
565    else if ( strcmp (name, "all" ) == 0)
566	return PictureCmapPolicyAll;
567    else
568	return PictureCmapPolicyInvalid;
569}
570
571_X_EXPORT Bool
572PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
573{
574    PictureScreenPtr	ps;
575    int			n;
576    CARD32		type, a, r, g, b;
577
578    if (PictureGeneration != serverGeneration)
579    {
580	PictureType = CreateNewResourceType (FreePicture);
581	if (!PictureType)
582	    return FALSE;
583	PictFormatType = CreateNewResourceType (FreePictFormat);
584	if (!PictFormatType)
585	    return FALSE;
586	GlyphSetType = CreateNewResourceType (FreeGlyphSet);
587	if (!GlyphSetType)
588	    return FALSE;
589	PictureGeneration = serverGeneration;
590	RegisterResourceName (PictureType, "PICTURE");
591	RegisterResourceName (PictFormatType, "PICTFORMAT");
592	RegisterResourceName (GlyphSetType, "GLYPHSET");
593    }
594    if (!formats)
595    {
596	formats = PictureCreateDefaultFormats (pScreen, &nformats);
597	if (!formats)
598	    return FALSE;
599    }
600    for (n = 0; n < nformats; n++)
601    {
602	if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n)))
603	{
604	    xfree (formats);
605	    return FALSE;
606	}
607	if (formats[n].type == PictTypeIndexed)
608	{
609            VisualPtr   pVisual = PictureFindVisual (pScreen, formats[n].index.vid);
610	    if ((pVisual->class | DynamicClass) == PseudoColor)
611		type = PICT_TYPE_COLOR;
612	    else
613		type = PICT_TYPE_GRAY;
614	    a = r = g = b = 0;
615	}
616	else
617	{
618	    if ((formats[n].direct.redMask|
619		 formats[n].direct.blueMask|
620		 formats[n].direct.greenMask) == 0)
621		type = PICT_TYPE_A;
622	    else if (formats[n].direct.red > formats[n].direct.blue)
623		type = PICT_TYPE_ARGB;
624	    else
625		type = PICT_TYPE_ABGR;
626	    a = Ones (formats[n].direct.alphaMask);
627	    r = Ones (formats[n].direct.redMask);
628	    g = Ones (formats[n].direct.greenMask);
629	    b = Ones (formats[n].direct.blueMask);
630	}
631	formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
632    }
633    ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec));
634    if (!ps)
635    {
636	xfree (formats);
637	return FALSE;
638    }
639    SetPictureScreen(pScreen, ps);
640
641    ps->formats = formats;
642    ps->fallback = formats;
643    ps->nformats = nformats;
644
645    ps->filters = 0;
646    ps->nfilters = 0;
647    ps->filterAliases = 0;
648    ps->nfilterAliases = 0;
649
650    ps->subpixel = SubPixelUnknown;
651
652    ps->CloseScreen = pScreen->CloseScreen;
653    ps->DestroyWindow = pScreen->DestroyWindow;
654    ps->StoreColors = pScreen->StoreColors;
655    pScreen->DestroyWindow = PictureDestroyWindow;
656    pScreen->CloseScreen = PictureCloseScreen;
657    pScreen->StoreColors = PictureStoreColors;
658
659    if (!PictureSetDefaultFilters (pScreen))
660    {
661	PictureResetFilters (pScreen);
662	SetPictureScreen(pScreen, 0);
663	xfree (formats);
664	xfree (ps);
665	return FALSE;
666    }
667
668    return TRUE;
669}
670
671void
672SetPictureToDefaults (PicturePtr    pPicture)
673{
674    pPicture->refcnt = 1;
675    pPicture->repeat = 0;
676    pPicture->graphicsExposures = FALSE;
677    pPicture->subWindowMode = ClipByChildren;
678    pPicture->polyEdge = PolyEdgeSharp;
679    pPicture->polyMode = PolyModePrecise;
680    pPicture->freeCompClip = FALSE;
681    pPicture->clientClipType = CT_NONE;
682    pPicture->componentAlpha = FALSE;
683    pPicture->repeatType = RepeatNone;
684
685    pPicture->alphaMap = 0;
686    pPicture->alphaOrigin.x = 0;
687    pPicture->alphaOrigin.y = 0;
688
689    pPicture->clipOrigin.x = 0;
690    pPicture->clipOrigin.y = 0;
691    pPicture->clientClip = 0;
692
693    pPicture->transform = 0;
694
695    pPicture->dither = None;
696    pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
697    pPicture->filter_params = 0;
698    pPicture->filter_nparams = 0;
699
700    pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
701    pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
702    pPicture->pSourcePict = 0;
703}
704
705PicturePtr
706CreatePicture (Picture		pid,
707	       DrawablePtr	pDrawable,
708	       PictFormatPtr	pFormat,
709	       Mask		vmask,
710	       XID		*vlist,
711	       ClientPtr	client,
712	       int		*error)
713{
714    PicturePtr		pPicture;
715    PictureScreenPtr	ps = GetPictureScreen(pDrawable->pScreen);
716
717    pPicture = (PicturePtr)xalloc(sizeof(PictureRec));
718    if (!pPicture)
719    {
720	*error = BadAlloc;
721	return 0;
722    }
723
724    pPicture->id = pid;
725    pPicture->pDrawable = pDrawable;
726    pPicture->pFormat = pFormat;
727    pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
728    pPicture->devPrivates = NULL;
729
730    /* security creation/labeling check */
731    *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
732		      RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
733    if (*error != Success)
734	goto out;
735
736    if (pDrawable->type == DRAWABLE_PIXMAP)
737    {
738	++((PixmapPtr)pDrawable)->refcnt;
739	pPicture->pNext = 0;
740    }
741    else
742    {
743	pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
744	SetPictureWindow(((WindowPtr) pDrawable), pPicture);
745    }
746
747    SetPictureToDefaults (pPicture);
748
749    if (vmask)
750	*error = ChangePicture (pPicture, vmask, vlist, 0, client);
751    else
752	*error = Success;
753    if (*error == Success)
754	*error = (*ps->CreatePicture) (pPicture);
755out:
756    if (*error != Success)
757    {
758	FreePicture (pPicture, (XID) 0);
759	pPicture = 0;
760    }
761    return pPicture;
762}
763
764static CARD32 xRenderColorToCard32(xRenderColor c)
765{
766    return
767        (c.alpha >> 8 << 24) |
768        (c.red >> 8 << 16) |
769        (c.green & 0xff00) |
770        (c.blue >> 8);
771}
772
773static unsigned int premultiply(unsigned int x)
774{
775    unsigned int a = x >> 24;
776    unsigned int t = (x & 0xff00ff) * a + 0x800080;
777    t = (t + ((t >> 8) & 0xff00ff)) >> 8;
778    t &= 0xff00ff;
779
780    x = ((x >> 8) & 0xff) * a + 0x80;
781    x = (x + ((x >> 8) & 0xff));
782    x &= 0xff00;
783    x |= t | (a << 24);
784    return x;
785}
786
787static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
788                                          unsigned int y, unsigned int b)
789{
790    CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
791    t >>= 8;
792    t &= 0xff00ff;
793
794    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
795    x &= 0xff00ff00;
796    x |= t;
797    return x;
798}
799
800CARD32
801PictureGradientColor (PictGradientStopPtr stop1,
802		      PictGradientStopPtr stop2,
803		      CARD32	          x)
804{
805     CARD32 current_color, next_color;
806     int	   dist, idist;
807
808     current_color = xRenderColorToCard32 (stop1->color);
809     next_color    = xRenderColorToCard32 (stop2->color);
810
811     dist  = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
812     idist = 256 - dist;
813
814     return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
815					       next_color, dist));
816}
817
818static void initGradient(SourcePictPtr pGradient, int stopCount,
819                         xFixed *stopPoints, xRenderColor *stopColors, int *error)
820{
821    int i;
822    xFixed dpos;
823
824    if (stopCount <= 0) {
825        *error = BadValue;
826        return;
827    }
828
829    dpos = -1;
830    for (i = 0; i < stopCount; ++i) {
831        if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
832            *error = BadValue;
833            return;
834        }
835        dpos = stopPoints[i];
836    }
837
838    pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
839    if (!pGradient->gradient.stops) {
840        *error = BadAlloc;
841        return;
842    }
843
844    pGradient->gradient.nstops = stopCount;
845
846    for (i = 0; i < stopCount; ++i) {
847        pGradient->gradient.stops[i].x = stopPoints[i];
848        pGradient->gradient.stops[i].color = stopColors[i];
849    }
850
851    pGradient->gradient.class	       = SourcePictClassUnknown;
852    pGradient->gradient.stopRange      = 0xffff;
853    pGradient->gradient.colorTable     = NULL;
854    pGradient->gradient.colorTableSize = 0;
855}
856
857static PicturePtr createSourcePicture(void)
858{
859    PicturePtr pPicture;
860    pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
861    pPicture->pDrawable = 0;
862    pPicture->pFormat = 0;
863    pPicture->pNext = 0;
864    pPicture->format = PICT_a8r8g8b8;
865    pPicture->devPrivates = 0;
866
867    SetPictureToDefaults(pPicture);
868    return pPicture;
869}
870
871PicturePtr
872CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
873{
874    PicturePtr pPicture;
875    pPicture = createSourcePicture();
876    if (!pPicture) {
877        *error = BadAlloc;
878        return 0;
879    }
880
881    pPicture->id = pid;
882    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill));
883    if (!pPicture->pSourcePict) {
884        *error = BadAlloc;
885        xfree(pPicture);
886        return 0;
887    }
888    pPicture->pSourcePict->type = SourcePictTypeSolidFill;
889    pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
890    return pPicture;
891}
892
893PicturePtr
894CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
895                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
896{
897    PicturePtr pPicture;
898
899    if (nStops < 2) {
900        *error = BadValue;
901        return 0;
902    }
903
904    pPicture = createSourcePicture();
905    if (!pPicture) {
906        *error = BadAlloc;
907        return 0;
908    }
909
910    pPicture->id = pid;
911    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
912    if (!pPicture->pSourcePict) {
913        *error = BadAlloc;
914        xfree(pPicture);
915        return 0;
916    }
917
918    pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
919    pPicture->pSourcePict->linear.p1 = *p1;
920    pPicture->pSourcePict->linear.p2 = *p2;
921
922    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
923    if (*error) {
924        xfree(pPicture);
925        return 0;
926    }
927    return pPicture;
928}
929
930#define FixedToDouble(x) ((x)/65536.)
931
932PicturePtr
933CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
934                             xFixed innerRadius, xFixed outerRadius,
935                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
936{
937    PicturePtr pPicture;
938    PictRadialGradient *radial;
939
940    if (nStops < 2) {
941        *error = BadValue;
942        return 0;
943    }
944
945    pPicture = createSourcePicture();
946    if (!pPicture) {
947        *error = BadAlloc;
948        return 0;
949    }
950
951    pPicture->id = pid;
952    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
953    if (!pPicture->pSourcePict) {
954        *error = BadAlloc;
955        xfree(pPicture);
956        return 0;
957    }
958    radial = &pPicture->pSourcePict->radial;
959
960    radial->type = SourcePictTypeRadial;
961    radial->c1.x = inner->x;
962    radial->c1.y = inner->y;
963    radial->c1.radius = innerRadius;
964    radial->c2.x = outer->x;
965    radial->c2.y = outer->y;
966    radial->c2.radius = outerRadius;
967    radial->cdx = (radial->c2.x - radial->c1.x) / 65536.;
968    radial->cdy = (radial->c2.y - radial->c1.y) / 65536.;
969    radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.;
970    radial->A = (  radial->cdx * radial->cdx
971		   + radial->cdy * radial->cdy
972		   - radial->dr  * radial->dr);
973
974    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
975    if (*error) {
976        xfree(pPicture);
977        return 0;
978    }
979    return pPicture;
980}
981
982PicturePtr
983CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
984                              int nStops, xFixed *stops, xRenderColor *colors, int *error)
985{
986    PicturePtr pPicture;
987
988    if (nStops < 2) {
989        *error = BadValue;
990        return 0;
991    }
992
993    pPicture = createSourcePicture();
994    if (!pPicture) {
995        *error = BadAlloc;
996        return 0;
997    }
998
999    pPicture->id = pid;
1000    pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient));
1001    if (!pPicture->pSourcePict) {
1002        *error = BadAlloc;
1003        xfree(pPicture);
1004        return 0;
1005    }
1006
1007    pPicture->pSourcePict->conical.type = SourcePictTypeConical;
1008    pPicture->pSourcePict->conical.center = *center;
1009    pPicture->pSourcePict->conical.angle = angle;
1010
1011    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
1012    if (*error) {
1013        xfree(pPicture);
1014        return 0;
1015    }
1016    return pPicture;
1017}
1018
1019#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
1020
1021#define NEXT_PTR(_type) ((_type) ulist++->ptr)
1022
1023int
1024ChangePicture (PicturePtr	pPicture,
1025	       Mask		vmask,
1026	       XID		*vlist,
1027	       DevUnion		*ulist,
1028	       ClientPtr	client)
1029{
1030    ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
1031    PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
1032    BITS32		index2;
1033    int			error = 0;
1034    BITS32		maskQ;
1035
1036    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1037    maskQ = vmask;
1038    while (vmask && !error)
1039    {
1040	index2 = (BITS32) lowbit (vmask);
1041	vmask &= ~index2;
1042	pPicture->stateChanges |= index2;
1043	switch (index2)
1044	{
1045	case CPRepeat:
1046	    {
1047		unsigned int	newr;
1048		newr = NEXT_VAL(unsigned int);
1049		if (newr <= RepeatReflect)
1050		{
1051		    pPicture->repeat = (newr != RepeatNone);
1052		    pPicture->repeatType = newr;
1053		}
1054		else
1055		{
1056		    client->errorValue = newr;
1057		    error = BadValue;
1058		}
1059	    }
1060	    break;
1061	case CPAlphaMap:
1062	    {
1063		PicturePtr  pAlpha;
1064
1065		if (vlist)
1066		{
1067		    Picture	pid = NEXT_VAL(Picture);
1068
1069		    if (pid == None)
1070			pAlpha = 0;
1071		    else
1072		    {
1073			error = dixLookupResource((pointer *)&pAlpha, pid,
1074						  PictureType, client,
1075						  DixReadAccess);
1076			if (error != Success)
1077			{
1078			    client->errorValue = pid;
1079			    error = (error == BadValue) ? BadPixmap : error;
1080			    break;
1081			}
1082			if (pAlpha->pDrawable == NULL ||
1083			    pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
1084			{
1085			    client->errorValue = pid;
1086			    error = BadMatch;
1087			    break;
1088			}
1089		    }
1090		}
1091		else
1092		    pAlpha = NEXT_PTR(PicturePtr);
1093		if (!error)
1094		{
1095		    if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
1096			pAlpha->refcnt++;
1097		    if (pPicture->alphaMap)
1098			FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1099		    pPicture->alphaMap = pAlpha;
1100		}
1101	    }
1102	    break;
1103	case CPAlphaXOrigin:
1104	    pPicture->alphaOrigin.x = NEXT_VAL(INT16);
1105	    break;
1106	case CPAlphaYOrigin:
1107	    pPicture->alphaOrigin.y = NEXT_VAL(INT16);
1108	    break;
1109	case CPClipXOrigin:
1110	    pPicture->clipOrigin.x = NEXT_VAL(INT16);
1111	    break;
1112	case CPClipYOrigin:
1113	    pPicture->clipOrigin.y = NEXT_VAL(INT16);
1114	    break;
1115	case CPClipMask:
1116	    {
1117		Pixmap	    pid;
1118		PixmapPtr   pPixmap;
1119		int	    clipType;
1120                if (!pScreen)
1121                    return BadDrawable;
1122
1123		if (vlist)
1124		{
1125		    pid = NEXT_VAL(Pixmap);
1126		    if (pid == None)
1127		    {
1128			clipType = CT_NONE;
1129			pPixmap = NullPixmap;
1130		    }
1131		    else
1132		    {
1133			clipType = CT_PIXMAP;
1134			error = dixLookupResource((pointer *)&pPixmap, pid,
1135						  RT_PIXMAP, client,
1136						  DixReadAccess);
1137			if (error != Success)
1138			{
1139			    client->errorValue = pid;
1140			    error = (error == BadValue) ? BadPixmap : error;
1141			    break;
1142			}
1143		    }
1144		}
1145		else
1146		{
1147		    pPixmap = NEXT_PTR(PixmapPtr);
1148		    if (pPixmap)
1149			clipType = CT_PIXMAP;
1150		    else
1151			clipType = CT_NONE;
1152		}
1153
1154		if (pPixmap)
1155		{
1156		    if ((pPixmap->drawable.depth != 1) ||
1157			(pPixmap->drawable.pScreen != pScreen))
1158		    {
1159			error = BadMatch;
1160			break;
1161		    }
1162		    else
1163		    {
1164			clipType = CT_PIXMAP;
1165			pPixmap->refcnt++;
1166		    }
1167		}
1168		error = (*ps->ChangePictureClip)(pPicture, clipType,
1169						 (pointer)pPixmap, 0);
1170		break;
1171	    }
1172	case CPGraphicsExposure:
1173	    {
1174		unsigned int	newe;
1175		newe = NEXT_VAL(unsigned int);
1176		if (newe <= xTrue)
1177		    pPicture->graphicsExposures = newe;
1178		else
1179		{
1180		    client->errorValue = newe;
1181		    error = BadValue;
1182		}
1183	    }
1184	    break;
1185	case CPSubwindowMode:
1186	    {
1187		unsigned int	news;
1188		news = NEXT_VAL(unsigned int);
1189		if (news == ClipByChildren || news == IncludeInferiors)
1190		    pPicture->subWindowMode = news;
1191		else
1192		{
1193		    client->errorValue = news;
1194		    error = BadValue;
1195		}
1196	    }
1197	    break;
1198	case CPPolyEdge:
1199	    {
1200		unsigned int	newe;
1201		newe = NEXT_VAL(unsigned int);
1202		if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
1203		    pPicture->polyEdge = newe;
1204		else
1205		{
1206		    client->errorValue = newe;
1207		    error = BadValue;
1208		}
1209	    }
1210	    break;
1211	case CPPolyMode:
1212	    {
1213		unsigned int	newm;
1214		newm = NEXT_VAL(unsigned int);
1215		if (newm == PolyModePrecise || newm == PolyModeImprecise)
1216		    pPicture->polyMode = newm;
1217		else
1218		{
1219		    client->errorValue = newm;
1220		    error = BadValue;
1221		}
1222	    }
1223	    break;
1224	case CPDither:
1225	    pPicture->dither = NEXT_VAL(Atom);
1226	    break;
1227	case CPComponentAlpha:
1228	    {
1229		unsigned int	newca;
1230
1231		newca = NEXT_VAL (unsigned int);
1232		if (newca <= xTrue)
1233		    pPicture->componentAlpha = newca;
1234		else
1235		{
1236		    client->errorValue = newca;
1237		    error = BadValue;
1238		}
1239	    }
1240	    break;
1241	default:
1242	    client->errorValue = maskQ;
1243	    error = BadValue;
1244	    break;
1245	}
1246    }
1247    if (ps)
1248        (*ps->ChangePicture) (pPicture, maskQ);
1249    return error;
1250}
1251
1252int
1253SetPictureClipRects (PicturePtr	pPicture,
1254		     int	xOrigin,
1255		     int	yOrigin,
1256		     int	nRect,
1257		     xRectangle	*rects)
1258{
1259    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
1260    PictureScreenPtr	ps = GetPictureScreen(pScreen);
1261    RegionPtr		clientClip;
1262    int			result;
1263
1264    clientClip = RECTS_TO_REGION(pScreen,
1265				 nRect, rects, CT_UNSORTED);
1266    if (!clientClip)
1267	return BadAlloc;
1268    result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
1269				      (pointer) clientClip, 0);
1270    if (result == Success)
1271    {
1272	pPicture->clipOrigin.x = xOrigin;
1273	pPicture->clipOrigin.y = yOrigin;
1274	pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1275	pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1276    }
1277    return result;
1278}
1279
1280int
1281SetPictureClipRegion (PicturePtr    pPicture,
1282                      int           xOrigin,
1283                      int           yOrigin,
1284                      RegionPtr     pRegion)
1285{
1286    ScreenPtr           pScreen = pPicture->pDrawable->pScreen;
1287    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1288    RegionPtr           clientClip;
1289    int                 result;
1290    int                 type;
1291
1292    if (pRegion)
1293    {
1294        type = CT_REGION;
1295        clientClip = REGION_CREATE (pScreen,
1296                                    REGION_EXTENTS(pScreen, pRegion),
1297                                    REGION_NUM_RECTS(pRegion));
1298        if (!clientClip)
1299            return BadAlloc;
1300        if (!REGION_COPY (pSCreen, clientClip, pRegion))
1301        {
1302            REGION_DESTROY (pScreen, clientClip);
1303            return BadAlloc;
1304        }
1305    }
1306    else
1307    {
1308        type = CT_NONE;
1309        clientClip = 0;
1310    }
1311
1312    result =(*ps->ChangePictureClip) (pPicture, type,
1313                                      (pointer) clientClip, 0);
1314    if (result == Success)
1315    {
1316        pPicture->clipOrigin.x = xOrigin;
1317        pPicture->clipOrigin.y = yOrigin;
1318        pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1319        pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1320    }
1321    return result;
1322}
1323
1324static Bool
1325transformIsIdentity(PictTransform *t)
1326{
1327    return ((t->matrix[0][0] == t->matrix[1][1]) &&
1328            (t->matrix[0][0] == t->matrix[2][2]) &&
1329            (t->matrix[0][0] != 0) &&
1330            (t->matrix[0][1] == 0) &&
1331            (t->matrix[0][2] == 0) &&
1332            (t->matrix[1][0] == 0) &&
1333            (t->matrix[1][2] == 0) &&
1334            (t->matrix[2][0] == 0) &&
1335            (t->matrix[2][1] == 0));
1336}
1337
1338int
1339SetPictureTransform (PicturePtr	    pPicture,
1340		     PictTransform  *transform)
1341{
1342    if (transform && transformIsIdentity (transform))
1343	transform = 0;
1344
1345    if (transform)
1346    {
1347	if (!pPicture->transform)
1348	{
1349	    pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform));
1350	    if (!pPicture->transform)
1351		return BadAlloc;
1352	}
1353	*pPicture->transform = *transform;
1354    }
1355    else
1356    {
1357	if (pPicture->transform)
1358	{
1359	    xfree (pPicture->transform);
1360	    pPicture->transform = 0;
1361	}
1362    }
1363    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1364
1365    if (pPicture->pDrawable != NULL) {
1366	int result;
1367	PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1368
1369	result = (*ps->ChangePictureTransform) (pPicture, transform);
1370
1371	return result;
1372    }
1373
1374    return Success;
1375}
1376
1377void
1378CopyPicture (PicturePtr	pSrc,
1379	     Mask	mask,
1380	     PicturePtr	pDst)
1381{
1382    PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
1383    Mask origMask = mask;
1384
1385    pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
1386    pDst->stateChanges |= mask;
1387
1388    while (mask) {
1389	Mask bit = lowbit(mask);
1390
1391	switch (bit)
1392	{
1393	case CPRepeat:
1394	    pDst->repeat = pSrc->repeat;
1395	    pDst->repeatType = pSrc->repeatType;
1396	    break;
1397	case CPAlphaMap:
1398	    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
1399		pSrc->alphaMap->refcnt++;
1400	    if (pDst->alphaMap)
1401		FreePicture ((pointer) pDst->alphaMap, (XID) 0);
1402	    pDst->alphaMap = pSrc->alphaMap;
1403	    break;
1404	case CPAlphaXOrigin:
1405	    pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
1406	    break;
1407	case CPAlphaYOrigin:
1408	    pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
1409	    break;
1410	case CPClipXOrigin:
1411	    pDst->clipOrigin.x = pSrc->clipOrigin.x;
1412	    break;
1413	case CPClipYOrigin:
1414	    pDst->clipOrigin.y = pSrc->clipOrigin.y;
1415	    break;
1416	case CPClipMask:
1417	    switch (pSrc->clientClipType) {
1418	    case CT_NONE:
1419		(*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1420		break;
1421	    case CT_REGION:
1422		if (!pSrc->clientClip) {
1423		    (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1424		} else {
1425		    RegionPtr clientClip;
1426		    RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
1427
1428		    clientClip = REGION_CREATE(pSrc->pDrawable->pScreen,
1429			REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip),
1430			REGION_NUM_RECTS(srcClientClip));
1431		    (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
1432		}
1433		break;
1434	    default:
1435		/* XXX: CT_PIXMAP unimplemented */
1436		break;
1437	    }
1438	    break;
1439	case CPGraphicsExposure:
1440	    pDst->graphicsExposures = pSrc->graphicsExposures;
1441	    break;
1442	case CPPolyEdge:
1443	    pDst->polyEdge = pSrc->polyEdge;
1444	    break;
1445	case CPPolyMode:
1446	    pDst->polyMode = pSrc->polyMode;
1447	    break;
1448	case CPDither:
1449	    pDst->dither = pSrc->dither;
1450	    break;
1451	case CPComponentAlpha:
1452	    pDst->componentAlpha = pSrc->componentAlpha;
1453	    break;
1454	}
1455	mask &= ~bit;
1456    }
1457
1458    (*ps->ChangePicture)(pDst, origMask);
1459}
1460
1461static void
1462ValidateOnePicture (PicturePtr pPicture)
1463{
1464    if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
1465    {
1466	PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1467
1468	(*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
1469	pPicture->stateChanges = 0;
1470	pPicture->serialNumber = pPicture->pDrawable->serialNumber;
1471    }
1472}
1473
1474void
1475ValidatePicture(PicturePtr pPicture)
1476{
1477    ValidateOnePicture (pPicture);
1478    if (pPicture->alphaMap)
1479	ValidateOnePicture (pPicture->alphaMap);
1480}
1481
1482int
1483FreePicture (pointer	value,
1484	     XID	pid)
1485{
1486    PicturePtr	pPicture = (PicturePtr) value;
1487
1488    if (--pPicture->refcnt == 0)
1489    {
1490	if (pPicture->transform)
1491	    xfree (pPicture->transform);
1492
1493	if (pPicture->pSourcePict)
1494	{
1495	    if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
1496		xfree(pPicture->pSourcePict->linear.stops);
1497
1498	    xfree(pPicture->pSourcePict);
1499	}
1500
1501	if (pPicture->pDrawable)
1502	{
1503            ScreenPtr	    pScreen = pPicture->pDrawable->pScreen;
1504            PictureScreenPtr    ps = GetPictureScreen(pScreen);
1505
1506            if (pPicture->alphaMap)
1507                FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1508            (*ps->DestroyPicture) (pPicture);
1509            (*ps->DestroyPictureClip) (pPicture);
1510            if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
1511            {
1512                WindowPtr	pWindow = (WindowPtr) pPicture->pDrawable;
1513                PicturePtr	*pPrev;
1514
1515                for (pPrev = (PicturePtr *)dixLookupPrivateAddr
1516			 (&pWindow->devPrivates, PictureWindowPrivateKey);
1517                     *pPrev;
1518                     pPrev = &(*pPrev)->pNext)
1519                {
1520                    if (*pPrev == pPicture)
1521                    {
1522                        *pPrev = pPicture->pNext;
1523                        break;
1524                    }
1525                }
1526            }
1527            else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
1528            {
1529                (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
1530            }
1531        }
1532	dixFreePrivates(pPicture->devPrivates);
1533	xfree (pPicture);
1534    }
1535    return Success;
1536}
1537
1538int
1539FreePictFormat (pointer	pPictFormat,
1540		XID     pid)
1541{
1542    return Success;
1543}
1544
1545/**
1546 * ReduceCompositeOp is used to choose simpler ops for cases where alpha
1547 * channels are always one and so math on the alpha channel per pixel becomes
1548 * unnecessary.  It may also avoid destination reads sometimes if apps aren't
1549 * being careful to avoid these cases.
1550 */
1551static CARD8
1552ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1553		   INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
1554{
1555    Bool no_src_alpha, no_dst_alpha;
1556
1557    /* Sampling off the edge of a RepeatNone picture introduces alpha
1558     * even if the picture itself doesn't have alpha. We don't try to
1559     * detect every case where we don't sample off the edge, just the
1560     * simplest case where there is no transform on the source
1561     * picture.
1562     */
1563    no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
1564                   PICT_FORMAT_A(pSrc->format) == 0 &&
1565                   (pSrc->repeatType != RepeatNone ||
1566		    (!pSrc->transform &&
1567		     xSrc >= 0 && ySrc >= 0 &&
1568		     xSrc + width <= pSrc->pDrawable->width &&
1569		     ySrc + height <= pSrc->pDrawable->height)) &&
1570                   pSrc->alphaMap == NULL &&
1571                   pMask == NULL;
1572    no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
1573                   PICT_FORMAT_A(pDst->format) == 0 &&
1574                   pDst->alphaMap == NULL;
1575
1576    /* TODO, maybe: Conjoint and Disjoint op reductions? */
1577
1578    /* Deal with simplifications where the source alpha is always 1. */
1579    if (no_src_alpha)
1580    {
1581	switch (op) {
1582	case PictOpOver:
1583	    op = PictOpSrc;
1584	    break;
1585	case PictOpInReverse:
1586	    op = PictOpDst;
1587	    break;
1588	case PictOpOutReverse:
1589	    op = PictOpClear;
1590	    break;
1591	case PictOpAtop:
1592	    op = PictOpIn;
1593	    break;
1594	case PictOpAtopReverse:
1595	    op = PictOpOverReverse;
1596	    break;
1597	case PictOpXor:
1598	    op = PictOpOut;
1599	    break;
1600	default:
1601	    break;
1602	}
1603    }
1604
1605    /* Deal with simplifications when the destination alpha is always 1 */
1606    if (no_dst_alpha)
1607    {
1608	switch (op) {
1609	case PictOpOverReverse:
1610	    op = PictOpDst;
1611	    break;
1612	case PictOpIn:
1613	    op = PictOpSrc;
1614	    break;
1615	case PictOpOut:
1616	    op = PictOpClear;
1617	    break;
1618	case PictOpAtop:
1619	    op = PictOpOver;
1620	    break;
1621	case PictOpXor:
1622	    op = PictOpOutReverse;
1623	    break;
1624	default:
1625	    break;
1626	}
1627    }
1628
1629    /* Reduce some con/disjoint ops to the basic names. */
1630    switch (op) {
1631    case PictOpDisjointClear:
1632    case PictOpConjointClear:
1633	op = PictOpClear;
1634	break;
1635    case PictOpDisjointSrc:
1636    case PictOpConjointSrc:
1637	op = PictOpSrc;
1638	break;
1639    case PictOpDisjointDst:
1640    case PictOpConjointDst:
1641	op = PictOpDst;
1642	break;
1643    default:
1644	break;
1645    }
1646
1647    return op;
1648}
1649
1650void
1651CompositePicture (CARD8		op,
1652		  PicturePtr	pSrc,
1653		  PicturePtr	pMask,
1654		  PicturePtr	pDst,
1655		  INT16		xSrc,
1656		  INT16		ySrc,
1657		  INT16		xMask,
1658		  INT16		yMask,
1659		  INT16		xDst,
1660		  INT16		yDst,
1661		  CARD16	width,
1662		  CARD16	height)
1663{
1664    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1665
1666    ValidatePicture (pSrc);
1667    if (pMask)
1668	ValidatePicture (pMask);
1669    ValidatePicture (pDst);
1670
1671    op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
1672    if (op == PictOpDst)
1673	return;
1674
1675    (*ps->Composite) (op,
1676		       pSrc,
1677		       pMask,
1678		       pDst,
1679		       xSrc,
1680		       ySrc,
1681		       xMask,
1682		       yMask,
1683		       xDst,
1684		       yDst,
1685		       width,
1686		       height);
1687}
1688
1689void
1690CompositeRects (CARD8		op,
1691		PicturePtr	pDst,
1692		xRenderColor	*color,
1693		int		nRect,
1694		xRectangle      *rects)
1695{
1696    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1697
1698    ValidatePicture (pDst);
1699    (*ps->CompositeRects) (op, pDst, color, nRect, rects);
1700}
1701
1702void
1703CompositeTrapezoids (CARD8	    op,
1704		     PicturePtr	    pSrc,
1705		     PicturePtr	    pDst,
1706		     PictFormatPtr  maskFormat,
1707		     INT16	    xSrc,
1708		     INT16	    ySrc,
1709		     int	    ntrap,
1710		     xTrapezoid	    *traps)
1711{
1712    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1713
1714    ValidatePicture (pSrc);
1715    ValidatePicture (pDst);
1716    (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
1717}
1718
1719void
1720CompositeTriangles (CARD8	    op,
1721		    PicturePtr	    pSrc,
1722		    PicturePtr	    pDst,
1723		    PictFormatPtr   maskFormat,
1724		    INT16	    xSrc,
1725		    INT16	    ySrc,
1726		    int		    ntriangles,
1727		    xTriangle	    *triangles)
1728{
1729    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1730
1731    ValidatePicture (pSrc);
1732    ValidatePicture (pDst);
1733    (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
1734}
1735
1736void
1737CompositeTriStrip (CARD8	    op,
1738		   PicturePtr	    pSrc,
1739		   PicturePtr	    pDst,
1740		   PictFormatPtr    maskFormat,
1741		   INT16	    xSrc,
1742		   INT16	    ySrc,
1743		   int		    npoints,
1744		   xPointFixed	    *points)
1745{
1746    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1747
1748    ValidatePicture (pSrc);
1749    ValidatePicture (pDst);
1750    (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1751}
1752
1753void
1754CompositeTriFan (CARD8		op,
1755		 PicturePtr	pSrc,
1756		 PicturePtr	pDst,
1757		 PictFormatPtr	maskFormat,
1758		 INT16		xSrc,
1759		 INT16		ySrc,
1760		 int		npoints,
1761		 xPointFixed	*points)
1762{
1763    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1764
1765    ValidatePicture (pSrc);
1766    ValidatePicture (pDst);
1767    (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1768}
1769
1770void
1771AddTraps (PicturePtr	pPicture,
1772	  INT16		xOff,
1773	  INT16		yOff,
1774	  int		ntrap,
1775	  xTrap		*traps)
1776{
1777    PictureScreenPtr	ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1778
1779    ValidatePicture (pPicture);
1780    (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
1781}
1782
1783