105b261ecSmrg/*
205b261ecSmrg *
305b261ecSmrg * Copyright © 1999 Keith Packard
405b261ecSmrg *
505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
705b261ecSmrg * the above copyright notice appear in all copies and that both that
805b261ecSmrg * copyright notice and this permission notice appear in supporting
905b261ecSmrg * documentation, and that the name of Keith Packard not be used in
1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1105b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1205b261ecSmrg * representations about the suitability of this software for any purpose.  It
1305b261ecSmrg * is provided "as is" without express or implied warranty.
1405b261ecSmrg *
1505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2205b261ecSmrg */
2305b261ecSmrg
2405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2505b261ecSmrg#include <dix-config.h>
2605b261ecSmrg#endif
2705b261ecSmrg
2805b261ecSmrg#include "scrnintstr.h"
2905b261ecSmrg#include "gcstruct.h"
3005b261ecSmrg#include "pixmapstr.h"
3105b261ecSmrg#include "windowstr.h"
3205b261ecSmrg#include "mi.h"
3305b261ecSmrg#include "picturestr.h"
3405b261ecSmrg#include "mipict.h"
3505b261ecSmrg
3605b261ecSmrgint
3735c4bbdfSmrgmiCreatePicture(PicturePtr pPicture)
3805b261ecSmrg{
3905b261ecSmrg    return Success;
4005b261ecSmrg}
4105b261ecSmrg
4205b261ecSmrgvoid
4335c4bbdfSmrgmiDestroyPicture(PicturePtr pPicture)
4405b261ecSmrg{
4505b261ecSmrg    if (pPicture->freeCompClip)
4635c4bbdfSmrg        RegionDestroy(pPicture->pCompositeClip);
4705b261ecSmrg}
4805b261ecSmrg
4935c4bbdfSmrgstatic void
5035c4bbdfSmrgmiDestroyPictureClip(PicturePtr pPicture)
5105b261ecSmrg{
5235c4bbdfSmrg    if (pPicture->clientClip)
5335c4bbdfSmrg        RegionDestroy(pPicture->clientClip);
5405b261ecSmrg    pPicture->clientClip = NULL;
5535c4bbdfSmrg}
5605b261ecSmrg
5735c4bbdfSmrgstatic int
5835c4bbdfSmrgmiChangePictureClip(PicturePtr pPicture, int type, void *value, int n)
5905b261ecSmrg{
6035c4bbdfSmrg    ScreenPtr pScreen = pPicture->pDrawable->pScreen;
6135c4bbdfSmrg    PictureScreenPtr ps = GetPictureScreen(pScreen);
6235c4bbdfSmrg    RegionPtr clientClip;
6335c4bbdfSmrg
6405b261ecSmrg    switch (type) {
6505b261ecSmrg    case CT_PIXMAP:
6635c4bbdfSmrg        /* convert the pixmap to a region */
6735c4bbdfSmrg        clientClip = BitmapToRegion(pScreen, (PixmapPtr) value);
6835c4bbdfSmrg        if (!clientClip)
6935c4bbdfSmrg            return BadAlloc;
7035c4bbdfSmrg        (*pScreen->DestroyPixmap) ((PixmapPtr) value);
7135c4bbdfSmrg        break;
7205b261ecSmrg    case CT_REGION:
7335c4bbdfSmrg        clientClip = value;
7435c4bbdfSmrg        break;
7505b261ecSmrg    case CT_NONE:
7635c4bbdfSmrg        clientClip = 0;
7735c4bbdfSmrg        break;
7805b261ecSmrg    default:
7935c4bbdfSmrg        clientClip = RegionFromRects(n, (xRectangle *) value, type);
8035c4bbdfSmrg        if (!clientClip)
8135c4bbdfSmrg            return BadAlloc;
8235c4bbdfSmrg        free(value);
8335c4bbdfSmrg        break;
8405b261ecSmrg    }
8505b261ecSmrg    (*ps->DestroyPictureClip) (pPicture);
8605b261ecSmrg    pPicture->clientClip = clientClip;
8705b261ecSmrg    pPicture->stateChanges |= CPClipMask;
8805b261ecSmrg    return Success;
8905b261ecSmrg}
9005b261ecSmrg
9135c4bbdfSmrgstatic void
9235c4bbdfSmrgmiChangePicture(PicturePtr pPicture, Mask mask)
9305b261ecSmrg{
9405b261ecSmrg    return;
9505b261ecSmrg}
9605b261ecSmrg
9735c4bbdfSmrgstatic void
9835c4bbdfSmrgmiValidatePicture(PicturePtr pPicture, Mask mask)
9905b261ecSmrg{
10035c4bbdfSmrg    DrawablePtr pDrawable = pPicture->pDrawable;
10135c4bbdfSmrg
10235c4bbdfSmrg    if ((mask & (CPClipXOrigin | CPClipYOrigin | CPClipMask | CPSubwindowMode))
10335c4bbdfSmrg        || (pDrawable->serialNumber !=
10435c4bbdfSmrg            (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) {
10535c4bbdfSmrg        if (pDrawable->type == DRAWABLE_WINDOW) {
10635c4bbdfSmrg            WindowPtr pWin = (WindowPtr) pDrawable;
10735c4bbdfSmrg            RegionPtr pregWin;
10835c4bbdfSmrg            Bool freeTmpClip, freeCompClip;
10935c4bbdfSmrg
11035c4bbdfSmrg            if (pPicture->subWindowMode == IncludeInferiors) {
11135c4bbdfSmrg                pregWin = NotClippedByChildren(pWin);
11235c4bbdfSmrg                freeTmpClip = TRUE;
11335c4bbdfSmrg            }
11435c4bbdfSmrg            else {
11535c4bbdfSmrg                pregWin = &pWin->clipList;
11635c4bbdfSmrg                freeTmpClip = FALSE;
11735c4bbdfSmrg            }
11835c4bbdfSmrg            freeCompClip = pPicture->freeCompClip;
11935c4bbdfSmrg
12035c4bbdfSmrg            /*
12135c4bbdfSmrg             * if there is no client clip, we can get by with just keeping the
12235c4bbdfSmrg             * pointer we got, and remembering whether or not should destroy
12335c4bbdfSmrg             * (or maybe re-use) it later.  this way, we avoid unnecessary
12435c4bbdfSmrg             * copying of regions.  (this wins especially if many clients clip
12535c4bbdfSmrg             * by children and have no client clip.)
12635c4bbdfSmrg             */
12735c4bbdfSmrg            if (!pPicture->clientClip) {
12835c4bbdfSmrg                if (freeCompClip)
12935c4bbdfSmrg                    RegionDestroy(pPicture->pCompositeClip);
13035c4bbdfSmrg                pPicture->pCompositeClip = pregWin;
13135c4bbdfSmrg                pPicture->freeCompClip = freeTmpClip;
13235c4bbdfSmrg            }
13335c4bbdfSmrg            else {
13435c4bbdfSmrg                /*
13535c4bbdfSmrg                 * we need one 'real' region to put into the composite clip. if
13635c4bbdfSmrg                 * pregWin the current composite clip are real, we can get rid of
13735c4bbdfSmrg                 * one. if pregWin is real and the current composite clip isn't,
13835c4bbdfSmrg                 * use pregWin for the composite clip. if the current composite
13935c4bbdfSmrg                 * clip is real and pregWin isn't, use the current composite
14035c4bbdfSmrg                 * clip. if neither is real, create a new region.
14135c4bbdfSmrg                 */
14235c4bbdfSmrg
14335c4bbdfSmrg                RegionTranslate(pPicture->clientClip,
14435c4bbdfSmrg                                pDrawable->x + pPicture->clipOrigin.x,
14535c4bbdfSmrg                                pDrawable->y + pPicture->clipOrigin.y);
14635c4bbdfSmrg
14735c4bbdfSmrg                if (freeCompClip) {
14835c4bbdfSmrg                    RegionIntersect(pPicture->pCompositeClip,
14935c4bbdfSmrg                                    pregWin, pPicture->clientClip);
15035c4bbdfSmrg                    if (freeTmpClip)
15135c4bbdfSmrg                        RegionDestroy(pregWin);
15235c4bbdfSmrg                }
15335c4bbdfSmrg                else if (freeTmpClip) {
15435c4bbdfSmrg                    RegionIntersect(pregWin, pregWin, pPicture->clientClip);
15535c4bbdfSmrg                    pPicture->pCompositeClip = pregWin;
15635c4bbdfSmrg                }
15735c4bbdfSmrg                else {
15835c4bbdfSmrg                    pPicture->pCompositeClip = RegionCreate(NullBox, 0);
15935c4bbdfSmrg                    RegionIntersect(pPicture->pCompositeClip,
16035c4bbdfSmrg                                    pregWin, pPicture->clientClip);
16135c4bbdfSmrg                }
16235c4bbdfSmrg                pPicture->freeCompClip = TRUE;
16335c4bbdfSmrg                RegionTranslate(pPicture->clientClip,
16435c4bbdfSmrg                                -(pDrawable->x + pPicture->clipOrigin.x),
16535c4bbdfSmrg                                -(pDrawable->y + pPicture->clipOrigin.y));
16635c4bbdfSmrg            }
16735c4bbdfSmrg        }                       /* end of composite clip for a window */
16835c4bbdfSmrg        else {
16935c4bbdfSmrg            BoxRec pixbounds;
17035c4bbdfSmrg
17135c4bbdfSmrg            /* XXX should we translate by drawable.x/y here ? */
17235c4bbdfSmrg            /* If you want pixmaps in offscreen memory, yes */
17335c4bbdfSmrg            pixbounds.x1 = pDrawable->x;
17435c4bbdfSmrg            pixbounds.y1 = pDrawable->y;
17535c4bbdfSmrg            pixbounds.x2 = pDrawable->x + pDrawable->width;
17635c4bbdfSmrg            pixbounds.y2 = pDrawable->y + pDrawable->height;
17735c4bbdfSmrg
17835c4bbdfSmrg            if (pPicture->freeCompClip) {
17935c4bbdfSmrg                RegionReset(pPicture->pCompositeClip, &pixbounds);
18035c4bbdfSmrg            }
18135c4bbdfSmrg            else {
18235c4bbdfSmrg                pPicture->freeCompClip = TRUE;
18335c4bbdfSmrg                pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
18435c4bbdfSmrg            }
18535c4bbdfSmrg
18635c4bbdfSmrg            if (pPicture->clientClip) {
18735c4bbdfSmrg                if (pDrawable->x || pDrawable->y) {
18835c4bbdfSmrg                    RegionTranslate(pPicture->clientClip,
18935c4bbdfSmrg                                    pDrawable->x + pPicture->clipOrigin.x,
19035c4bbdfSmrg                                    pDrawable->y + pPicture->clipOrigin.y);
19135c4bbdfSmrg                    RegionIntersect(pPicture->pCompositeClip,
19235c4bbdfSmrg                                    pPicture->pCompositeClip,
19335c4bbdfSmrg                                    pPicture->clientClip);
19435c4bbdfSmrg                    RegionTranslate(pPicture->clientClip,
19535c4bbdfSmrg                                    -(pDrawable->x + pPicture->clipOrigin.x),
19635c4bbdfSmrg                                    -(pDrawable->y + pPicture->clipOrigin.y));
19735c4bbdfSmrg                }
19835c4bbdfSmrg                else {
19935c4bbdfSmrg                    RegionTranslate(pPicture->pCompositeClip,
20035c4bbdfSmrg                                    -pPicture->clipOrigin.x,
20135c4bbdfSmrg                                    -pPicture->clipOrigin.y);
20235c4bbdfSmrg                    RegionIntersect(pPicture->pCompositeClip,
20335c4bbdfSmrg                                    pPicture->pCompositeClip,
20435c4bbdfSmrg                                    pPicture->clientClip);
20535c4bbdfSmrg                    RegionTranslate(pPicture->pCompositeClip,
20635c4bbdfSmrg                                    pPicture->clipOrigin.x,
20735c4bbdfSmrg                                    pPicture->clipOrigin.y);
20835c4bbdfSmrg                }
20935c4bbdfSmrg            }
21035c4bbdfSmrg        }                       /* end of composite clip for pixmap */
21105b261ecSmrg    }
21205b261ecSmrg}
21305b261ecSmrg
21435c4bbdfSmrgstatic int
21535c4bbdfSmrgmiChangePictureTransform(PicturePtr pPicture, PictTransform * transform)
21605b261ecSmrg{
21705b261ecSmrg    return Success;
21805b261ecSmrg}
21905b261ecSmrg
22035c4bbdfSmrgstatic int
22135c4bbdfSmrgmiChangePictureFilter(PicturePtr pPicture,
22235c4bbdfSmrg                      int filter, xFixed * params, int nparams)
22305b261ecSmrg{
22405b261ecSmrg    return Success;
22505b261ecSmrg}
22605b261ecSmrg
22705b261ecSmrg#define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
22805b261ecSmrg
22905b261ecSmrgstatic inline pixman_bool_t
23035c4bbdfSmrgmiClipPictureReg(pixman_region16_t * pRegion,
23135c4bbdfSmrg                 pixman_region16_t * pClip, int dx, int dy)
23205b261ecSmrg{
23305b261ecSmrg    if (pixman_region_n_rects(pRegion) == 1 &&
23435c4bbdfSmrg        pixman_region_n_rects(pClip) == 1) {
23535c4bbdfSmrg        pixman_box16_t *pRbox = pixman_region_rectangles(pRegion, NULL);
23635c4bbdfSmrg        pixman_box16_t *pCbox = pixman_region_rectangles(pClip, NULL);
23735c4bbdfSmrg        int v;
23835c4bbdfSmrg
23935c4bbdfSmrg        if (pRbox->x1 < (v = pCbox->x1 + dx))
24035c4bbdfSmrg            pRbox->x1 = BOUND(v);
24135c4bbdfSmrg        if (pRbox->x2 > (v = pCbox->x2 + dx))
24235c4bbdfSmrg            pRbox->x2 = BOUND(v);
24335c4bbdfSmrg        if (pRbox->y1 < (v = pCbox->y1 + dy))
24435c4bbdfSmrg            pRbox->y1 = BOUND(v);
24535c4bbdfSmrg        if (pRbox->y2 > (v = pCbox->y2 + dy))
24635c4bbdfSmrg            pRbox->y2 = BOUND(v);
24735c4bbdfSmrg        if (pRbox->x1 >= pRbox->x2 || pRbox->y1 >= pRbox->y2) {
24835c4bbdfSmrg            pixman_region_init(pRegion);
24935c4bbdfSmrg        }
25005b261ecSmrg    }
25135c4bbdfSmrg    else if (!pixman_region_not_empty(pClip))
25235c4bbdfSmrg        return FALSE;
25335c4bbdfSmrg    else {
25435c4bbdfSmrg        if (dx || dy)
25535c4bbdfSmrg            pixman_region_translate(pRegion, -dx, -dy);
25635c4bbdfSmrg        if (!pixman_region_intersect(pRegion, pRegion, pClip))
25735c4bbdfSmrg            return FALSE;
25835c4bbdfSmrg        if (dx || dy)
25935c4bbdfSmrg            pixman_region_translate(pRegion, dx, dy);
26005b261ecSmrg    }
26105b261ecSmrg    return pixman_region_not_empty(pRegion);
26205b261ecSmrg}
26305b261ecSmrg
26435c4bbdfSmrgstatic inline Bool
26535c4bbdfSmrgmiClipPictureSrc(RegionPtr pRegion, PicturePtr pPicture, int dx, int dy)
26605b261ecSmrg{
26735c4bbdfSmrg    if (pPicture->clientClip) {
26835c4bbdfSmrg        Bool result;
26935c4bbdfSmrg
27035c4bbdfSmrg        pixman_region_translate(pPicture->clientClip,
27135c4bbdfSmrg                                pPicture->clipOrigin.x + dx,
27235c4bbdfSmrg                                pPicture->clipOrigin.y + dy);
27335c4bbdfSmrg
27435c4bbdfSmrg        result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
27535c4bbdfSmrg
27635c4bbdfSmrg        pixman_region_translate(pPicture->clientClip,
27735c4bbdfSmrg                                -(pPicture->clipOrigin.x + dx),
27835c4bbdfSmrg                                -(pPicture->clipOrigin.y + dy));
27935c4bbdfSmrg
28035c4bbdfSmrg        if (!result)
28135c4bbdfSmrg            return FALSE;
28205b261ecSmrg    }
2836747b715Smrg    return TRUE;
28405b261ecSmrg}
28505b261ecSmrg
28635c4bbdfSmrgstatic void
28735c4bbdfSmrgSourceValidateOnePicture(PicturePtr pPicture)
28805b261ecSmrg{
28935c4bbdfSmrg    DrawablePtr pDrawable = pPicture->pDrawable;
29035c4bbdfSmrg    ScreenPtr pScreen;
29105b261ecSmrg
29205b261ecSmrg    if (!pDrawable)
29305b261ecSmrg        return;
29405b261ecSmrg
29505b261ecSmrg    pScreen = pDrawable->pScreen;
29635c4bbdfSmrg
297ed6184dfSmrg    pScreen->SourceValidate(pDrawable, 0, 0, pDrawable->width,
298ed6184dfSmrg                            pDrawable->height, pPicture->subWindowMode);
29905b261ecSmrg}
30005b261ecSmrg
30135c4bbdfSmrgvoid
30235c4bbdfSmrgmiCompositeSourceValidate(PicturePtr pPicture)
30335c4bbdfSmrg{
30435c4bbdfSmrg    SourceValidateOnePicture(pPicture);
30535c4bbdfSmrg    if (pPicture->alphaMap)
30635c4bbdfSmrg        SourceValidateOnePicture(pPicture->alphaMap);
30735c4bbdfSmrg}
30835c4bbdfSmrg
30905b261ecSmrg/*
31005b261ecSmrg * returns FALSE if the final region is empty.  Indistinguishable from
31105b261ecSmrg * an allocation failure, but rendering ignores those anyways.
31205b261ecSmrg */
31305b261ecSmrg
3146747b715SmrgBool
31535c4bbdfSmrgmiComputeCompositeRegion(RegionPtr pRegion,
31635c4bbdfSmrg                         PicturePtr pSrc,
31735c4bbdfSmrg                         PicturePtr pMask,
31835c4bbdfSmrg                         PicturePtr pDst,
31935c4bbdfSmrg                         INT16 xSrc,
32035c4bbdfSmrg                         INT16 ySrc,
32135c4bbdfSmrg                         INT16 xMask,
32235c4bbdfSmrg                         INT16 yMask,
32335c4bbdfSmrg                         INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
32405b261ecSmrg{
32535c4bbdfSmrg
32635c4bbdfSmrg    int v;
32705b261ecSmrg
32805b261ecSmrg    pRegion->extents.x1 = xDst;
32905b261ecSmrg    v = xDst + width;
33005b261ecSmrg    pRegion->extents.x2 = BOUND(v);
33105b261ecSmrg    pRegion->extents.y1 = yDst;
33205b261ecSmrg    v = yDst + height;
33305b261ecSmrg    pRegion->extents.y2 = BOUND(v);
33405b261ecSmrg    pRegion->data = 0;
33505b261ecSmrg    /* Check for empty operation */
33605b261ecSmrg    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
33735c4bbdfSmrg        pRegion->extents.y1 >= pRegion->extents.y2) {
33835c4bbdfSmrg        pixman_region_init(pRegion);
33935c4bbdfSmrg        return FALSE;
34005b261ecSmrg    }
34105b261ecSmrg    /* clip against dst */
34235c4bbdfSmrg    if (!miClipPictureReg(pRegion, pDst->pCompositeClip, 0, 0)) {
34335c4bbdfSmrg        pixman_region_fini(pRegion);
34435c4bbdfSmrg        return FALSE;
34505b261ecSmrg    }
34635c4bbdfSmrg    if (pDst->alphaMap) {
34735c4bbdfSmrg        if (!miClipPictureReg(pRegion, pDst->alphaMap->pCompositeClip,
34835c4bbdfSmrg                              -pDst->alphaOrigin.x, -pDst->alphaOrigin.y)) {
34935c4bbdfSmrg            pixman_region_fini(pRegion);
35035c4bbdfSmrg            return FALSE;
35135c4bbdfSmrg        }
35205b261ecSmrg    }
35305b261ecSmrg    /* clip against src */
35435c4bbdfSmrg    if (!miClipPictureSrc(pRegion, pSrc, xDst - xSrc, yDst - ySrc)) {
35535c4bbdfSmrg        pixman_region_fini(pRegion);
35635c4bbdfSmrg        return FALSE;
35705b261ecSmrg    }
35835c4bbdfSmrg    if (pSrc->alphaMap) {
35935c4bbdfSmrg        if (!miClipPictureSrc(pRegion, pSrc->alphaMap,
36035c4bbdfSmrg                              xDst - (xSrc - pSrc->alphaOrigin.x),
36135c4bbdfSmrg                              yDst - (ySrc - pSrc->alphaOrigin.y))) {
36235c4bbdfSmrg            pixman_region_fini(pRegion);
36335c4bbdfSmrg            return FALSE;
36435c4bbdfSmrg        }
36505b261ecSmrg    }
36605b261ecSmrg    /* clip against mask */
36735c4bbdfSmrg    if (pMask) {
36835c4bbdfSmrg        if (!miClipPictureSrc(pRegion, pMask, xDst - xMask, yDst - yMask)) {
36935c4bbdfSmrg            pixman_region_fini(pRegion);
37035c4bbdfSmrg            return FALSE;
37135c4bbdfSmrg        }
37235c4bbdfSmrg        if (pMask->alphaMap) {
37335c4bbdfSmrg            if (!miClipPictureSrc(pRegion, pMask->alphaMap,
37435c4bbdfSmrg                                  xDst - (xMask - pMask->alphaOrigin.x),
37535c4bbdfSmrg                                  yDst - (yMask - pMask->alphaOrigin.y))) {
37635c4bbdfSmrg                pixman_region_fini(pRegion);
37735c4bbdfSmrg                return FALSE;
37835c4bbdfSmrg            }
37935c4bbdfSmrg        }
38005b261ecSmrg    }
38105b261ecSmrg
38235c4bbdfSmrg    miCompositeSourceValidate(pSrc);
38305b261ecSmrg    if (pMask)
38435c4bbdfSmrg        miCompositeSourceValidate(pMask);
38505b261ecSmrg
38605b261ecSmrg    return TRUE;
38705b261ecSmrg}
38805b261ecSmrg
38905b261ecSmrgvoid
39035c4bbdfSmrgmiRenderColorToPixel(PictFormatPtr format, xRenderColor * color, CARD32 *pixel)
39105b261ecSmrg{
39235c4bbdfSmrg    CARD32 r, g, b, a;
39335c4bbdfSmrg    miIndexedPtr pIndexed;
39405b261ecSmrg
39505b261ecSmrg    switch (format->type) {
39605b261ecSmrg    case PictTypeDirect:
39735c4bbdfSmrg        r = color->red >> (16 - Ones(format->direct.redMask));
39835c4bbdfSmrg        g = color->green >> (16 - Ones(format->direct.greenMask));
39935c4bbdfSmrg        b = color->blue >> (16 - Ones(format->direct.blueMask));
40035c4bbdfSmrg        a = color->alpha >> (16 - Ones(format->direct.alphaMask));
40135c4bbdfSmrg        r = r << format->direct.red;
40235c4bbdfSmrg        g = g << format->direct.green;
40335c4bbdfSmrg        b = b << format->direct.blue;
40435c4bbdfSmrg        a = a << format->direct.alpha;
40535c4bbdfSmrg        *pixel = r | g | b | a;
40635c4bbdfSmrg        break;
40705b261ecSmrg    case PictTypeIndexed:
40835c4bbdfSmrg        pIndexed = (miIndexedPtr) (format->index.devPrivate);
40935c4bbdfSmrg        if (pIndexed->color) {
41035c4bbdfSmrg            r = color->red >> 11;
41135c4bbdfSmrg            g = color->green >> 11;
41235c4bbdfSmrg            b = color->blue >> 11;
41335c4bbdfSmrg            *pixel = miIndexToEnt15(pIndexed, (r << 10) | (g << 5) | b);
41435c4bbdfSmrg        }
41535c4bbdfSmrg        else {
41635c4bbdfSmrg            r = color->red >> 8;
41735c4bbdfSmrg            g = color->green >> 8;
41835c4bbdfSmrg            b = color->blue >> 8;
41935c4bbdfSmrg            *pixel = miIndexToEntY24(pIndexed, (r << 16) | (g << 8) | b);
42035c4bbdfSmrg        }
42135c4bbdfSmrg        break;
42205b261ecSmrg    }
42305b261ecSmrg}
42405b261ecSmrg
42505b261ecSmrgstatic CARD16
42635c4bbdfSmrgmiFillColor(CARD32 pixel, int bits)
42705b261ecSmrg{
42835c4bbdfSmrg    while (bits < 16) {
42935c4bbdfSmrg        pixel |= pixel << bits;
43035c4bbdfSmrg        bits <<= 1;
43105b261ecSmrg    }
43205b261ecSmrg    return (CARD16) pixel;
43305b261ecSmrg}
43405b261ecSmrg
43505b261ecSmrgBool
43635c4bbdfSmrgmiIsSolidAlpha(PicturePtr pSrc)
43705b261ecSmrg{
43835c4bbdfSmrg    ScreenPtr pScreen;
43935c4bbdfSmrg    char line[1];
44005b261ecSmrg
44105b261ecSmrg    if (!pSrc->pDrawable)
44205b261ecSmrg        return FALSE;
44305b261ecSmrg
44405b261ecSmrg    pScreen = pSrc->pDrawable->pScreen;
44535c4bbdfSmrg
44605b261ecSmrg    /* Alpha-only */
44735c4bbdfSmrg    if (PICT_FORMAT_TYPE(pSrc->format) != PICT_TYPE_A)
44835c4bbdfSmrg        return FALSE;
44905b261ecSmrg    /* repeat */
45005b261ecSmrg    if (!pSrc->repeat)
45135c4bbdfSmrg        return FALSE;
45205b261ecSmrg    /* 1x1 */
45305b261ecSmrg    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
45435c4bbdfSmrg        return FALSE;
45505b261ecSmrg    line[0] = 1;
45605b261ecSmrg    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
45705b261ecSmrg    switch (pSrc->pDrawable->bitsPerPixel) {
45805b261ecSmrg    case 1:
45935c4bbdfSmrg        return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
46005b261ecSmrg    case 4:
46135c4bbdfSmrg        return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
46205b261ecSmrg    case 8:
46335c4bbdfSmrg        return (CARD8) line[0] == 0xff;
46405b261ecSmrg    default:
46535c4bbdfSmrg        return FALSE;
46605b261ecSmrg    }
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrgvoid
47035c4bbdfSmrgmiRenderPixelToColor(PictFormatPtr format, CARD32 pixel, xRenderColor * color)
47105b261ecSmrg{
47235c4bbdfSmrg    CARD32 r, g, b, a;
47335c4bbdfSmrg    miIndexedPtr pIndexed;
47435c4bbdfSmrg
47505b261ecSmrg    switch (format->type) {
47605b261ecSmrg    case PictTypeDirect:
47735c4bbdfSmrg        r = (pixel >> format->direct.red) & format->direct.redMask;
47835c4bbdfSmrg        g = (pixel >> format->direct.green) & format->direct.greenMask;
47935c4bbdfSmrg        b = (pixel >> format->direct.blue) & format->direct.blueMask;
48035c4bbdfSmrg        a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
48135c4bbdfSmrg        color->red = miFillColor(r, Ones(format->direct.redMask));
48235c4bbdfSmrg        color->green = miFillColor(g, Ones(format->direct.greenMask));
48335c4bbdfSmrg        color->blue = miFillColor(b, Ones(format->direct.blueMask));
48435c4bbdfSmrg        color->alpha = miFillColor(a, Ones(format->direct.alphaMask));
48535c4bbdfSmrg        break;
48605b261ecSmrg    case PictTypeIndexed:
48735c4bbdfSmrg        pIndexed = (miIndexedPtr) (format->index.devPrivate);
48835c4bbdfSmrg        pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED - 1)];
48935c4bbdfSmrg        r = (pixel >> 16) & 0xff;
49035c4bbdfSmrg        g = (pixel >> 8) & 0xff;
49135c4bbdfSmrg        b = (pixel) & 0xff;
49235c4bbdfSmrg        color->red = miFillColor(r, 8);
49335c4bbdfSmrg        color->green = miFillColor(g, 8);
49435c4bbdfSmrg        color->blue = miFillColor(b, 8);
49535c4bbdfSmrg        color->alpha = 0xffff;
49635c4bbdfSmrg        break;
49735c4bbdfSmrg    }
49835c4bbdfSmrg}
49935c4bbdfSmrg
50035c4bbdfSmrgstatic void
50135c4bbdfSmrgmiTriStrip(CARD8 op,
50235c4bbdfSmrg           PicturePtr pSrc,
50335c4bbdfSmrg           PicturePtr pDst,
50435c4bbdfSmrg           PictFormatPtr maskFormat,
50535c4bbdfSmrg           INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
50635c4bbdfSmrg{
50735c4bbdfSmrg    xTriangle *tris, *tri;
50835c4bbdfSmrg    int ntri;
50935c4bbdfSmrg
51035c4bbdfSmrg    ntri = npoints - 2;
51135c4bbdfSmrg    tris = xallocarray(ntri, sizeof(xTriangle));
51235c4bbdfSmrg    if (!tris)
51335c4bbdfSmrg        return;
51435c4bbdfSmrg
51535c4bbdfSmrg    for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
51635c4bbdfSmrg        tri->p1 = points[0];
51735c4bbdfSmrg        tri->p2 = points[1];
51835c4bbdfSmrg        tri->p3 = points[2];
51905b261ecSmrg    }
52035c4bbdfSmrg    CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
52135c4bbdfSmrg    free(tris);
52235c4bbdfSmrg}
52335c4bbdfSmrg
52435c4bbdfSmrgstatic void
52535c4bbdfSmrgmiTriFan(CARD8 op,
52635c4bbdfSmrg         PicturePtr pSrc,
52735c4bbdfSmrg         PicturePtr pDst,
52835c4bbdfSmrg         PictFormatPtr maskFormat,
52935c4bbdfSmrg         INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
53035c4bbdfSmrg{
53135c4bbdfSmrg    xTriangle *tris, *tri;
53235c4bbdfSmrg    xPointFixed *first;
53335c4bbdfSmrg    int ntri;
53435c4bbdfSmrg
53535c4bbdfSmrg    ntri = npoints - 2;
53635c4bbdfSmrg    tris = xallocarray(ntri, sizeof(xTriangle));
53735c4bbdfSmrg    if (!tris)
53835c4bbdfSmrg        return;
53935c4bbdfSmrg
54035c4bbdfSmrg    first = points++;
54135c4bbdfSmrg    for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
54235c4bbdfSmrg        tri->p1 = *first;
54335c4bbdfSmrg        tri->p2 = points[0];
54435c4bbdfSmrg        tri->p3 = points[1];
54535c4bbdfSmrg    }
54635c4bbdfSmrg    CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
54735c4bbdfSmrg    free(tris);
54805b261ecSmrg}
54905b261ecSmrg
5506747b715SmrgBool
55135c4bbdfSmrgmiPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
55205b261ecSmrg{
55335c4bbdfSmrg    PictureScreenPtr ps;
55435c4bbdfSmrg
55535c4bbdfSmrg    if (!PictureInit(pScreen, formats, nformats))
55635c4bbdfSmrg        return FALSE;
55705b261ecSmrg    ps = GetPictureScreen(pScreen);
55805b261ecSmrg    ps->CreatePicture = miCreatePicture;
55905b261ecSmrg    ps->DestroyPicture = miDestroyPicture;
56005b261ecSmrg    ps->ChangePictureClip = miChangePictureClip;
56105b261ecSmrg    ps->DestroyPictureClip = miDestroyPictureClip;
56205b261ecSmrg    ps->ChangePicture = miChangePicture;
56305b261ecSmrg    ps->ValidatePicture = miValidatePicture;
56405b261ecSmrg    ps->InitIndexed = miInitIndexed;
56505b261ecSmrg    ps->CloseIndexed = miCloseIndexed;
56605b261ecSmrg    ps->UpdateIndexed = miUpdateIndexed;
56705b261ecSmrg    ps->ChangePictureTransform = miChangePictureTransform;
56805b261ecSmrg    ps->ChangePictureFilter = miChangePictureFilter;
56905b261ecSmrg    ps->RealizeGlyph = miRealizeGlyph;
57005b261ecSmrg    ps->UnrealizeGlyph = miUnrealizeGlyph;
57105b261ecSmrg
57205b261ecSmrg    /* MI rendering routines */
57335c4bbdfSmrg    ps->Composite = 0;          /* requires DDX support */
57435c4bbdfSmrg    ps->Glyphs = miGlyphs;
57535c4bbdfSmrg    ps->CompositeRects = miCompositeRects;
57635c4bbdfSmrg    ps->Trapezoids = 0;
57735c4bbdfSmrg    ps->Triangles = 0;
57835c4bbdfSmrg
57935c4bbdfSmrg    ps->RasterizeTrapezoid = 0; /* requires DDX support */
58035c4bbdfSmrg    ps->AddTraps = 0;           /* requires DDX support */
58135c4bbdfSmrg    ps->AddTriangles = 0;       /* requires DDX support */
58235c4bbdfSmrg
58335c4bbdfSmrg    ps->TriStrip = miTriStrip;  /* converts call to CompositeTriangles */
58435c4bbdfSmrg    ps->TriFan = miTriFan;
58505b261ecSmrg
58605b261ecSmrg    return TRUE;
58705b261ecSmrg}
588