xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

picture.c (47997B)


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