mipict.c revision 6747b715
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
3605b261ecSmrg#ifndef __GNUC__
3705b261ecSmrg#define __inline
3805b261ecSmrg#endif
3905b261ecSmrg
4005b261ecSmrgint
4105b261ecSmrgmiCreatePicture (PicturePtr pPicture)
4205b261ecSmrg{
4305b261ecSmrg    return Success;
4405b261ecSmrg}
4505b261ecSmrg
4605b261ecSmrgvoid
4705b261ecSmrgmiDestroyPicture (PicturePtr pPicture)
4805b261ecSmrg{
4905b261ecSmrg    if (pPicture->freeCompClip)
506747b715Smrg	RegionDestroy(pPicture->pCompositeClip);
5105b261ecSmrg}
5205b261ecSmrg
5305b261ecSmrgvoid
5405b261ecSmrgmiDestroyPictureClip (PicturePtr pPicture)
5505b261ecSmrg{
5605b261ecSmrg    switch (pPicture->clientClipType) {
5705b261ecSmrg    case CT_NONE:
5805b261ecSmrg	return;
5905b261ecSmrg    case CT_PIXMAP:
6005b261ecSmrg	(*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
6105b261ecSmrg	break;
6205b261ecSmrg    default:
6305b261ecSmrg	/*
6405b261ecSmrg	 * we know we'll never have a list of rectangles, since ChangeClip
6505b261ecSmrg	 * immediately turns them into a region
6605b261ecSmrg	 */
676747b715Smrg	RegionDestroy(pPicture->clientClip);
6805b261ecSmrg	break;
6905b261ecSmrg    }
7005b261ecSmrg    pPicture->clientClip = NULL;
7105b261ecSmrg    pPicture->clientClipType = CT_NONE;
7205b261ecSmrg}
7305b261ecSmrg
7405b261ecSmrgint
7505b261ecSmrgmiChangePictureClip (PicturePtr    pPicture,
7605b261ecSmrg		     int	   type,
7705b261ecSmrg		     pointer	   value,
7805b261ecSmrg		     int	   n)
7905b261ecSmrg{
8005b261ecSmrg    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
8105b261ecSmrg    PictureScreenPtr    ps = GetPictureScreen(pScreen);
8205b261ecSmrg    pointer		clientClip;
8305b261ecSmrg    int			clientClipType;
8405b261ecSmrg
8505b261ecSmrg    switch (type) {
8605b261ecSmrg    case CT_PIXMAP:
8705b261ecSmrg	/* convert the pixmap to a region */
886747b715Smrg	clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value);
8905b261ecSmrg	if (!clientClip)
9005b261ecSmrg	    return BadAlloc;
9105b261ecSmrg	clientClipType = CT_REGION;
9205b261ecSmrg	(*pScreen->DestroyPixmap) ((PixmapPtr) value);
9305b261ecSmrg	break;
9405b261ecSmrg    case CT_REGION:
9505b261ecSmrg	clientClip = value;
9605b261ecSmrg	clientClipType = CT_REGION;
9705b261ecSmrg	break;
9805b261ecSmrg    case CT_NONE:
9905b261ecSmrg	clientClip = 0;
10005b261ecSmrg	clientClipType = CT_NONE;
10105b261ecSmrg	break;
10205b261ecSmrg    default:
1036747b715Smrg	clientClip = (pointer) RegionFromRects(n,
10405b261ecSmrg					       (xRectangle *) value,
10505b261ecSmrg					       type);
10605b261ecSmrg	if (!clientClip)
10705b261ecSmrg	    return BadAlloc;
10805b261ecSmrg	clientClipType = CT_REGION;
1096747b715Smrg	free(value);
11005b261ecSmrg	break;
11105b261ecSmrg    }
11205b261ecSmrg    (*ps->DestroyPictureClip) (pPicture);
11305b261ecSmrg    pPicture->clientClip = clientClip;
11405b261ecSmrg    pPicture->clientClipType = clientClipType;
11505b261ecSmrg    pPicture->stateChanges |= CPClipMask;
11605b261ecSmrg    return Success;
11705b261ecSmrg}
11805b261ecSmrg
11905b261ecSmrgvoid
12005b261ecSmrgmiChangePicture (PicturePtr pPicture,
12105b261ecSmrg		 Mask       mask)
12205b261ecSmrg{
12305b261ecSmrg    return;
12405b261ecSmrg}
12505b261ecSmrg
12605b261ecSmrgvoid
12705b261ecSmrgmiValidatePicture (PicturePtr pPicture,
12805b261ecSmrg		   Mask       mask)
12905b261ecSmrg{
13005b261ecSmrg    DrawablePtr	    pDrawable = pPicture->pDrawable;
13105b261ecSmrg
13205b261ecSmrg    if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
13305b261ecSmrg	(pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
13405b261ecSmrg    {
13505b261ecSmrg	if (pDrawable->type == DRAWABLE_WINDOW)
13605b261ecSmrg	{
13705b261ecSmrg	    WindowPtr       pWin = (WindowPtr) pDrawable;
13805b261ecSmrg	    RegionPtr       pregWin;
13905b261ecSmrg	    Bool            freeTmpClip, freeCompClip;
14005b261ecSmrg
14105b261ecSmrg	    if (pPicture->subWindowMode == IncludeInferiors)
14205b261ecSmrg	    {
14305b261ecSmrg		pregWin = NotClippedByChildren(pWin);
14405b261ecSmrg		freeTmpClip = TRUE;
14505b261ecSmrg	    }
14605b261ecSmrg	    else
14705b261ecSmrg	    {
14805b261ecSmrg		pregWin = &pWin->clipList;
14905b261ecSmrg		freeTmpClip = FALSE;
15005b261ecSmrg	    }
15105b261ecSmrg	    freeCompClip = pPicture->freeCompClip;
15205b261ecSmrg
15305b261ecSmrg	    /*
15405b261ecSmrg	     * if there is no client clip, we can get by with just keeping the
15505b261ecSmrg	     * pointer we got, and remembering whether or not should destroy
15605b261ecSmrg	     * (or maybe re-use) it later.  this way, we avoid unnecessary
15705b261ecSmrg	     * copying of regions.  (this wins especially if many clients clip
15805b261ecSmrg	     * by children and have no client clip.)
15905b261ecSmrg	     */
16005b261ecSmrg	    if (pPicture->clientClipType == CT_NONE)
16105b261ecSmrg	    {
16205b261ecSmrg		if (freeCompClip)
1636747b715Smrg		    RegionDestroy(pPicture->pCompositeClip);
16405b261ecSmrg		pPicture->pCompositeClip = pregWin;
16505b261ecSmrg		pPicture->freeCompClip = freeTmpClip;
16605b261ecSmrg	    }
16705b261ecSmrg	    else
16805b261ecSmrg	    {
16905b261ecSmrg		/*
17005b261ecSmrg		 * we need one 'real' region to put into the composite clip. if
17105b261ecSmrg		 * pregWin the current composite clip are real, we can get rid of
17205b261ecSmrg		 * one. if pregWin is real and the current composite clip isn't,
17305b261ecSmrg		 * use pregWin for the composite clip. if the current composite
17405b261ecSmrg		 * clip is real and pregWin isn't, use the current composite
17505b261ecSmrg		 * clip. if neither is real, create a new region.
17605b261ecSmrg		 */
17705b261ecSmrg
1786747b715Smrg		RegionTranslate(pPicture->clientClip,
17905b261ecSmrg				 pDrawable->x + pPicture->clipOrigin.x,
18005b261ecSmrg				 pDrawable->y + pPicture->clipOrigin.y);
18105b261ecSmrg
18205b261ecSmrg		if (freeCompClip)
18305b261ecSmrg		{
1846747b715Smrg		    RegionIntersect(pPicture->pCompositeClip,
18505b261ecSmrg				     pregWin, pPicture->clientClip);
18605b261ecSmrg		    if (freeTmpClip)
1876747b715Smrg			RegionDestroy(pregWin);
18805b261ecSmrg		}
18905b261ecSmrg		else if (freeTmpClip)
19005b261ecSmrg		{
1916747b715Smrg		    RegionIntersect(pregWin, pregWin, pPicture->clientClip);
19205b261ecSmrg		    pPicture->pCompositeClip = pregWin;
19305b261ecSmrg		}
19405b261ecSmrg		else
19505b261ecSmrg		{
1966747b715Smrg		    pPicture->pCompositeClip = RegionCreate(NullBox, 0);
1976747b715Smrg		    RegionIntersect(pPicture->pCompositeClip,
19805b261ecSmrg				     pregWin, pPicture->clientClip);
19905b261ecSmrg		}
20005b261ecSmrg		pPicture->freeCompClip = TRUE;
2016747b715Smrg		RegionTranslate(pPicture->clientClip,
20205b261ecSmrg				 -(pDrawable->x + pPicture->clipOrigin.x),
20305b261ecSmrg				 -(pDrawable->y + pPicture->clipOrigin.y));
20405b261ecSmrg	    }
20505b261ecSmrg	}	/* end of composite clip for a window */
20605b261ecSmrg	else
20705b261ecSmrg	{
20805b261ecSmrg	    BoxRec          pixbounds;
20905b261ecSmrg
21005b261ecSmrg	    /* XXX should we translate by drawable.x/y here ? */
21105b261ecSmrg	    /* If you want pixmaps in offscreen memory, yes */
21205b261ecSmrg	    pixbounds.x1 = pDrawable->x;
21305b261ecSmrg	    pixbounds.y1 = pDrawable->y;
21405b261ecSmrg	    pixbounds.x2 = pDrawable->x + pDrawable->width;
21505b261ecSmrg	    pixbounds.y2 = pDrawable->y + pDrawable->height;
21605b261ecSmrg
21705b261ecSmrg	    if (pPicture->freeCompClip)
21805b261ecSmrg	    {
2196747b715Smrg		RegionReset(pPicture->pCompositeClip, &pixbounds);
22005b261ecSmrg	    }
22105b261ecSmrg	    else
22205b261ecSmrg	    {
22305b261ecSmrg		pPicture->freeCompClip = TRUE;
2246747b715Smrg		pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
22505b261ecSmrg	    }
22605b261ecSmrg
22705b261ecSmrg	    if (pPicture->clientClipType == CT_REGION)
22805b261ecSmrg	    {
22905b261ecSmrg		if(pDrawable->x || pDrawable->y) {
2306747b715Smrg		    RegionTranslate(pPicture->clientClip,
23105b261ecSmrg				     pDrawable->x + pPicture->clipOrigin.x,
23205b261ecSmrg				     pDrawable->y + pPicture->clipOrigin.y);
2336747b715Smrg		    RegionIntersect(pPicture->pCompositeClip,
23405b261ecSmrg				     pPicture->pCompositeClip, pPicture->clientClip);
2356747b715Smrg		    RegionTranslate(pPicture->clientClip,
23605b261ecSmrg				     -(pDrawable->x + pPicture->clipOrigin.x),
23705b261ecSmrg				     -(pDrawable->y + pPicture->clipOrigin.y));
23805b261ecSmrg		} else {
2396747b715Smrg		    RegionTranslate(pPicture->pCompositeClip,
24005b261ecSmrg				     -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
2416747b715Smrg		    RegionIntersect(pPicture->pCompositeClip,
24205b261ecSmrg				     pPicture->pCompositeClip, pPicture->clientClip);
2436747b715Smrg		    RegionTranslate(pPicture->pCompositeClip,
24405b261ecSmrg				     pPicture->clipOrigin.x, pPicture->clipOrigin.y);
24505b261ecSmrg		}
24605b261ecSmrg	    }
24705b261ecSmrg	}	/* end of composite clip for pixmap */
24805b261ecSmrg    }
24905b261ecSmrg}
25005b261ecSmrg
25105b261ecSmrgint
25205b261ecSmrgmiChangePictureTransform (PicturePtr	pPicture,
25305b261ecSmrg			  PictTransform *transform)
25405b261ecSmrg{
25505b261ecSmrg    return Success;
25605b261ecSmrg}
25705b261ecSmrg
25805b261ecSmrgint
25905b261ecSmrgmiChangePictureFilter (PicturePtr pPicture,
26005b261ecSmrg		       int	  filter,
26105b261ecSmrg		       xFixed     *params,
26205b261ecSmrg		       int	  nparams)
26305b261ecSmrg{
26405b261ecSmrg    return Success;
26505b261ecSmrg}
26605b261ecSmrg
26705b261ecSmrg#define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
26805b261ecSmrg
26905b261ecSmrgstatic inline pixman_bool_t
27005b261ecSmrgmiClipPictureReg (pixman_region16_t *	pRegion,
27105b261ecSmrg		  pixman_region16_t *	pClip,
27205b261ecSmrg		  int		dx,
27305b261ecSmrg		  int		dy)
27405b261ecSmrg{
27505b261ecSmrg    if (pixman_region_n_rects(pRegion) == 1 &&
27605b261ecSmrg	pixman_region_n_rects(pClip) == 1)
27705b261ecSmrg    {
27805b261ecSmrg	pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
27905b261ecSmrg	pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
28005b261ecSmrg	int	v;
28105b261ecSmrg
28205b261ecSmrg	if (pRbox->x1 < (v = pCbox->x1 + dx))
28305b261ecSmrg	    pRbox->x1 = BOUND(v);
28405b261ecSmrg	if (pRbox->x2 > (v = pCbox->x2 + dx))
28505b261ecSmrg	    pRbox->x2 = BOUND(v);
28605b261ecSmrg	if (pRbox->y1 < (v = pCbox->y1 + dy))
28705b261ecSmrg	    pRbox->y1 = BOUND(v);
28805b261ecSmrg	if (pRbox->y2 > (v = pCbox->y2 + dy))
28905b261ecSmrg	    pRbox->y2 = BOUND(v);
29005b261ecSmrg	if (pRbox->x1 >= pRbox->x2 ||
29105b261ecSmrg	    pRbox->y1 >= pRbox->y2)
29205b261ecSmrg	{
29305b261ecSmrg	    pixman_region_init (pRegion);
29405b261ecSmrg	}
29505b261ecSmrg    }
29605b261ecSmrg    else if (!pixman_region_not_empty (pClip))
29705b261ecSmrg	return FALSE;
29805b261ecSmrg    else
29905b261ecSmrg    {
30005b261ecSmrg	if (dx || dy)
30105b261ecSmrg	    pixman_region_translate (pRegion, -dx, -dy);
30205b261ecSmrg	if (!pixman_region_intersect (pRegion, pRegion, pClip))
30305b261ecSmrg	    return FALSE;
30405b261ecSmrg	if (dx || dy)
30505b261ecSmrg	    pixman_region_translate(pRegion, dx, dy);
30605b261ecSmrg    }
30705b261ecSmrg    return pixman_region_not_empty(pRegion);
30805b261ecSmrg}
30905b261ecSmrg
31005b261ecSmrgstatic __inline Bool
31105b261ecSmrgmiClipPictureSrc (RegionPtr	pRegion,
31205b261ecSmrg		  PicturePtr	pPicture,
31305b261ecSmrg		  int		dx,
31405b261ecSmrg		  int		dy)
31505b261ecSmrg{
3166747b715Smrg    if (pPicture->clientClipType != CT_NONE)
31705b261ecSmrg    {
3186747b715Smrg	Bool result;
3196747b715Smrg
3206747b715Smrg	pixman_region_translate ( pPicture->clientClip,
3216747b715Smrg				  pPicture->clipOrigin.x + dx,
3226747b715Smrg				  pPicture->clipOrigin.y + dy);
3236747b715Smrg
3246747b715Smrg	result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
3256747b715Smrg
3266747b715Smrg	pixman_region_translate ( pPicture->clientClip,
3276747b715Smrg				  - (pPicture->clipOrigin.x + dx),
3286747b715Smrg				  - (pPicture->clipOrigin.y + dy));
3296747b715Smrg
3306747b715Smrg	if (!result)
3316747b715Smrg	    return FALSE;
33205b261ecSmrg    }
3336747b715Smrg    return TRUE;
33405b261ecSmrg}
33505b261ecSmrg
33605b261ecSmrgvoid
33705b261ecSmrgmiCompositeSourceValidate (PicturePtr	pPicture,
33805b261ecSmrg			   INT16	x,
33905b261ecSmrg			   INT16	y,
34005b261ecSmrg			   CARD16	width,
34105b261ecSmrg			   CARD16	height)
34205b261ecSmrg{
34305b261ecSmrg    DrawablePtr	pDrawable = pPicture->pDrawable;
34405b261ecSmrg    ScreenPtr	pScreen;
34505b261ecSmrg
34605b261ecSmrg    if (!pDrawable)
34705b261ecSmrg        return;
34805b261ecSmrg
34905b261ecSmrg    pScreen = pDrawable->pScreen;
35005b261ecSmrg
35105b261ecSmrg    if (pScreen->SourceValidate)
35205b261ecSmrg    {
35305b261ecSmrg	if (pPicture->transform)
35405b261ecSmrg	{
35505b261ecSmrg	    xPoint	    points[4];
35605b261ecSmrg	    int		    i;
35705b261ecSmrg	    int		    xmin, ymin, xmax, ymax;
35805b261ecSmrg
35905b261ecSmrg#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
36005b261ecSmrg	    VectorSet (0, x, y);
36105b261ecSmrg	    VectorSet (1, x + width, y);
36205b261ecSmrg	    VectorSet (2, x, y + height);
36305b261ecSmrg	    VectorSet (3, x + width, y + height);
36405b261ecSmrg	    xmin = ymin = 32767;
36505b261ecSmrg	    xmax = ymax = -32737;
36605b261ecSmrg	    for (i = 0; i < 4; i++)
36705b261ecSmrg	    {
36805b261ecSmrg		PictVector  t;
36905b261ecSmrg		t.vector[0] = IntToxFixed (points[i].x);
37005b261ecSmrg		t.vector[1] = IntToxFixed (points[i].y);
37105b261ecSmrg		t.vector[2] = xFixed1;
3724642e01fSmrg		if (pixman_transform_point (pPicture->transform, &t))
37305b261ecSmrg		{
37405b261ecSmrg		    int	tx = xFixedToInt (t.vector[0]);
37505b261ecSmrg		    int ty = xFixedToInt (t.vector[1]);
37605b261ecSmrg		    if (tx < xmin) xmin = tx;
37705b261ecSmrg		    if (tx > xmax) xmax = tx;
37805b261ecSmrg		    if (ty < ymin) ymin = ty;
37905b261ecSmrg		    if (ty > ymax) ymax = ty;
38005b261ecSmrg		}
38105b261ecSmrg	    }
38205b261ecSmrg	    x = xmin;
38305b261ecSmrg	    y = ymin;
38405b261ecSmrg	    width = xmax - xmin;
38505b261ecSmrg	    height = ymax - ymin;
38605b261ecSmrg	}
3876747b715Smrg        x += pPicture->pDrawable->x;
3886747b715Smrg        y += pPicture->pDrawable->y;
38905b261ecSmrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
39005b261ecSmrg    }
39105b261ecSmrg}
39205b261ecSmrg
39305b261ecSmrg/*
39405b261ecSmrg * returns FALSE if the final region is empty.  Indistinguishable from
39505b261ecSmrg * an allocation failure, but rendering ignores those anyways.
39605b261ecSmrg */
39705b261ecSmrg
3986747b715SmrgBool
39905b261ecSmrgmiComputeCompositeRegion (RegionPtr	pRegion,
40005b261ecSmrg			  PicturePtr	pSrc,
40105b261ecSmrg			  PicturePtr	pMask,
40205b261ecSmrg			  PicturePtr	pDst,
40305b261ecSmrg			  INT16		xSrc,
40405b261ecSmrg			  INT16		ySrc,
40505b261ecSmrg			  INT16		xMask,
40605b261ecSmrg			  INT16		yMask,
40705b261ecSmrg			  INT16		xDst,
40805b261ecSmrg			  INT16		yDst,
40905b261ecSmrg			  CARD16	width,
41005b261ecSmrg			  CARD16	height)
41105b261ecSmrg{
41205b261ecSmrg
41305b261ecSmrg    int		v;
41405b261ecSmrg
41505b261ecSmrg    pRegion->extents.x1 = xDst;
41605b261ecSmrg    v = xDst + width;
41705b261ecSmrg    pRegion->extents.x2 = BOUND(v);
41805b261ecSmrg    pRegion->extents.y1 = yDst;
41905b261ecSmrg    v = yDst + height;
42005b261ecSmrg    pRegion->extents.y2 = BOUND(v);
42105b261ecSmrg    pRegion->data = 0;
42205b261ecSmrg    /* Check for empty operation */
42305b261ecSmrg    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
42405b261ecSmrg	pRegion->extents.y1 >= pRegion->extents.y2)
42505b261ecSmrg    {
42605b261ecSmrg	pixman_region_init (pRegion);
42705b261ecSmrg	return FALSE;
42805b261ecSmrg    }
42905b261ecSmrg    /* clip against dst */
43005b261ecSmrg    if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
43105b261ecSmrg    {
43205b261ecSmrg	pixman_region_fini (pRegion);
43305b261ecSmrg	return FALSE;
43405b261ecSmrg    }
43505b261ecSmrg    if (pDst->alphaMap)
43605b261ecSmrg    {
43705b261ecSmrg	if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
43805b261ecSmrg			       -pDst->alphaOrigin.x,
43905b261ecSmrg			       -pDst->alphaOrigin.y))
44005b261ecSmrg	{
44105b261ecSmrg	    pixman_region_fini (pRegion);
44205b261ecSmrg	    return FALSE;
44305b261ecSmrg	}
44405b261ecSmrg    }
44505b261ecSmrg    /* clip against src */
44605b261ecSmrg    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
44705b261ecSmrg    {
44805b261ecSmrg	pixman_region_fini (pRegion);
44905b261ecSmrg	return FALSE;
45005b261ecSmrg    }
45105b261ecSmrg    if (pSrc->alphaMap)
45205b261ecSmrg    {
45305b261ecSmrg	if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
4546747b715Smrg			       xDst - (xSrc - pSrc->alphaOrigin.x),
4556747b715Smrg			       yDst - (ySrc - pSrc->alphaOrigin.y)))
45605b261ecSmrg	{
45705b261ecSmrg	    pixman_region_fini (pRegion);
45805b261ecSmrg	    return FALSE;
45905b261ecSmrg	}
46005b261ecSmrg    }
46105b261ecSmrg    /* clip against mask */
46205b261ecSmrg    if (pMask)
46305b261ecSmrg    {
46405b261ecSmrg	if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
46505b261ecSmrg	{
46605b261ecSmrg	    pixman_region_fini (pRegion);
46705b261ecSmrg	    return FALSE;
46805b261ecSmrg	}
46905b261ecSmrg	if (pMask->alphaMap)
47005b261ecSmrg	{
47105b261ecSmrg	    if (!miClipPictureSrc (pRegion, pMask->alphaMap,
4726747b715Smrg				   xDst - (xMask - pMask->alphaOrigin.x),
4736747b715Smrg				   yDst - (yMask - pMask->alphaOrigin.y)))
47405b261ecSmrg	    {
47505b261ecSmrg		pixman_region_fini (pRegion);
47605b261ecSmrg		return FALSE;
47705b261ecSmrg	    }
47805b261ecSmrg	}
47905b261ecSmrg    }
48005b261ecSmrg
48105b261ecSmrg
48205b261ecSmrg    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
48305b261ecSmrg    if (pMask)
48405b261ecSmrg	miCompositeSourceValidate (pMask, xMask, yMask, width, height);
48505b261ecSmrg
48605b261ecSmrg    return TRUE;
48705b261ecSmrg}
48805b261ecSmrg
48905b261ecSmrgvoid
49005b261ecSmrgmiRenderColorToPixel (PictFormatPtr format,
49105b261ecSmrg		      xRenderColor  *color,
49205b261ecSmrg		      CARD32	    *pixel)
49305b261ecSmrg{
49405b261ecSmrg    CARD32	    r, g, b, a;
49505b261ecSmrg    miIndexedPtr    pIndexed;
49605b261ecSmrg
49705b261ecSmrg    switch (format->type) {
49805b261ecSmrg    case PictTypeDirect:
49905b261ecSmrg	r = color->red >> (16 - Ones (format->direct.redMask));
50005b261ecSmrg	g = color->green >> (16 - Ones (format->direct.greenMask));
50105b261ecSmrg	b = color->blue >> (16 - Ones (format->direct.blueMask));
50205b261ecSmrg	a = color->alpha >> (16 - Ones (format->direct.alphaMask));
50305b261ecSmrg	r = r << format->direct.red;
50405b261ecSmrg	g = g << format->direct.green;
50505b261ecSmrg	b = b << format->direct.blue;
50605b261ecSmrg	a = a << format->direct.alpha;
50705b261ecSmrg	*pixel = r|g|b|a;
50805b261ecSmrg	break;
50905b261ecSmrg    case PictTypeIndexed:
51005b261ecSmrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
51105b261ecSmrg	if (pIndexed->color)
51205b261ecSmrg	{
51305b261ecSmrg	    r = color->red >> 11;
51405b261ecSmrg	    g = color->green >> 11;
51505b261ecSmrg	    b = color->blue >> 11;
51605b261ecSmrg	    *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
51705b261ecSmrg	}
51805b261ecSmrg	else
51905b261ecSmrg	{
52005b261ecSmrg	    r = color->red >> 8;
52105b261ecSmrg	    g = color->green >> 8;
52205b261ecSmrg	    b = color->blue >> 8;
52305b261ecSmrg	    *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
52405b261ecSmrg	}
52505b261ecSmrg	break;
52605b261ecSmrg    }
52705b261ecSmrg}
52805b261ecSmrg
52905b261ecSmrgstatic CARD16
53005b261ecSmrgmiFillColor (CARD32 pixel, int bits)
53105b261ecSmrg{
53205b261ecSmrg    while (bits < 16)
53305b261ecSmrg    {
53405b261ecSmrg	pixel |= pixel << bits;
53505b261ecSmrg	bits <<= 1;
53605b261ecSmrg    }
53705b261ecSmrg    return (CARD16) pixel;
53805b261ecSmrg}
53905b261ecSmrg
54005b261ecSmrgBool
54105b261ecSmrgmiIsSolidAlpha (PicturePtr pSrc)
54205b261ecSmrg{
54305b261ecSmrg    ScreenPtr	pScreen;
54405b261ecSmrg    char	line[1];
54505b261ecSmrg
54605b261ecSmrg    if (!pSrc->pDrawable)
54705b261ecSmrg        return FALSE;
54805b261ecSmrg
54905b261ecSmrg    pScreen = pSrc->pDrawable->pScreen;
55005b261ecSmrg
55105b261ecSmrg    /* Alpha-only */
55205b261ecSmrg    if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
55305b261ecSmrg	return FALSE;
55405b261ecSmrg    /* repeat */
55505b261ecSmrg    if (!pSrc->repeat)
55605b261ecSmrg	return FALSE;
55705b261ecSmrg    /* 1x1 */
55805b261ecSmrg    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
55905b261ecSmrg	return FALSE;
56005b261ecSmrg    line[0] = 1;
56105b261ecSmrg    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
56205b261ecSmrg    switch (pSrc->pDrawable->bitsPerPixel) {
56305b261ecSmrg    case 1:
56405b261ecSmrg	return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
56505b261ecSmrg    case 4:
56605b261ecSmrg	return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
56705b261ecSmrg    case 8:
56805b261ecSmrg	return (CARD8) line[0] == 0xff;
56905b261ecSmrg    default:
57005b261ecSmrg	return FALSE;
57105b261ecSmrg    }
57205b261ecSmrg}
57305b261ecSmrg
57405b261ecSmrgvoid
57505b261ecSmrgmiRenderPixelToColor (PictFormatPtr format,
57605b261ecSmrg		      CARD32	    pixel,
57705b261ecSmrg		      xRenderColor  *color)
57805b261ecSmrg{
57905b261ecSmrg    CARD32	    r, g, b, a;
58005b261ecSmrg    miIndexedPtr    pIndexed;
58105b261ecSmrg
58205b261ecSmrg    switch (format->type) {
58305b261ecSmrg    case PictTypeDirect:
58405b261ecSmrg	r = (pixel >> format->direct.red) & format->direct.redMask;
58505b261ecSmrg	g = (pixel >> format->direct.green) & format->direct.greenMask;
58605b261ecSmrg	b = (pixel >> format->direct.blue) & format->direct.blueMask;
58705b261ecSmrg	a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
58805b261ecSmrg	color->red = miFillColor (r, Ones (format->direct.redMask));
58905b261ecSmrg	color->green = miFillColor (g, Ones (format->direct.greenMask));
59005b261ecSmrg	color->blue = miFillColor (b, Ones (format->direct.blueMask));
59105b261ecSmrg	color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
59205b261ecSmrg	break;
59305b261ecSmrg    case PictTypeIndexed:
59405b261ecSmrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
59505b261ecSmrg	pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
59605b261ecSmrg	r = (pixel >> 16) & 0xff;
59705b261ecSmrg	g = (pixel >>  8) & 0xff;
59805b261ecSmrg	b = (pixel      ) & 0xff;
59905b261ecSmrg	color->red = miFillColor (r, 8);
60005b261ecSmrg	color->green = miFillColor (g, 8);
60105b261ecSmrg	color->blue = miFillColor (b, 8);
60205b261ecSmrg	color->alpha = 0xffff;
60305b261ecSmrg	break;
60405b261ecSmrg    }
60505b261ecSmrg}
60605b261ecSmrg
6076747b715SmrgBool
60805b261ecSmrgmiPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
60905b261ecSmrg{
61005b261ecSmrg    PictureScreenPtr    ps;
61105b261ecSmrg
61205b261ecSmrg    if (!PictureInit (pScreen, formats, nformats))
61305b261ecSmrg	return FALSE;
61405b261ecSmrg    ps = GetPictureScreen(pScreen);
61505b261ecSmrg    ps->CreatePicture = miCreatePicture;
61605b261ecSmrg    ps->DestroyPicture = miDestroyPicture;
61705b261ecSmrg    ps->ChangePictureClip = miChangePictureClip;
61805b261ecSmrg    ps->DestroyPictureClip = miDestroyPictureClip;
61905b261ecSmrg    ps->ChangePicture = miChangePicture;
62005b261ecSmrg    ps->ValidatePicture = miValidatePicture;
62105b261ecSmrg    ps->InitIndexed = miInitIndexed;
62205b261ecSmrg    ps->CloseIndexed = miCloseIndexed;
62305b261ecSmrg    ps->UpdateIndexed = miUpdateIndexed;
62405b261ecSmrg    ps->ChangePictureTransform = miChangePictureTransform;
62505b261ecSmrg    ps->ChangePictureFilter = miChangePictureFilter;
62605b261ecSmrg    ps->RealizeGlyph = miRealizeGlyph;
62705b261ecSmrg    ps->UnrealizeGlyph = miUnrealizeGlyph;
62805b261ecSmrg
62905b261ecSmrg    /* MI rendering routines */
63005b261ecSmrg    ps->Composite	= 0;			/* requires DDX support */
63105b261ecSmrg    ps->Glyphs		= miGlyphs;
63205b261ecSmrg    ps->CompositeRects	= miCompositeRects;
63305b261ecSmrg    ps->Trapezoids	= miTrapezoids;
63405b261ecSmrg    ps->Triangles	= miTriangles;
63505b261ecSmrg    ps->TriStrip	= miTriStrip;
63605b261ecSmrg    ps->TriFan		= miTriFan;
63705b261ecSmrg
63805b261ecSmrg    ps->RasterizeTrapezoid = 0;			/* requires DDX support */
63905b261ecSmrg    ps->AddTraps	= 0;			/* requires DDX support */
64005b261ecSmrg    ps->AddTriangles	= 0;			/* requires DDX support */
64105b261ecSmrg
64205b261ecSmrg    return TRUE;
64305b261ecSmrg}
644