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