picture.c revision 6747b715
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->dither = None;
739    pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
740    pPicture->filter_params = 0;
741    pPicture->filter_nparams = 0;
742
743    pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
744    pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
745    pPicture->pSourcePict = 0;
746}
747
748PicturePtr
749CreatePicture (Picture		pid,
750	       DrawablePtr	pDrawable,
751	       PictFormatPtr	pFormat,
752	       Mask		vmask,
753	       XID		*vlist,
754	       ClientPtr	client,
755	       int		*error)
756{
757    PicturePtr		pPicture;
758    PictureScreenPtr	ps = GetPictureScreen(pDrawable->pScreen);
759
760    pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE);
761    if (!pPicture)
762    {
763	*error = BadAlloc;
764	return 0;
765    }
766
767    pPicture->id = pid;
768    pPicture->pDrawable = pDrawable;
769    pPicture->pFormat = pFormat;
770    pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
771
772    /* security creation/labeling check */
773    *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
774		      RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
775    if (*error != Success)
776	goto out;
777
778    if (pDrawable->type == DRAWABLE_PIXMAP)
779    {
780	++((PixmapPtr)pDrawable)->refcnt;
781	pPicture->pNext = 0;
782    }
783    else
784    {
785	pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
786	SetPictureWindow(((WindowPtr) pDrawable), pPicture);
787    }
788
789    SetPictureToDefaults (pPicture);
790
791    if (vmask)
792	*error = ChangePicture (pPicture, vmask, vlist, 0, client);
793    else
794	*error = Success;
795    if (*error == Success)
796	*error = (*ps->CreatePicture) (pPicture);
797out:
798    if (*error != Success)
799    {
800	FreePicture (pPicture, (XID) 0);
801	pPicture = 0;
802    }
803    return pPicture;
804}
805
806static CARD32 xRenderColorToCard32(xRenderColor c)
807{
808    return
809        (c.alpha >> 8 << 24) |
810        (c.red >> 8 << 16) |
811        (c.green & 0xff00) |
812        (c.blue >> 8);
813}
814
815static unsigned int premultiply(unsigned int x)
816{
817    unsigned int a = x >> 24;
818    unsigned int t = (x & 0xff00ff) * a + 0x800080;
819    t = (t + ((t >> 8) & 0xff00ff)) >> 8;
820    t &= 0xff00ff;
821
822    x = ((x >> 8) & 0xff) * a + 0x80;
823    x = (x + ((x >> 8) & 0xff));
824    x &= 0xff00;
825    x |= t | (a << 24);
826    return x;
827}
828
829static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
830                                          unsigned int y, unsigned int b)
831{
832    CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
833    t >>= 8;
834    t &= 0xff00ff;
835
836    x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
837    x &= 0xff00ff00;
838    x |= t;
839    return x;
840}
841
842CARD32
843PictureGradientColor (PictGradientStopPtr stop1,
844		      PictGradientStopPtr stop2,
845		      CARD32	          x)
846{
847     CARD32 current_color, next_color;
848     int	   dist, idist;
849
850     current_color = xRenderColorToCard32 (stop1->color);
851     next_color    = xRenderColorToCard32 (stop2->color);
852
853     dist  = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
854     idist = 256 - dist;
855
856     return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
857					       next_color, dist));
858}
859
860static void initGradient(SourcePictPtr pGradient, int stopCount,
861                         xFixed *stopPoints, xRenderColor *stopColors, int *error)
862{
863    int i;
864    xFixed dpos;
865
866    if (stopCount <= 0) {
867        *error = BadValue;
868        return;
869    }
870
871    dpos = -1;
872    for (i = 0; i < stopCount; ++i) {
873        if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
874            *error = BadValue;
875            return;
876        }
877        dpos = stopPoints[i];
878    }
879
880    pGradient->gradient.stops = malloc(stopCount*sizeof(PictGradientStop));
881    if (!pGradient->gradient.stops) {
882        *error = BadAlloc;
883        return;
884    }
885
886    pGradient->gradient.nstops = stopCount;
887
888    for (i = 0; i < stopCount; ++i) {
889        pGradient->gradient.stops[i].x = stopPoints[i];
890        pGradient->gradient.stops[i].color = stopColors[i];
891    }
892
893    pGradient->gradient.class	       = SourcePictClassUnknown;
894    pGradient->gradient.stopRange      = 0xffff;
895    pGradient->gradient.colorTable     = NULL;
896    pGradient->gradient.colorTableSize = 0;
897}
898
899static PicturePtr createSourcePicture(void)
900{
901    PicturePtr pPicture;
902    pPicture = dixAllocateObjectWithPrivates(PictureRec, PRIVATE_PICTURE);
903    pPicture->pDrawable = 0;
904    pPicture->pFormat = 0;
905    pPicture->pNext = 0;
906    pPicture->format = PICT_a8r8g8b8;
907
908    SetPictureToDefaults(pPicture);
909    return pPicture;
910}
911
912PicturePtr
913CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
914{
915    PicturePtr pPicture;
916    pPicture = createSourcePicture();
917    if (!pPicture) {
918        *error = BadAlloc;
919        return 0;
920    }
921
922    pPicture->id = pid;
923    pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictSolidFill));
924    if (!pPicture->pSourcePict) {
925        *error = BadAlloc;
926        free(pPicture);
927        return 0;
928    }
929    pPicture->pSourcePict->type = SourcePictTypeSolidFill;
930    pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
931    return pPicture;
932}
933
934PicturePtr
935CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
936                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
937{
938    PicturePtr pPicture;
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) malloc(sizeof(PictLinearGradient));
953    if (!pPicture->pSourcePict) {
954        *error = BadAlloc;
955        free(pPicture);
956        return 0;
957    }
958
959    pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
960    pPicture->pSourcePict->linear.p1 = *p1;
961    pPicture->pSourcePict->linear.p2 = *p2;
962
963    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
964    if (*error) {
965        free(pPicture);
966        return 0;
967    }
968    return pPicture;
969}
970
971#define FixedToDouble(x) ((x)/65536.)
972
973PicturePtr
974CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
975                             xFixed innerRadius, xFixed outerRadius,
976                             int nStops, xFixed *stops, xRenderColor *colors, int *error)
977{
978    PicturePtr pPicture;
979    PictRadialGradient *radial;
980
981    if (nStops < 2) {
982        *error = BadValue;
983        return 0;
984    }
985
986    pPicture = createSourcePicture();
987    if (!pPicture) {
988        *error = BadAlloc;
989        return 0;
990    }
991
992    pPicture->id = pid;
993    pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictRadialGradient));
994    if (!pPicture->pSourcePict) {
995        *error = BadAlloc;
996        free(pPicture);
997        return 0;
998    }
999    radial = &pPicture->pSourcePict->radial;
1000
1001    radial->type = SourcePictTypeRadial;
1002    radial->c1.x = inner->x;
1003    radial->c1.y = inner->y;
1004    radial->c1.radius = innerRadius;
1005    radial->c2.x = outer->x;
1006    radial->c2.y = outer->y;
1007    radial->c2.radius = outerRadius;
1008    radial->cdx = (radial->c2.x - radial->c1.x) / 65536.;
1009    radial->cdy = (radial->c2.y - radial->c1.y) / 65536.;
1010    radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.;
1011    radial->A = (  radial->cdx * radial->cdx
1012		   + radial->cdy * radial->cdy
1013		   - radial->dr  * radial->dr);
1014
1015    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
1016    if (*error) {
1017        free(pPicture);
1018        return 0;
1019    }
1020    return pPicture;
1021}
1022
1023PicturePtr
1024CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
1025                              int nStops, xFixed *stops, xRenderColor *colors, int *error)
1026{
1027    PicturePtr pPicture;
1028
1029    if (nStops < 2) {
1030        *error = BadValue;
1031        return 0;
1032    }
1033
1034    pPicture = createSourcePicture();
1035    if (!pPicture) {
1036        *error = BadAlloc;
1037        return 0;
1038    }
1039
1040    pPicture->id = pid;
1041    pPicture->pSourcePict = (SourcePictPtr) malloc(sizeof(PictConicalGradient));
1042    if (!pPicture->pSourcePict) {
1043        *error = BadAlloc;
1044        free(pPicture);
1045        return 0;
1046    }
1047
1048    pPicture->pSourcePict->conical.type = SourcePictTypeConical;
1049    pPicture->pSourcePict->conical.center = *center;
1050    pPicture->pSourcePict->conical.angle = angle;
1051
1052    initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
1053    if (*error) {
1054        free(pPicture);
1055        return 0;
1056    }
1057    return pPicture;
1058}
1059
1060#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
1061
1062#define NEXT_PTR(_type) ((_type) ulist++->ptr)
1063
1064int
1065ChangePicture (PicturePtr	pPicture,
1066	       Mask		vmask,
1067	       XID		*vlist,
1068	       DevUnion		*ulist,
1069	       ClientPtr	client)
1070{
1071    ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
1072    PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
1073    BITS32		index2;
1074    int			error = 0;
1075    BITS32		maskQ;
1076
1077    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1078    maskQ = vmask;
1079    while (vmask && !error)
1080    {
1081	index2 = (BITS32) lowbit (vmask);
1082	vmask &= ~index2;
1083	pPicture->stateChanges |= index2;
1084	switch (index2)
1085	{
1086	case CPRepeat:
1087	    {
1088		unsigned int	newr;
1089		newr = NEXT_VAL(unsigned int);
1090		if (newr <= RepeatReflect)
1091		{
1092		    pPicture->repeat = (newr != RepeatNone);
1093		    pPicture->repeatType = newr;
1094		}
1095		else
1096		{
1097		    client->errorValue = newr;
1098		    error = BadValue;
1099		}
1100	    }
1101	    break;
1102	case CPAlphaMap:
1103	    {
1104		PicturePtr  pAlpha;
1105
1106		if (vlist)
1107		{
1108		    Picture	pid = NEXT_VAL(Picture);
1109
1110		    if (pid == None)
1111			pAlpha = 0;
1112		    else
1113		    {
1114			error = dixLookupResourceByType((pointer *)&pAlpha, pid,
1115						  PictureType, client,
1116						  DixReadAccess);
1117			if (error != Success)
1118			{
1119			    client->errorValue = pid;
1120			    break;
1121			}
1122			if (pAlpha->pDrawable == NULL ||
1123			    pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
1124			{
1125			    client->errorValue = pid;
1126			    error = BadMatch;
1127			    break;
1128			}
1129		    }
1130		}
1131		else
1132		    pAlpha = NEXT_PTR(PicturePtr);
1133		if (!error)
1134		{
1135		    if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
1136			pAlpha->refcnt++;
1137		    if (pPicture->alphaMap)
1138			FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1139		    pPicture->alphaMap = pAlpha;
1140		}
1141	    }
1142	    break;
1143	case CPAlphaXOrigin:
1144	    pPicture->alphaOrigin.x = NEXT_VAL(INT16);
1145	    break;
1146	case CPAlphaYOrigin:
1147	    pPicture->alphaOrigin.y = NEXT_VAL(INT16);
1148	    break;
1149	case CPClipXOrigin:
1150	    pPicture->clipOrigin.x = NEXT_VAL(INT16);
1151	    break;
1152	case CPClipYOrigin:
1153	    pPicture->clipOrigin.y = NEXT_VAL(INT16);
1154	    break;
1155	case CPClipMask:
1156	    {
1157		Pixmap	    pid;
1158		PixmapPtr   pPixmap;
1159		int	    clipType;
1160                if (!pScreen)
1161                    return BadDrawable;
1162
1163		if (vlist)
1164		{
1165		    pid = NEXT_VAL(Pixmap);
1166		    if (pid == None)
1167		    {
1168			clipType = CT_NONE;
1169			pPixmap = NullPixmap;
1170		    }
1171		    else
1172		    {
1173			clipType = CT_PIXMAP;
1174			error = dixLookupResourceByType((pointer *)&pPixmap, pid,
1175						  RT_PIXMAP, client,
1176						  DixReadAccess);
1177			if (error != Success)
1178			{
1179			    client->errorValue = pid;
1180			    break;
1181			}
1182		    }
1183		}
1184		else
1185		{
1186		    pPixmap = NEXT_PTR(PixmapPtr);
1187		    if (pPixmap)
1188			clipType = CT_PIXMAP;
1189		    else
1190			clipType = CT_NONE;
1191		}
1192
1193		if (pPixmap)
1194		{
1195		    if ((pPixmap->drawable.depth != 1) ||
1196			(pPixmap->drawable.pScreen != pScreen))
1197		    {
1198			error = BadMatch;
1199			break;
1200		    }
1201		    else
1202		    {
1203			clipType = CT_PIXMAP;
1204			pPixmap->refcnt++;
1205		    }
1206		}
1207		error = (*ps->ChangePictureClip)(pPicture, clipType,
1208						 (pointer)pPixmap, 0);
1209		break;
1210	    }
1211	case CPGraphicsExposure:
1212	    {
1213		unsigned int	newe;
1214		newe = NEXT_VAL(unsigned int);
1215		if (newe <= xTrue)
1216		    pPicture->graphicsExposures = newe;
1217		else
1218		{
1219		    client->errorValue = newe;
1220		    error = BadValue;
1221		}
1222	    }
1223	    break;
1224	case CPSubwindowMode:
1225	    {
1226		unsigned int	news;
1227		news = NEXT_VAL(unsigned int);
1228		if (news == ClipByChildren || news == IncludeInferiors)
1229		    pPicture->subWindowMode = news;
1230		else
1231		{
1232		    client->errorValue = news;
1233		    error = BadValue;
1234		}
1235	    }
1236	    break;
1237	case CPPolyEdge:
1238	    {
1239		unsigned int	newe;
1240		newe = NEXT_VAL(unsigned int);
1241		if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
1242		    pPicture->polyEdge = newe;
1243		else
1244		{
1245		    client->errorValue = newe;
1246		    error = BadValue;
1247		}
1248	    }
1249	    break;
1250	case CPPolyMode:
1251	    {
1252		unsigned int	newm;
1253		newm = NEXT_VAL(unsigned int);
1254		if (newm == PolyModePrecise || newm == PolyModeImprecise)
1255		    pPicture->polyMode = newm;
1256		else
1257		{
1258		    client->errorValue = newm;
1259		    error = BadValue;
1260		}
1261	    }
1262	    break;
1263	case CPDither:
1264	    pPicture->dither = NEXT_VAL(Atom);
1265	    break;
1266	case CPComponentAlpha:
1267	    {
1268		unsigned int	newca;
1269
1270		newca = NEXT_VAL (unsigned int);
1271		if (newca <= xTrue)
1272		    pPicture->componentAlpha = newca;
1273		else
1274		{
1275		    client->errorValue = newca;
1276		    error = BadValue;
1277		}
1278	    }
1279	    break;
1280	default:
1281	    client->errorValue = maskQ;
1282	    error = BadValue;
1283	    break;
1284	}
1285    }
1286    if (ps)
1287        (*ps->ChangePicture) (pPicture, maskQ);
1288    return error;
1289}
1290
1291int
1292SetPictureClipRects (PicturePtr	pPicture,
1293		     int	xOrigin,
1294		     int	yOrigin,
1295		     int	nRect,
1296		     xRectangle	*rects)
1297{
1298    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
1299    PictureScreenPtr	ps = GetPictureScreen(pScreen);
1300    RegionPtr		clientClip;
1301    int			result;
1302
1303    clientClip = RegionFromRects(nRect, rects, CT_UNSORTED);
1304    if (!clientClip)
1305	return BadAlloc;
1306    result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
1307				      (pointer) clientClip, 0);
1308    if (result == Success)
1309    {
1310	pPicture->clipOrigin.x = xOrigin;
1311	pPicture->clipOrigin.y = yOrigin;
1312	pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1313	pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1314    }
1315    return result;
1316}
1317
1318int
1319SetPictureClipRegion (PicturePtr    pPicture,
1320                      int           xOrigin,
1321                      int           yOrigin,
1322                      RegionPtr     pRegion)
1323{
1324    ScreenPtr           pScreen = pPicture->pDrawable->pScreen;
1325    PictureScreenPtr    ps = GetPictureScreen(pScreen);
1326    RegionPtr           clientClip;
1327    int                 result;
1328    int                 type;
1329
1330    if (pRegion)
1331    {
1332        type = CT_REGION;
1333        clientClip = RegionCreate(RegionExtents(pRegion),
1334                                  RegionNumRects(pRegion));
1335        if (!clientClip)
1336            return BadAlloc;
1337        if (!RegionCopy(clientClip, pRegion))
1338        {
1339            RegionDestroy(clientClip);
1340            return BadAlloc;
1341        }
1342    }
1343    else
1344    {
1345        type = CT_NONE;
1346        clientClip = 0;
1347    }
1348
1349    result =(*ps->ChangePictureClip) (pPicture, type,
1350                                      (pointer) clientClip, 0);
1351    if (result == Success)
1352    {
1353        pPicture->clipOrigin.x = xOrigin;
1354        pPicture->clipOrigin.y = yOrigin;
1355        pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
1356        pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1357    }
1358    return result;
1359}
1360
1361static Bool
1362transformIsIdentity(PictTransform *t)
1363{
1364    return ((t->matrix[0][0] == t->matrix[1][1]) &&
1365            (t->matrix[0][0] == t->matrix[2][2]) &&
1366            (t->matrix[0][0] != 0) &&
1367            (t->matrix[0][1] == 0) &&
1368            (t->matrix[0][2] == 0) &&
1369            (t->matrix[1][0] == 0) &&
1370            (t->matrix[1][2] == 0) &&
1371            (t->matrix[2][0] == 0) &&
1372            (t->matrix[2][1] == 0));
1373}
1374
1375int
1376SetPictureTransform (PicturePtr	    pPicture,
1377		     PictTransform  *transform)
1378{
1379    if (transform && transformIsIdentity (transform))
1380	transform = 0;
1381
1382    if (transform)
1383    {
1384	if (!pPicture->transform)
1385	{
1386	    pPicture->transform = (PictTransform *) malloc(sizeof (PictTransform));
1387	    if (!pPicture->transform)
1388		return BadAlloc;
1389	}
1390	*pPicture->transform = *transform;
1391    }
1392    else
1393    {
1394	if (pPicture->transform)
1395	{
1396	    free(pPicture->transform);
1397	    pPicture->transform = 0;
1398	}
1399    }
1400    pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
1401
1402    if (pPicture->pDrawable != NULL) {
1403	int result;
1404	PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1405
1406	result = (*ps->ChangePictureTransform) (pPicture, transform);
1407
1408	return result;
1409    }
1410
1411    return Success;
1412}
1413
1414void
1415CopyPicture (PicturePtr	pSrc,
1416	     Mask	mask,
1417	     PicturePtr	pDst)
1418{
1419    PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
1420    Mask origMask = mask;
1421
1422    pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
1423    pDst->stateChanges |= mask;
1424
1425    while (mask) {
1426	Mask bit = lowbit(mask);
1427
1428	switch (bit)
1429	{
1430	case CPRepeat:
1431	    pDst->repeat = pSrc->repeat;
1432	    pDst->repeatType = pSrc->repeatType;
1433	    break;
1434	case CPAlphaMap:
1435	    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
1436		pSrc->alphaMap->refcnt++;
1437	    if (pDst->alphaMap)
1438		FreePicture ((pointer) pDst->alphaMap, (XID) 0);
1439	    pDst->alphaMap = pSrc->alphaMap;
1440	    break;
1441	case CPAlphaXOrigin:
1442	    pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
1443	    break;
1444	case CPAlphaYOrigin:
1445	    pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
1446	    break;
1447	case CPClipXOrigin:
1448	    pDst->clipOrigin.x = pSrc->clipOrigin.x;
1449	    break;
1450	case CPClipYOrigin:
1451	    pDst->clipOrigin.y = pSrc->clipOrigin.y;
1452	    break;
1453	case CPClipMask:
1454	    switch (pSrc->clientClipType) {
1455	    case CT_NONE:
1456		(*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1457		break;
1458	    case CT_REGION:
1459		if (!pSrc->clientClip) {
1460		    (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
1461		} else {
1462		    RegionPtr clientClip;
1463		    RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
1464
1465		    clientClip = RegionCreate(
1466			RegionExtents(srcClientClip),
1467			RegionNumRects(srcClientClip));
1468		    (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
1469		}
1470		break;
1471	    default:
1472		/* XXX: CT_PIXMAP unimplemented */
1473		break;
1474	    }
1475	    break;
1476	case CPGraphicsExposure:
1477	    pDst->graphicsExposures = pSrc->graphicsExposures;
1478	    break;
1479	case CPPolyEdge:
1480	    pDst->polyEdge = pSrc->polyEdge;
1481	    break;
1482	case CPPolyMode:
1483	    pDst->polyMode = pSrc->polyMode;
1484	    break;
1485	case CPDither:
1486	    pDst->dither = pSrc->dither;
1487	    break;
1488	case CPComponentAlpha:
1489	    pDst->componentAlpha = pSrc->componentAlpha;
1490	    break;
1491	}
1492	mask &= ~bit;
1493    }
1494
1495    (*ps->ChangePicture)(pDst, origMask);
1496}
1497
1498static void
1499ValidateOnePicture (PicturePtr pPicture)
1500{
1501    if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
1502    {
1503	PictureScreenPtr    ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1504
1505	(*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
1506	pPicture->stateChanges = 0;
1507	pPicture->serialNumber = pPicture->pDrawable->serialNumber;
1508    }
1509}
1510
1511void
1512ValidatePicture(PicturePtr pPicture)
1513{
1514    ValidateOnePicture (pPicture);
1515    if (pPicture->alphaMap)
1516	ValidateOnePicture (pPicture->alphaMap);
1517}
1518
1519int
1520FreePicture (pointer	value,
1521	     XID	pid)
1522{
1523    PicturePtr	pPicture = (PicturePtr) value;
1524
1525    if (--pPicture->refcnt == 0)
1526    {
1527	free(pPicture->transform);
1528
1529	if (pPicture->pSourcePict)
1530	{
1531	    if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
1532		free(pPicture->pSourcePict->linear.stops);
1533
1534	    free(pPicture->pSourcePict);
1535	}
1536
1537	if (pPicture->pDrawable)
1538	{
1539            ScreenPtr	    pScreen = pPicture->pDrawable->pScreen;
1540            PictureScreenPtr    ps = GetPictureScreen(pScreen);
1541
1542            if (pPicture->alphaMap)
1543                FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
1544            (*ps->DestroyPicture) (pPicture);
1545            (*ps->DestroyPictureClip) (pPicture);
1546            if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
1547            {
1548                WindowPtr	pWindow = (WindowPtr) pPicture->pDrawable;
1549                PicturePtr	*pPrev;
1550
1551                for (pPrev = (PicturePtr *)dixLookupPrivateAddr
1552			 (&pWindow->devPrivates, PictureWindowPrivateKey);
1553                     *pPrev;
1554                     pPrev = &(*pPrev)->pNext)
1555                {
1556                    if (*pPrev == pPicture)
1557                    {
1558                        *pPrev = pPicture->pNext;
1559                        break;
1560                    }
1561                }
1562            }
1563            else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
1564            {
1565                (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
1566            }
1567        }
1568	dixFreeObjectWithPrivates(pPicture, PRIVATE_PICTURE);
1569    }
1570    return Success;
1571}
1572
1573int
1574FreePictFormat (pointer	pPictFormat,
1575		XID     pid)
1576{
1577    return Success;
1578}
1579
1580/**
1581 * ReduceCompositeOp is used to choose simpler ops for cases where alpha
1582 * channels are always one and so math on the alpha channel per pixel becomes
1583 * unnecessary.  It may also avoid destination reads sometimes if apps aren't
1584 * being careful to avoid these cases.
1585 */
1586static CARD8
1587ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1588		   INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
1589{
1590    Bool no_src_alpha, no_dst_alpha;
1591
1592    /* Sampling off the edge of a RepeatNone picture introduces alpha
1593     * even if the picture itself doesn't have alpha. We don't try to
1594     * detect every case where we don't sample off the edge, just the
1595     * simplest case where there is no transform on the source
1596     * picture.
1597     */
1598    no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
1599                   PICT_FORMAT_A(pSrc->format) == 0 &&
1600                   (pSrc->repeatType != RepeatNone ||
1601		    (!pSrc->transform &&
1602		     xSrc >= 0 && ySrc >= 0 &&
1603		     xSrc + width <= pSrc->pDrawable->width &&
1604		     ySrc + height <= pSrc->pDrawable->height)) &&
1605                   pSrc->alphaMap == NULL &&
1606                   pMask == NULL;
1607    no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
1608                   PICT_FORMAT_A(pDst->format) == 0 &&
1609                   pDst->alphaMap == NULL;
1610
1611    /* TODO, maybe: Conjoint and Disjoint op reductions? */
1612
1613    /* Deal with simplifications where the source alpha is always 1. */
1614    if (no_src_alpha)
1615    {
1616	switch (op) {
1617	case PictOpOver:
1618	    op = PictOpSrc;
1619	    break;
1620	case PictOpInReverse:
1621	    op = PictOpDst;
1622	    break;
1623	case PictOpOutReverse:
1624	    op = PictOpClear;
1625	    break;
1626	case PictOpAtop:
1627	    op = PictOpIn;
1628	    break;
1629	case PictOpAtopReverse:
1630	    op = PictOpOverReverse;
1631	    break;
1632	case PictOpXor:
1633	    op = PictOpOut;
1634	    break;
1635	default:
1636	    break;
1637	}
1638    }
1639
1640    /* Deal with simplifications when the destination alpha is always 1 */
1641    if (no_dst_alpha)
1642    {
1643	switch (op) {
1644	case PictOpOverReverse:
1645	    op = PictOpDst;
1646	    break;
1647	case PictOpIn:
1648	    op = PictOpSrc;
1649	    break;
1650	case PictOpOut:
1651	    op = PictOpClear;
1652	    break;
1653	case PictOpAtop:
1654	    op = PictOpOver;
1655	    break;
1656	case PictOpXor:
1657	    op = PictOpOutReverse;
1658	    break;
1659	default:
1660	    break;
1661	}
1662    }
1663
1664    /* Reduce some con/disjoint ops to the basic names. */
1665    switch (op) {
1666    case PictOpDisjointClear:
1667    case PictOpConjointClear:
1668	op = PictOpClear;
1669	break;
1670    case PictOpDisjointSrc:
1671    case PictOpConjointSrc:
1672	op = PictOpSrc;
1673	break;
1674    case PictOpDisjointDst:
1675    case PictOpConjointDst:
1676	op = PictOpDst;
1677	break;
1678    default:
1679	break;
1680    }
1681
1682    return op;
1683}
1684
1685void
1686CompositePicture (CARD8		op,
1687		  PicturePtr	pSrc,
1688		  PicturePtr	pMask,
1689		  PicturePtr	pDst,
1690		  INT16		xSrc,
1691		  INT16		ySrc,
1692		  INT16		xMask,
1693		  INT16		yMask,
1694		  INT16		xDst,
1695		  INT16		yDst,
1696		  CARD16	width,
1697		  CARD16	height)
1698{
1699    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1700
1701    ValidatePicture (pSrc);
1702    if (pMask)
1703	ValidatePicture (pMask);
1704    ValidatePicture (pDst);
1705
1706    op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
1707    if (op == PictOpDst)
1708	return;
1709
1710    (*ps->Composite) (op,
1711		       pSrc,
1712		       pMask,
1713		       pDst,
1714		       xSrc,
1715		       ySrc,
1716		       xMask,
1717		       yMask,
1718		       xDst,
1719		       yDst,
1720		       width,
1721		       height);
1722}
1723
1724void
1725CompositeRects (CARD8		op,
1726		PicturePtr	pDst,
1727		xRenderColor	*color,
1728		int		nRect,
1729		xRectangle      *rects)
1730{
1731    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1732
1733    ValidatePicture (pDst);
1734    (*ps->CompositeRects) (op, pDst, color, nRect, rects);
1735}
1736
1737void
1738CompositeTrapezoids (CARD8	    op,
1739		     PicturePtr	    pSrc,
1740		     PicturePtr	    pDst,
1741		     PictFormatPtr  maskFormat,
1742		     INT16	    xSrc,
1743		     INT16	    ySrc,
1744		     int	    ntrap,
1745		     xTrapezoid	    *traps)
1746{
1747    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1748
1749    ValidatePicture (pSrc);
1750    ValidatePicture (pDst);
1751    (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
1752}
1753
1754void
1755CompositeTriangles (CARD8	    op,
1756		    PicturePtr	    pSrc,
1757		    PicturePtr	    pDst,
1758		    PictFormatPtr   maskFormat,
1759		    INT16	    xSrc,
1760		    INT16	    ySrc,
1761		    int		    ntriangles,
1762		    xTriangle	    *triangles)
1763{
1764    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1765
1766    ValidatePicture (pSrc);
1767    ValidatePicture (pDst);
1768    (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
1769}
1770
1771void
1772CompositeTriStrip (CARD8	    op,
1773		   PicturePtr	    pSrc,
1774		   PicturePtr	    pDst,
1775		   PictFormatPtr    maskFormat,
1776		   INT16	    xSrc,
1777		   INT16	    ySrc,
1778		   int		    npoints,
1779		   xPointFixed	    *points)
1780{
1781    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1782
1783    ValidatePicture (pSrc);
1784    ValidatePicture (pDst);
1785    (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1786}
1787
1788void
1789CompositeTriFan (CARD8		op,
1790		 PicturePtr	pSrc,
1791		 PicturePtr	pDst,
1792		 PictFormatPtr	maskFormat,
1793		 INT16		xSrc,
1794		 INT16		ySrc,
1795		 int		npoints,
1796		 xPointFixed	*points)
1797{
1798    PictureScreenPtr	ps = GetPictureScreen(pDst->pDrawable->pScreen);
1799
1800    ValidatePicture (pSrc);
1801    ValidatePicture (pDst);
1802    (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
1803}
1804
1805void
1806AddTraps (PicturePtr	pPicture,
1807	  INT16		xOff,
1808	  INT16		yOff,
1809	  int		ntrap,
1810	  xTrap		*traps)
1811{
1812    PictureScreenPtr	ps = GetPictureScreen(pPicture->pDrawable->pScreen);
1813
1814    ValidatePicture (pPicture);
1815    (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
1816}
1817
1818