mipict.c revision 05b261ec
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)
5005b261ecSmrg	REGION_DESTROY(pPicture->pDrawable->pScreen, 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	 */
6705b261ecSmrg	REGION_DESTROY(pPicture->pDrawable->pScreen, 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 */
8805b261ecSmrg	clientClip = (pointer) BITMAP_TO_REGION(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:
10305b261ecSmrg	clientClip = (pointer) RECTS_TO_REGION(pScreen, n,
10405b261ecSmrg					       (xRectangle *) value,
10505b261ecSmrg					       type);
10605b261ecSmrg	if (!clientClip)
10705b261ecSmrg	    return BadAlloc;
10805b261ecSmrg	clientClipType = CT_REGION;
10905b261ecSmrg	xfree(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)
16305b261ecSmrg		    REGION_DESTROY(pScreen, 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
17805b261ecSmrg		REGION_TRANSLATE(pScreen, pPicture->clientClip,
17905b261ecSmrg				 pDrawable->x + pPicture->clipOrigin.x,
18005b261ecSmrg				 pDrawable->y + pPicture->clipOrigin.y);
18105b261ecSmrg
18205b261ecSmrg		if (freeCompClip)
18305b261ecSmrg		{
18405b261ecSmrg		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
18505b261ecSmrg				     pregWin, pPicture->clientClip);
18605b261ecSmrg		    if (freeTmpClip)
18705b261ecSmrg			REGION_DESTROY(pScreen, pregWin);
18805b261ecSmrg		}
18905b261ecSmrg		else if (freeTmpClip)
19005b261ecSmrg		{
19105b261ecSmrg		    REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip);
19205b261ecSmrg		    pPicture->pCompositeClip = pregWin;
19305b261ecSmrg		}
19405b261ecSmrg		else
19505b261ecSmrg		{
19605b261ecSmrg		    pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
19705b261ecSmrg		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
19805b261ecSmrg				     pregWin, pPicture->clientClip);
19905b261ecSmrg		}
20005b261ecSmrg		pPicture->freeCompClip = TRUE;
20105b261ecSmrg		REGION_TRANSLATE(pScreen, 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	    {
21905b261ecSmrg		REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds);
22005b261ecSmrg	    }
22105b261ecSmrg	    else
22205b261ecSmrg	    {
22305b261ecSmrg		pPicture->freeCompClip = TRUE;
22405b261ecSmrg		pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
22505b261ecSmrg	    }
22605b261ecSmrg
22705b261ecSmrg	    if (pPicture->clientClipType == CT_REGION)
22805b261ecSmrg	    {
22905b261ecSmrg		if(pDrawable->x || pDrawable->y) {
23005b261ecSmrg		    REGION_TRANSLATE(pScreen, pPicture->clientClip,
23105b261ecSmrg				     pDrawable->x + pPicture->clipOrigin.x,
23205b261ecSmrg				     pDrawable->y + pPicture->clipOrigin.y);
23305b261ecSmrg		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
23405b261ecSmrg				     pPicture->pCompositeClip, pPicture->clientClip);
23505b261ecSmrg		    REGION_TRANSLATE(pScreen, pPicture->clientClip,
23605b261ecSmrg				     -(pDrawable->x + pPicture->clipOrigin.x),
23705b261ecSmrg				     -(pDrawable->y + pPicture->clipOrigin.y));
23805b261ecSmrg		} else {
23905b261ecSmrg		    REGION_TRANSLATE(pScreen, pPicture->pCompositeClip,
24005b261ecSmrg				     -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
24105b261ecSmrg		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
24205b261ecSmrg				     pPicture->pCompositeClip, pPicture->clientClip);
24305b261ecSmrg		    REGION_TRANSLATE(pScreen, 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{
31605b261ecSmrg    /* XXX what to do with clipping from transformed pictures? */
31705b261ecSmrg    if (pPicture->transform || !pPicture->pDrawable)
31805b261ecSmrg	return TRUE;
31905b261ecSmrg    if (pPicture->repeat)
32005b261ecSmrg    {
32105b261ecSmrg	if (pPicture->clientClipType != CT_NONE)
32205b261ecSmrg	{
32305b261ecSmrg	    pixman_region_translate ( pRegion,
32405b261ecSmrg			     dx - pPicture->clipOrigin.x,
32505b261ecSmrg			     dy - pPicture->clipOrigin.y);
32605b261ecSmrg	    if (!REGION_INTERSECT (pScreen, pRegion, pRegion,
32705b261ecSmrg				   (RegionPtr) pPicture->pCompositeClip)) // clientClip))
32805b261ecSmrg		return FALSE;
32905b261ecSmrg	    pixman_region_translate ( pRegion,
33005b261ecSmrg			     - (dx - pPicture->clipOrigin.x),
33105b261ecSmrg			     - (dy - pPicture->clipOrigin.y));
33205b261ecSmrg	}
33305b261ecSmrg	return TRUE;
33405b261ecSmrg    }
33505b261ecSmrg    else
33605b261ecSmrg    {
33705b261ecSmrg	return miClipPictureReg (pRegion,
33805b261ecSmrg				 pPicture->pCompositeClip,
33905b261ecSmrg				 dx,
34005b261ecSmrg				 dy);
34105b261ecSmrg    }
34205b261ecSmrg}
34305b261ecSmrg
34405b261ecSmrgvoid
34505b261ecSmrgmiCompositeSourceValidate (PicturePtr	pPicture,
34605b261ecSmrg			   INT16	x,
34705b261ecSmrg			   INT16	y,
34805b261ecSmrg			   CARD16	width,
34905b261ecSmrg			   CARD16	height)
35005b261ecSmrg{
35105b261ecSmrg    DrawablePtr	pDrawable = pPicture->pDrawable;
35205b261ecSmrg    ScreenPtr	pScreen;
35305b261ecSmrg
35405b261ecSmrg    if (!pDrawable)
35505b261ecSmrg        return;
35605b261ecSmrg
35705b261ecSmrg    pScreen = pDrawable->pScreen;
35805b261ecSmrg
35905b261ecSmrg    if (pScreen->SourceValidate)
36005b261ecSmrg    {
36105b261ecSmrg        x -= pPicture->pDrawable->x;
36205b261ecSmrg        y -= pPicture->pDrawable->y;
36305b261ecSmrg	if (pPicture->transform)
36405b261ecSmrg	{
36505b261ecSmrg	    xPoint	    points[4];
36605b261ecSmrg	    int		    i;
36705b261ecSmrg	    int		    xmin, ymin, xmax, ymax;
36805b261ecSmrg
36905b261ecSmrg#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
37005b261ecSmrg	    VectorSet (0, x, y);
37105b261ecSmrg	    VectorSet (1, x + width, y);
37205b261ecSmrg	    VectorSet (2, x, y + height);
37305b261ecSmrg	    VectorSet (3, x + width, y + height);
37405b261ecSmrg	    xmin = ymin = 32767;
37505b261ecSmrg	    xmax = ymax = -32737;
37605b261ecSmrg	    for (i = 0; i < 4; i++)
37705b261ecSmrg	    {
37805b261ecSmrg		PictVector  t;
37905b261ecSmrg		t.vector[0] = IntToxFixed (points[i].x);
38005b261ecSmrg		t.vector[1] = IntToxFixed (points[i].y);
38105b261ecSmrg		t.vector[2] = xFixed1;
38205b261ecSmrg		if (PictureTransformPoint (pPicture->transform, &t))
38305b261ecSmrg		{
38405b261ecSmrg		    int	tx = xFixedToInt (t.vector[0]);
38505b261ecSmrg		    int ty = xFixedToInt (t.vector[1]);
38605b261ecSmrg		    if (tx < xmin) xmin = tx;
38705b261ecSmrg		    if (tx > xmax) xmax = tx;
38805b261ecSmrg		    if (ty < ymin) ymin = ty;
38905b261ecSmrg		    if (ty > ymax) ymax = ty;
39005b261ecSmrg		}
39105b261ecSmrg	    }
39205b261ecSmrg	    x = xmin;
39305b261ecSmrg	    y = ymin;
39405b261ecSmrg	    width = xmax - xmin;
39505b261ecSmrg	    height = ymax - ymin;
39605b261ecSmrg	}
39705b261ecSmrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
39805b261ecSmrg    }
39905b261ecSmrg}
40005b261ecSmrg
40105b261ecSmrg/*
40205b261ecSmrg * returns FALSE if the final region is empty.  Indistinguishable from
40305b261ecSmrg * an allocation failure, but rendering ignores those anyways.
40405b261ecSmrg */
40505b261ecSmrg
40605b261ecSmrg_X_EXPORT Bool
40705b261ecSmrgmiComputeCompositeRegion (RegionPtr	pRegion,
40805b261ecSmrg			  PicturePtr	pSrc,
40905b261ecSmrg			  PicturePtr	pMask,
41005b261ecSmrg			  PicturePtr	pDst,
41105b261ecSmrg			  INT16		xSrc,
41205b261ecSmrg			  INT16		ySrc,
41305b261ecSmrg			  INT16		xMask,
41405b261ecSmrg			  INT16		yMask,
41505b261ecSmrg			  INT16		xDst,
41605b261ecSmrg			  INT16		yDst,
41705b261ecSmrg			  CARD16	width,
41805b261ecSmrg			  CARD16	height)
41905b261ecSmrg{
42005b261ecSmrg
42105b261ecSmrg    int		v;
42205b261ecSmrg
42305b261ecSmrg    pRegion->extents.x1 = xDst;
42405b261ecSmrg    v = xDst + width;
42505b261ecSmrg    pRegion->extents.x2 = BOUND(v);
42605b261ecSmrg    pRegion->extents.y1 = yDst;
42705b261ecSmrg    v = yDst + height;
42805b261ecSmrg    pRegion->extents.y2 = BOUND(v);
42905b261ecSmrg    pRegion->data = 0;
43005b261ecSmrg    /* Check for empty operation */
43105b261ecSmrg    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
43205b261ecSmrg	pRegion->extents.y1 >= pRegion->extents.y2)
43305b261ecSmrg    {
43405b261ecSmrg	pixman_region_init (pRegion);
43505b261ecSmrg	return FALSE;
43605b261ecSmrg    }
43705b261ecSmrg    /* clip against dst */
43805b261ecSmrg    if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
43905b261ecSmrg    {
44005b261ecSmrg	pixman_region_fini (pRegion);
44105b261ecSmrg	return FALSE;
44205b261ecSmrg    }
44305b261ecSmrg    if (pDst->alphaMap)
44405b261ecSmrg    {
44505b261ecSmrg	if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
44605b261ecSmrg			       -pDst->alphaOrigin.x,
44705b261ecSmrg			       -pDst->alphaOrigin.y))
44805b261ecSmrg	{
44905b261ecSmrg	    pixman_region_fini (pRegion);
45005b261ecSmrg	    return FALSE;
45105b261ecSmrg	}
45205b261ecSmrg    }
45305b261ecSmrg    /* clip against src */
45405b261ecSmrg    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
45505b261ecSmrg    {
45605b261ecSmrg	pixman_region_fini (pRegion);
45705b261ecSmrg	return FALSE;
45805b261ecSmrg    }
45905b261ecSmrg    if (pSrc->alphaMap)
46005b261ecSmrg    {
46105b261ecSmrg	if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
46205b261ecSmrg			       xDst - (xSrc + pSrc->alphaOrigin.x),
46305b261ecSmrg			       yDst - (ySrc + pSrc->alphaOrigin.y)))
46405b261ecSmrg	{
46505b261ecSmrg	    pixman_region_fini (pRegion);
46605b261ecSmrg	    return FALSE;
46705b261ecSmrg	}
46805b261ecSmrg    }
46905b261ecSmrg    /* clip against mask */
47005b261ecSmrg    if (pMask)
47105b261ecSmrg    {
47205b261ecSmrg	if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
47305b261ecSmrg	{
47405b261ecSmrg	    pixman_region_fini (pRegion);
47505b261ecSmrg	    return FALSE;
47605b261ecSmrg	}
47705b261ecSmrg	if (pMask->alphaMap)
47805b261ecSmrg	{
47905b261ecSmrg	    if (!miClipPictureSrc (pRegion, pMask->alphaMap,
48005b261ecSmrg				   xDst - (xMask + pMask->alphaOrigin.x),
48105b261ecSmrg				   yDst - (yMask + pMask->alphaOrigin.y)))
48205b261ecSmrg	    {
48305b261ecSmrg		pixman_region_fini (pRegion);
48405b261ecSmrg		return FALSE;
48505b261ecSmrg	    }
48605b261ecSmrg	}
48705b261ecSmrg    }
48805b261ecSmrg
48905b261ecSmrg
49005b261ecSmrg    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
49105b261ecSmrg    if (pMask)
49205b261ecSmrg	miCompositeSourceValidate (pMask, xMask, yMask, width, height);
49305b261ecSmrg
49405b261ecSmrg    return TRUE;
49505b261ecSmrg}
49605b261ecSmrg
49705b261ecSmrgvoid
49805b261ecSmrgmiRenderColorToPixel (PictFormatPtr format,
49905b261ecSmrg		      xRenderColor  *color,
50005b261ecSmrg		      CARD32	    *pixel)
50105b261ecSmrg{
50205b261ecSmrg    CARD32	    r, g, b, a;
50305b261ecSmrg    miIndexedPtr    pIndexed;
50405b261ecSmrg
50505b261ecSmrg    switch (format->type) {
50605b261ecSmrg    case PictTypeDirect:
50705b261ecSmrg	r = color->red >> (16 - Ones (format->direct.redMask));
50805b261ecSmrg	g = color->green >> (16 - Ones (format->direct.greenMask));
50905b261ecSmrg	b = color->blue >> (16 - Ones (format->direct.blueMask));
51005b261ecSmrg	a = color->alpha >> (16 - Ones (format->direct.alphaMask));
51105b261ecSmrg	r = r << format->direct.red;
51205b261ecSmrg	g = g << format->direct.green;
51305b261ecSmrg	b = b << format->direct.blue;
51405b261ecSmrg	a = a << format->direct.alpha;
51505b261ecSmrg	*pixel = r|g|b|a;
51605b261ecSmrg	break;
51705b261ecSmrg    case PictTypeIndexed:
51805b261ecSmrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
51905b261ecSmrg	if (pIndexed->color)
52005b261ecSmrg	{
52105b261ecSmrg	    r = color->red >> 11;
52205b261ecSmrg	    g = color->green >> 11;
52305b261ecSmrg	    b = color->blue >> 11;
52405b261ecSmrg	    *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
52505b261ecSmrg	}
52605b261ecSmrg	else
52705b261ecSmrg	{
52805b261ecSmrg	    r = color->red >> 8;
52905b261ecSmrg	    g = color->green >> 8;
53005b261ecSmrg	    b = color->blue >> 8;
53105b261ecSmrg	    *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
53205b261ecSmrg	}
53305b261ecSmrg	break;
53405b261ecSmrg    }
53505b261ecSmrg}
53605b261ecSmrg
53705b261ecSmrgstatic CARD16
53805b261ecSmrgmiFillColor (CARD32 pixel, int bits)
53905b261ecSmrg{
54005b261ecSmrg    while (bits < 16)
54105b261ecSmrg    {
54205b261ecSmrg	pixel |= pixel << bits;
54305b261ecSmrg	bits <<= 1;
54405b261ecSmrg    }
54505b261ecSmrg    return (CARD16) pixel;
54605b261ecSmrg}
54705b261ecSmrg
54805b261ecSmrgBool
54905b261ecSmrgmiIsSolidAlpha (PicturePtr pSrc)
55005b261ecSmrg{
55105b261ecSmrg    ScreenPtr	pScreen;
55205b261ecSmrg    char	line[1];
55305b261ecSmrg
55405b261ecSmrg    if (!pSrc->pDrawable)
55505b261ecSmrg        return FALSE;
55605b261ecSmrg
55705b261ecSmrg    pScreen = pSrc->pDrawable->pScreen;
55805b261ecSmrg
55905b261ecSmrg    /* Alpha-only */
56005b261ecSmrg    if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
56105b261ecSmrg	return FALSE;
56205b261ecSmrg    /* repeat */
56305b261ecSmrg    if (!pSrc->repeat)
56405b261ecSmrg	return FALSE;
56505b261ecSmrg    /* 1x1 */
56605b261ecSmrg    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
56705b261ecSmrg	return FALSE;
56805b261ecSmrg    line[0] = 1;
56905b261ecSmrg    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
57005b261ecSmrg    switch (pSrc->pDrawable->bitsPerPixel) {
57105b261ecSmrg    case 1:
57205b261ecSmrg	return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
57305b261ecSmrg    case 4:
57405b261ecSmrg	return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
57505b261ecSmrg    case 8:
57605b261ecSmrg	return (CARD8) line[0] == 0xff;
57705b261ecSmrg    default:
57805b261ecSmrg	return FALSE;
57905b261ecSmrg    }
58005b261ecSmrg}
58105b261ecSmrg
58205b261ecSmrgvoid
58305b261ecSmrgmiRenderPixelToColor (PictFormatPtr format,
58405b261ecSmrg		      CARD32	    pixel,
58505b261ecSmrg		      xRenderColor  *color)
58605b261ecSmrg{
58705b261ecSmrg    CARD32	    r, g, b, a;
58805b261ecSmrg    miIndexedPtr    pIndexed;
58905b261ecSmrg
59005b261ecSmrg    switch (format->type) {
59105b261ecSmrg    case PictTypeDirect:
59205b261ecSmrg	r = (pixel >> format->direct.red) & format->direct.redMask;
59305b261ecSmrg	g = (pixel >> format->direct.green) & format->direct.greenMask;
59405b261ecSmrg	b = (pixel >> format->direct.blue) & format->direct.blueMask;
59505b261ecSmrg	a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
59605b261ecSmrg	color->red = miFillColor (r, Ones (format->direct.redMask));
59705b261ecSmrg	color->green = miFillColor (g, Ones (format->direct.greenMask));
59805b261ecSmrg	color->blue = miFillColor (b, Ones (format->direct.blueMask));
59905b261ecSmrg	color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
60005b261ecSmrg	break;
60105b261ecSmrg    case PictTypeIndexed:
60205b261ecSmrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
60305b261ecSmrg	pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
60405b261ecSmrg	r = (pixel >> 16) & 0xff;
60505b261ecSmrg	g = (pixel >>  8) & 0xff;
60605b261ecSmrg	b = (pixel      ) & 0xff;
60705b261ecSmrg	color->red = miFillColor (r, 8);
60805b261ecSmrg	color->green = miFillColor (g, 8);
60905b261ecSmrg	color->blue = miFillColor (b, 8);
61005b261ecSmrg	color->alpha = 0xffff;
61105b261ecSmrg	break;
61205b261ecSmrg    }
61305b261ecSmrg}
61405b261ecSmrg
61505b261ecSmrg_X_EXPORT Bool
61605b261ecSmrgmiPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
61705b261ecSmrg{
61805b261ecSmrg    PictureScreenPtr    ps;
61905b261ecSmrg
62005b261ecSmrg    if (!PictureInit (pScreen, formats, nformats))
62105b261ecSmrg	return FALSE;
62205b261ecSmrg    ps = GetPictureScreen(pScreen);
62305b261ecSmrg    ps->CreatePicture = miCreatePicture;
62405b261ecSmrg    ps->DestroyPicture = miDestroyPicture;
62505b261ecSmrg    ps->ChangePictureClip = miChangePictureClip;
62605b261ecSmrg    ps->DestroyPictureClip = miDestroyPictureClip;
62705b261ecSmrg    ps->ChangePicture = miChangePicture;
62805b261ecSmrg    ps->ValidatePicture = miValidatePicture;
62905b261ecSmrg    ps->InitIndexed = miInitIndexed;
63005b261ecSmrg    ps->CloseIndexed = miCloseIndexed;
63105b261ecSmrg    ps->UpdateIndexed = miUpdateIndexed;
63205b261ecSmrg    ps->ChangePictureTransform = miChangePictureTransform;
63305b261ecSmrg    ps->ChangePictureFilter = miChangePictureFilter;
63405b261ecSmrg    ps->RealizeGlyph = miRealizeGlyph;
63505b261ecSmrg    ps->UnrealizeGlyph = miUnrealizeGlyph;
63605b261ecSmrg
63705b261ecSmrg    /* MI rendering routines */
63805b261ecSmrg    ps->Composite	= 0;			/* requires DDX support */
63905b261ecSmrg    ps->Glyphs		= miGlyphs;
64005b261ecSmrg    ps->CompositeRects	= miCompositeRects;
64105b261ecSmrg    ps->Trapezoids	= miTrapezoids;
64205b261ecSmrg    ps->Triangles	= miTriangles;
64305b261ecSmrg    ps->TriStrip	= miTriStrip;
64405b261ecSmrg    ps->TriFan		= miTriFan;
64505b261ecSmrg
64605b261ecSmrg    ps->RasterizeTrapezoid = 0;			/* requires DDX support */
64705b261ecSmrg    ps->AddTraps	= 0;			/* requires DDX support */
64805b261ecSmrg    ps->AddTriangles	= 0;			/* requires DDX support */
64905b261ecSmrg
65005b261ecSmrg    return TRUE;
65105b261ecSmrg}
652