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