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