xserver

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

mipict.c (19156B)


      1 /*
      2  *
      3  * Copyright © 1999 Keith Packard
      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 Keith Packard not be used in
     10  * advertising or publicity pertaining to distribution of the software without
     11  * specific, written prior permission.  Keith Packard makes no
     12  * representations about the suitability of this software for any purpose.  It
     13  * is provided "as is" without express or implied warranty.
     14  *
     15  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     17  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     21  * PERFORMANCE OF THIS SOFTWARE.
     22  */
     23 
     24 #ifdef HAVE_DIX_CONFIG_H
     25 #include <dix-config.h>
     26 #endif
     27 
     28 #include "scrnintstr.h"
     29 #include "gcstruct.h"
     30 #include "pixmapstr.h"
     31 #include "windowstr.h"
     32 #include "mi.h"
     33 #include "picturestr.h"
     34 #include "mipict.h"
     35 
     36 int
     37 miCreatePicture(PicturePtr pPicture)
     38 {
     39     return Success;
     40 }
     41 
     42 void
     43 miDestroyPicture(PicturePtr pPicture)
     44 {
     45     if (pPicture->freeCompClip)
     46         RegionDestroy(pPicture->pCompositeClip);
     47 }
     48 
     49 static void
     50 miDestroyPictureClip(PicturePtr pPicture)
     51 {
     52     if (pPicture->clientClip)
     53         RegionDestroy(pPicture->clientClip);
     54     pPicture->clientClip = NULL;
     55 }
     56 
     57 static int
     58 miChangePictureClip(PicturePtr pPicture, int type, void *value, int n)
     59 {
     60     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
     61     PictureScreenPtr ps = GetPictureScreen(pScreen);
     62     RegionPtr clientClip;
     63 
     64     switch (type) {
     65     case CT_PIXMAP:
     66         /* convert the pixmap to a region */
     67         clientClip = BitmapToRegion(pScreen, (PixmapPtr) value);
     68         if (!clientClip)
     69             return BadAlloc;
     70         (*pScreen->DestroyPixmap) ((PixmapPtr) value);
     71         break;
     72     case CT_REGION:
     73         clientClip = value;
     74         break;
     75     case CT_NONE:
     76         clientClip = 0;
     77         break;
     78     default:
     79         clientClip = RegionFromRects(n, (xRectangle *) value, type);
     80         if (!clientClip)
     81             return BadAlloc;
     82         free(value);
     83         break;
     84     }
     85     (*ps->DestroyPictureClip) (pPicture);
     86     pPicture->clientClip = clientClip;
     87     pPicture->stateChanges |= CPClipMask;
     88     return Success;
     89 }
     90 
     91 static void
     92 miChangePicture(PicturePtr pPicture, Mask mask)
     93 {
     94     return;
     95 }
     96 
     97 static void
     98 miValidatePicture(PicturePtr pPicture, Mask mask)
     99 {
    100     DrawablePtr pDrawable = pPicture->pDrawable;
    101 
    102     if ((mask & (CPClipXOrigin | CPClipYOrigin | CPClipMask | CPSubwindowMode))
    103         || (pDrawable->serialNumber !=
    104             (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) {
    105         if (pDrawable->type == DRAWABLE_WINDOW) {
    106             WindowPtr pWin = (WindowPtr) pDrawable;
    107             RegionPtr pregWin;
    108             Bool freeTmpClip, freeCompClip;
    109 
    110             if (pPicture->subWindowMode == IncludeInferiors) {
    111                 pregWin = NotClippedByChildren(pWin);
    112                 freeTmpClip = TRUE;
    113             }
    114             else {
    115                 pregWin = &pWin->clipList;
    116                 freeTmpClip = FALSE;
    117             }
    118             freeCompClip = pPicture->freeCompClip;
    119 
    120             /*
    121              * if there is no client clip, we can get by with just keeping the
    122              * pointer we got, and remembering whether or not should destroy
    123              * (or maybe re-use) it later.  this way, we avoid unnecessary
    124              * copying of regions.  (this wins especially if many clients clip
    125              * by children and have no client clip.)
    126              */
    127             if (!pPicture->clientClip) {
    128                 if (freeCompClip)
    129                     RegionDestroy(pPicture->pCompositeClip);
    130                 pPicture->pCompositeClip = pregWin;
    131                 pPicture->freeCompClip = freeTmpClip;
    132             }
    133             else {
    134                 /*
    135                  * we need one 'real' region to put into the composite clip. if
    136                  * pregWin the current composite clip are real, we can get rid of
    137                  * one. if pregWin is real and the current composite clip isn't,
    138                  * use pregWin for the composite clip. if the current composite
    139                  * clip is real and pregWin isn't, use the current composite
    140                  * clip. if neither is real, create a new region.
    141                  */
    142 
    143                 RegionTranslate(pPicture->clientClip,
    144                                 pDrawable->x + pPicture->clipOrigin.x,
    145                                 pDrawable->y + pPicture->clipOrigin.y);
    146 
    147                 if (freeCompClip) {
    148                     RegionIntersect(pPicture->pCompositeClip,
    149                                     pregWin, pPicture->clientClip);
    150                     if (freeTmpClip)
    151                         RegionDestroy(pregWin);
    152                 }
    153                 else if (freeTmpClip) {
    154                     RegionIntersect(pregWin, pregWin, pPicture->clientClip);
    155                     pPicture->pCompositeClip = pregWin;
    156                 }
    157                 else {
    158                     pPicture->pCompositeClip = RegionCreate(NullBox, 0);
    159                     RegionIntersect(pPicture->pCompositeClip,
    160                                     pregWin, pPicture->clientClip);
    161                 }
    162                 pPicture->freeCompClip = TRUE;
    163                 RegionTranslate(pPicture->clientClip,
    164                                 -(pDrawable->x + pPicture->clipOrigin.x),
    165                                 -(pDrawable->y + pPicture->clipOrigin.y));
    166             }
    167         }                       /* end of composite clip for a window */
    168         else {
    169             BoxRec pixbounds;
    170 
    171             /* XXX should we translate by drawable.x/y here ? */
    172             /* If you want pixmaps in offscreen memory, yes */
    173             pixbounds.x1 = pDrawable->x;
    174             pixbounds.y1 = pDrawable->y;
    175             pixbounds.x2 = pDrawable->x + pDrawable->width;
    176             pixbounds.y2 = pDrawable->y + pDrawable->height;
    177 
    178             if (pPicture->freeCompClip) {
    179                 RegionReset(pPicture->pCompositeClip, &pixbounds);
    180             }
    181             else {
    182                 pPicture->freeCompClip = TRUE;
    183                 pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
    184             }
    185 
    186             if (pPicture->clientClip) {
    187                 if (pDrawable->x || pDrawable->y) {
    188                     RegionTranslate(pPicture->clientClip,
    189                                     pDrawable->x + pPicture->clipOrigin.x,
    190                                     pDrawable->y + pPicture->clipOrigin.y);
    191                     RegionIntersect(pPicture->pCompositeClip,
    192                                     pPicture->pCompositeClip,
    193                                     pPicture->clientClip);
    194                     RegionTranslate(pPicture->clientClip,
    195                                     -(pDrawable->x + pPicture->clipOrigin.x),
    196                                     -(pDrawable->y + pPicture->clipOrigin.y));
    197                 }
    198                 else {
    199                     RegionTranslate(pPicture->pCompositeClip,
    200                                     -pPicture->clipOrigin.x,
    201                                     -pPicture->clipOrigin.y);
    202                     RegionIntersect(pPicture->pCompositeClip,
    203                                     pPicture->pCompositeClip,
    204                                     pPicture->clientClip);
    205                     RegionTranslate(pPicture->pCompositeClip,
    206                                     pPicture->clipOrigin.x,
    207                                     pPicture->clipOrigin.y);
    208                 }
    209             }
    210         }                       /* end of composite clip for pixmap */
    211     }
    212 }
    213 
    214 static int
    215 miChangePictureTransform(PicturePtr pPicture, PictTransform * transform)
    216 {
    217     return Success;
    218 }
    219 
    220 static int
    221 miChangePictureFilter(PicturePtr pPicture,
    222                       int filter, xFixed * params, int nparams)
    223 {
    224     return Success;
    225 }
    226 
    227 #define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
    228 
    229 static inline pixman_bool_t
    230 miClipPictureReg(pixman_region16_t * pRegion,
    231                  pixman_region16_t * pClip, int dx, int dy)
    232 {
    233     if (pixman_region_n_rects(pRegion) == 1 &&
    234         pixman_region_n_rects(pClip) == 1) {
    235         pixman_box16_t *pRbox = pixman_region_rectangles(pRegion, NULL);
    236         pixman_box16_t *pCbox = pixman_region_rectangles(pClip, NULL);
    237         int v;
    238 
    239         if (pRbox->x1 < (v = pCbox->x1 + dx))
    240             pRbox->x1 = BOUND(v);
    241         if (pRbox->x2 > (v = pCbox->x2 + dx))
    242             pRbox->x2 = BOUND(v);
    243         if (pRbox->y1 < (v = pCbox->y1 + dy))
    244             pRbox->y1 = BOUND(v);
    245         if (pRbox->y2 > (v = pCbox->y2 + dy))
    246             pRbox->y2 = BOUND(v);
    247         if (pRbox->x1 >= pRbox->x2 || pRbox->y1 >= pRbox->y2) {
    248             pixman_region_init(pRegion);
    249         }
    250     }
    251     else if (!pixman_region_not_empty(pClip))
    252         return FALSE;
    253     else {
    254         if (dx || dy)
    255             pixman_region_translate(pRegion, -dx, -dy);
    256         if (!pixman_region_intersect(pRegion, pRegion, pClip))
    257             return FALSE;
    258         if (dx || dy)
    259             pixman_region_translate(pRegion, dx, dy);
    260     }
    261     return pixman_region_not_empty(pRegion);
    262 }
    263 
    264 static inline Bool
    265 miClipPictureSrc(RegionPtr pRegion, PicturePtr pPicture, int dx, int dy)
    266 {
    267     if (pPicture->clientClip) {
    268         Bool result;
    269 
    270         pixman_region_translate(pPicture->clientClip,
    271                                 pPicture->clipOrigin.x + dx,
    272                                 pPicture->clipOrigin.y + dy);
    273 
    274         result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
    275 
    276         pixman_region_translate(pPicture->clientClip,
    277                                 -(pPicture->clipOrigin.x + dx),
    278                                 -(pPicture->clipOrigin.y + dy));
    279 
    280         if (!result)
    281             return FALSE;
    282     }
    283     return TRUE;
    284 }
    285 
    286 static void
    287 SourceValidateOnePicture(PicturePtr pPicture)
    288 {
    289     DrawablePtr pDrawable = pPicture->pDrawable;
    290     ScreenPtr pScreen;
    291 
    292     if (!pDrawable)
    293         return;
    294 
    295     pScreen = pDrawable->pScreen;
    296 
    297     pScreen->SourceValidate(pDrawable, 0, 0, pDrawable->width,
    298                             pDrawable->height, pPicture->subWindowMode);
    299 }
    300 
    301 void
    302 miCompositeSourceValidate(PicturePtr pPicture)
    303 {
    304     SourceValidateOnePicture(pPicture);
    305     if (pPicture->alphaMap)
    306         SourceValidateOnePicture(pPicture->alphaMap);
    307 }
    308 
    309 /*
    310  * returns FALSE if the final region is empty.  Indistinguishable from
    311  * an allocation failure, but rendering ignores those anyways.
    312  */
    313 
    314 Bool
    315 miComputeCompositeRegion(RegionPtr pRegion,
    316                          PicturePtr pSrc,
    317                          PicturePtr pMask,
    318                          PicturePtr pDst,
    319                          INT16 xSrc,
    320                          INT16 ySrc,
    321                          INT16 xMask,
    322                          INT16 yMask,
    323                          INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    324 {
    325 
    326     int v;
    327 
    328     pRegion->extents.x1 = xDst;
    329     v = xDst + width;
    330     pRegion->extents.x2 = BOUND(v);
    331     pRegion->extents.y1 = yDst;
    332     v = yDst + height;
    333     pRegion->extents.y2 = BOUND(v);
    334     pRegion->data = 0;
    335     /* Check for empty operation */
    336     if (pRegion->extents.x1 >= pRegion->extents.x2 ||
    337         pRegion->extents.y1 >= pRegion->extents.y2) {
    338         pixman_region_init(pRegion);
    339         return FALSE;
    340     }
    341     /* clip against dst */
    342     if (!miClipPictureReg(pRegion, pDst->pCompositeClip, 0, 0)) {
    343         pixman_region_fini(pRegion);
    344         return FALSE;
    345     }
    346     if (pDst->alphaMap) {
    347         if (!miClipPictureReg(pRegion, pDst->alphaMap->pCompositeClip,
    348                               -pDst->alphaOrigin.x, -pDst->alphaOrigin.y)) {
    349             pixman_region_fini(pRegion);
    350             return FALSE;
    351         }
    352     }
    353     /* clip against src */
    354     if (!miClipPictureSrc(pRegion, pSrc, xDst - xSrc, yDst - ySrc)) {
    355         pixman_region_fini(pRegion);
    356         return FALSE;
    357     }
    358     if (pSrc->alphaMap) {
    359         if (!miClipPictureSrc(pRegion, pSrc->alphaMap,
    360                               xDst - (xSrc - pSrc->alphaOrigin.x),
    361                               yDst - (ySrc - pSrc->alphaOrigin.y))) {
    362             pixman_region_fini(pRegion);
    363             return FALSE;
    364         }
    365     }
    366     /* clip against mask */
    367     if (pMask) {
    368         if (!miClipPictureSrc(pRegion, pMask, xDst - xMask, yDst - yMask)) {
    369             pixman_region_fini(pRegion);
    370             return FALSE;
    371         }
    372         if (pMask->alphaMap) {
    373             if (!miClipPictureSrc(pRegion, pMask->alphaMap,
    374                                   xDst - (xMask - pMask->alphaOrigin.x),
    375                                   yDst - (yMask - pMask->alphaOrigin.y))) {
    376                 pixman_region_fini(pRegion);
    377                 return FALSE;
    378             }
    379         }
    380     }
    381 
    382     miCompositeSourceValidate(pSrc);
    383     if (pMask)
    384         miCompositeSourceValidate(pMask);
    385 
    386     return TRUE;
    387 }
    388 
    389 void
    390 miRenderColorToPixel(PictFormatPtr format, xRenderColor * color, CARD32 *pixel)
    391 {
    392     CARD32 r, g, b, a;
    393     miIndexedPtr pIndexed;
    394 
    395     switch (format->type) {
    396     case PictTypeDirect:
    397         r = color->red >> (16 - Ones(format->direct.redMask));
    398         g = color->green >> (16 - Ones(format->direct.greenMask));
    399         b = color->blue >> (16 - Ones(format->direct.blueMask));
    400         a = color->alpha >> (16 - Ones(format->direct.alphaMask));
    401         r = r << format->direct.red;
    402         g = g << format->direct.green;
    403         b = b << format->direct.blue;
    404         a = a << format->direct.alpha;
    405         *pixel = r | g | b | a;
    406         break;
    407     case PictTypeIndexed:
    408         pIndexed = (miIndexedPtr) (format->index.devPrivate);
    409         if (pIndexed->color) {
    410             r = color->red >> 11;
    411             g = color->green >> 11;
    412             b = color->blue >> 11;
    413             *pixel = miIndexToEnt15(pIndexed, (r << 10) | (g << 5) | b);
    414         }
    415         else {
    416             r = color->red >> 8;
    417             g = color->green >> 8;
    418             b = color->blue >> 8;
    419             *pixel = miIndexToEntY24(pIndexed, (r << 16) | (g << 8) | b);
    420         }
    421         break;
    422     }
    423 }
    424 
    425 static CARD16
    426 miFillColor(CARD32 pixel, int bits)
    427 {
    428     while (bits < 16) {
    429         pixel |= pixel << bits;
    430         bits <<= 1;
    431     }
    432     return (CARD16) pixel;
    433 }
    434 
    435 Bool
    436 miIsSolidAlpha(PicturePtr pSrc)
    437 {
    438     ScreenPtr pScreen;
    439     char line[1];
    440 
    441     if (!pSrc->pDrawable)
    442         return FALSE;
    443 
    444     pScreen = pSrc->pDrawable->pScreen;
    445 
    446     /* Alpha-only */
    447     if (PICT_FORMAT_TYPE(pSrc->format) != PICT_TYPE_A)
    448         return FALSE;
    449     /* repeat */
    450     if (!pSrc->repeat)
    451         return FALSE;
    452     /* 1x1 */
    453     if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
    454         return FALSE;
    455     line[0] = 1;
    456     (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
    457     switch (pSrc->pDrawable->bitsPerPixel) {
    458     case 1:
    459         return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
    460     case 4:
    461         return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
    462     case 8:
    463         return (CARD8) line[0] == 0xff;
    464     default:
    465         return FALSE;
    466     }
    467 }
    468 
    469 void
    470 miRenderPixelToColor(PictFormatPtr format, CARD32 pixel, xRenderColor * color)
    471 {
    472     CARD32 r, g, b, a;
    473     miIndexedPtr pIndexed;
    474 
    475     switch (format->type) {
    476     case PictTypeDirect:
    477         r = (pixel >> format->direct.red) & format->direct.redMask;
    478         g = (pixel >> format->direct.green) & format->direct.greenMask;
    479         b = (pixel >> format->direct.blue) & format->direct.blueMask;
    480         a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
    481         color->red = miFillColor(r, Ones(format->direct.redMask));
    482         color->green = miFillColor(g, Ones(format->direct.greenMask));
    483         color->blue = miFillColor(b, Ones(format->direct.blueMask));
    484         color->alpha = miFillColor(a, Ones(format->direct.alphaMask));
    485         break;
    486     case PictTypeIndexed:
    487         pIndexed = (miIndexedPtr) (format->index.devPrivate);
    488         pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED - 1)];
    489         r = (pixel >> 16) & 0xff;
    490         g = (pixel >> 8) & 0xff;
    491         b = (pixel) & 0xff;
    492         color->red = miFillColor(r, 8);
    493         color->green = miFillColor(g, 8);
    494         color->blue = miFillColor(b, 8);
    495         color->alpha = 0xffff;
    496         break;
    497     }
    498 }
    499 
    500 static void
    501 miTriStrip(CARD8 op,
    502            PicturePtr pSrc,
    503            PicturePtr pDst,
    504            PictFormatPtr maskFormat,
    505            INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
    506 {
    507     xTriangle *tris, *tri;
    508     int ntri;
    509 
    510     ntri = npoints - 2;
    511     tris = xallocarray(ntri, sizeof(xTriangle));
    512     if (!tris)
    513         return;
    514 
    515     for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
    516         tri->p1 = points[0];
    517         tri->p2 = points[1];
    518         tri->p3 = points[2];
    519     }
    520     CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
    521     free(tris);
    522 }
    523 
    524 static void
    525 miTriFan(CARD8 op,
    526          PicturePtr pSrc,
    527          PicturePtr pDst,
    528          PictFormatPtr maskFormat,
    529          INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
    530 {
    531     xTriangle *tris, *tri;
    532     xPointFixed *first;
    533     int ntri;
    534 
    535     ntri = npoints - 2;
    536     tris = xallocarray(ntri, sizeof(xTriangle));
    537     if (!tris)
    538         return;
    539 
    540     first = points++;
    541     for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
    542         tri->p1 = *first;
    543         tri->p2 = points[0];
    544         tri->p3 = points[1];
    545     }
    546     CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
    547     free(tris);
    548 }
    549 
    550 Bool
    551 miPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
    552 {
    553     PictureScreenPtr ps;
    554 
    555     if (!PictureInit(pScreen, formats, nformats))
    556         return FALSE;
    557     ps = GetPictureScreen(pScreen);
    558     ps->CreatePicture = miCreatePicture;
    559     ps->DestroyPicture = miDestroyPicture;
    560     ps->ChangePictureClip = miChangePictureClip;
    561     ps->DestroyPictureClip = miDestroyPictureClip;
    562     ps->ChangePicture = miChangePicture;
    563     ps->ValidatePicture = miValidatePicture;
    564     ps->InitIndexed = miInitIndexed;
    565     ps->CloseIndexed = miCloseIndexed;
    566     ps->UpdateIndexed = miUpdateIndexed;
    567     ps->ChangePictureTransform = miChangePictureTransform;
    568     ps->ChangePictureFilter = miChangePictureFilter;
    569     ps->RealizeGlyph = miRealizeGlyph;
    570     ps->UnrealizeGlyph = miUnrealizeGlyph;
    571 
    572     /* MI rendering routines */
    573     ps->Composite = 0;          /* requires DDX support */
    574     ps->Glyphs = miGlyphs;
    575     ps->CompositeRects = miCompositeRects;
    576     ps->Trapezoids = 0;
    577     ps->Triangles = 0;
    578 
    579     ps->RasterizeTrapezoid = 0; /* requires DDX support */
    580     ps->AddTraps = 0;           /* requires DDX support */
    581     ps->AddTriangles = 0;       /* requires DDX support */
    582 
    583     ps->TriStrip = miTriStrip;  /* converts call to CompositeTriangles */
    584     ps->TriFan = miTriFan;
    585 
    586     return TRUE;
    587 }