1706f2543Smrg/*
2706f2543Smrg *
3706f2543Smrg * Copyright © 1999 Keith Packard
4706f2543Smrg *
5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
7706f2543Smrg * the above copyright notice appear in all copies and that both that
8706f2543Smrg * copyright notice and this permission notice appear in supporting
9706f2543Smrg * documentation, and that the name of Keith Packard not be used in
10706f2543Smrg * advertising or publicity pertaining to distribution of the software without
11706f2543Smrg * specific, written prior permission.  Keith Packard makes no
12706f2543Smrg * representations about the suitability of this software for any purpose.  It
13706f2543Smrg * is provided "as is" without express or implied warranty.
14706f2543Smrg *
15706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
22706f2543Smrg */
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
25706f2543Smrg#include <dix-config.h>
26706f2543Smrg#endif
27706f2543Smrg
28706f2543Smrg#include "scrnintstr.h"
29706f2543Smrg#include "gcstruct.h"
30706f2543Smrg#include "pixmapstr.h"
31706f2543Smrg#include "windowstr.h"
32706f2543Smrg#include "mi.h"
33706f2543Smrg#include "picturestr.h"
34706f2543Smrg#include "mipict.h"
35706f2543Smrg
36706f2543Smrg#ifndef __GNUC__
37706f2543Smrg#define __inline
38706f2543Smrg#endif
39706f2543Smrg
40706f2543Smrgint
41706f2543SmrgmiCreatePicture (PicturePtr pPicture)
42706f2543Smrg{
43706f2543Smrg    return Success;
44706f2543Smrg}
45706f2543Smrg
46706f2543Smrgvoid
47706f2543SmrgmiDestroyPicture (PicturePtr pPicture)
48706f2543Smrg{
49706f2543Smrg    if (pPicture->freeCompClip)
50706f2543Smrg	RegionDestroy(pPicture->pCompositeClip);
51706f2543Smrg}
52706f2543Smrg
53706f2543Smrgvoid
54706f2543SmrgmiDestroyPictureClip (PicturePtr pPicture)
55706f2543Smrg{
56706f2543Smrg    switch (pPicture->clientClipType) {
57706f2543Smrg    case CT_NONE:
58706f2543Smrg	return;
59706f2543Smrg    case CT_PIXMAP:
60706f2543Smrg	(*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
61706f2543Smrg	break;
62706f2543Smrg    default:
63706f2543Smrg	/*
64706f2543Smrg	 * we know we'll never have a list of rectangles, since ChangeClip
65706f2543Smrg	 * immediately turns them into a region
66706f2543Smrg	 */
67706f2543Smrg	RegionDestroy(pPicture->clientClip);
68706f2543Smrg	break;
69706f2543Smrg    }
70706f2543Smrg    pPicture->clientClip = NULL;
71706f2543Smrg    pPicture->clientClipType = CT_NONE;
72706f2543Smrg}
73706f2543Smrg
74706f2543Smrgint
75706f2543SmrgmiChangePictureClip (PicturePtr    pPicture,
76706f2543Smrg		     int	   type,
77706f2543Smrg		     pointer	   value,
78706f2543Smrg		     int	   n)
79706f2543Smrg{
80706f2543Smrg    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
81706f2543Smrg    PictureScreenPtr    ps = GetPictureScreen(pScreen);
82706f2543Smrg    pointer		clientClip;
83706f2543Smrg    int			clientClipType;
84706f2543Smrg
85706f2543Smrg    switch (type) {
86706f2543Smrg    case CT_PIXMAP:
87706f2543Smrg	/* convert the pixmap to a region */
88706f2543Smrg	clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value);
89706f2543Smrg	if (!clientClip)
90706f2543Smrg	    return BadAlloc;
91706f2543Smrg	clientClipType = CT_REGION;
92706f2543Smrg	(*pScreen->DestroyPixmap) ((PixmapPtr) value);
93706f2543Smrg	break;
94706f2543Smrg    case CT_REGION:
95706f2543Smrg	clientClip = value;
96706f2543Smrg	clientClipType = CT_REGION;
97706f2543Smrg	break;
98706f2543Smrg    case CT_NONE:
99706f2543Smrg	clientClip = 0;
100706f2543Smrg	clientClipType = CT_NONE;
101706f2543Smrg	break;
102706f2543Smrg    default:
103706f2543Smrg	clientClip = (pointer) RegionFromRects(n,
104706f2543Smrg					       (xRectangle *) value,
105706f2543Smrg					       type);
106706f2543Smrg	if (!clientClip)
107706f2543Smrg	    return BadAlloc;
108706f2543Smrg	clientClipType = CT_REGION;
109706f2543Smrg	free(value);
110706f2543Smrg	break;
111706f2543Smrg    }
112706f2543Smrg    (*ps->DestroyPictureClip) (pPicture);
113706f2543Smrg    pPicture->clientClip = clientClip;
114706f2543Smrg    pPicture->clientClipType = clientClipType;
115706f2543Smrg    pPicture->stateChanges |= CPClipMask;
116706f2543Smrg    return Success;
117706f2543Smrg}
118706f2543Smrg
119706f2543Smrgvoid
120706f2543SmrgmiChangePicture (PicturePtr pPicture,
121706f2543Smrg		 Mask       mask)
122706f2543Smrg{
123706f2543Smrg    return;
124706f2543Smrg}
125706f2543Smrg
126706f2543Smrgvoid
127706f2543SmrgmiValidatePicture (PicturePtr pPicture,
128706f2543Smrg		   Mask       mask)
129706f2543Smrg{
130706f2543Smrg    DrawablePtr	    pDrawable = pPicture->pDrawable;
131706f2543Smrg
132706f2543Smrg    if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
133706f2543Smrg	(pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
134706f2543Smrg    {
135706f2543Smrg	if (pDrawable->type == DRAWABLE_WINDOW)
136706f2543Smrg	{
137706f2543Smrg	    WindowPtr       pWin = (WindowPtr) pDrawable;
138706f2543Smrg	    RegionPtr       pregWin;
139706f2543Smrg	    Bool            freeTmpClip, freeCompClip;
140706f2543Smrg
141706f2543Smrg	    if (pPicture->subWindowMode == IncludeInferiors)
142706f2543Smrg	    {
143706f2543Smrg		pregWin = NotClippedByChildren(pWin);
144706f2543Smrg		freeTmpClip = TRUE;
145706f2543Smrg	    }
146706f2543Smrg	    else
147706f2543Smrg	    {
148706f2543Smrg		pregWin = &pWin->clipList;
149706f2543Smrg		freeTmpClip = FALSE;
150706f2543Smrg	    }
151706f2543Smrg	    freeCompClip = pPicture->freeCompClip;
152706f2543Smrg
153706f2543Smrg	    /*
154706f2543Smrg	     * if there is no client clip, we can get by with just keeping the
155706f2543Smrg	     * pointer we got, and remembering whether or not should destroy
156706f2543Smrg	     * (or maybe re-use) it later.  this way, we avoid unnecessary
157706f2543Smrg	     * copying of regions.  (this wins especially if many clients clip
158706f2543Smrg	     * by children and have no client clip.)
159706f2543Smrg	     */
160706f2543Smrg	    if (pPicture->clientClipType == CT_NONE)
161706f2543Smrg	    {
162706f2543Smrg		if (freeCompClip)
163706f2543Smrg		    RegionDestroy(pPicture->pCompositeClip);
164706f2543Smrg		pPicture->pCompositeClip = pregWin;
165706f2543Smrg		pPicture->freeCompClip = freeTmpClip;
166706f2543Smrg	    }
167706f2543Smrg	    else
168706f2543Smrg	    {
169706f2543Smrg		/*
170706f2543Smrg		 * we need one 'real' region to put into the composite clip. if
171706f2543Smrg		 * pregWin the current composite clip are real, we can get rid of
172706f2543Smrg		 * one. if pregWin is real and the current composite clip isn't,
173706f2543Smrg		 * use pregWin for the composite clip. if the current composite
174706f2543Smrg		 * clip is real and pregWin isn't, use the current composite
175706f2543Smrg		 * clip. if neither is real, create a new region.
176706f2543Smrg		 */
177706f2543Smrg
178706f2543Smrg		RegionTranslate(pPicture->clientClip,
179706f2543Smrg				 pDrawable->x + pPicture->clipOrigin.x,
180706f2543Smrg				 pDrawable->y + pPicture->clipOrigin.y);
181706f2543Smrg
182706f2543Smrg		if (freeCompClip)
183706f2543Smrg		{
184706f2543Smrg		    RegionIntersect(pPicture->pCompositeClip,
185706f2543Smrg				     pregWin, pPicture->clientClip);
186706f2543Smrg		    if (freeTmpClip)
187706f2543Smrg			RegionDestroy(pregWin);
188706f2543Smrg		}
189706f2543Smrg		else if (freeTmpClip)
190706f2543Smrg		{
191706f2543Smrg		    RegionIntersect(pregWin, pregWin, pPicture->clientClip);
192706f2543Smrg		    pPicture->pCompositeClip = pregWin;
193706f2543Smrg		}
194706f2543Smrg		else
195706f2543Smrg		{
196706f2543Smrg		    pPicture->pCompositeClip = RegionCreate(NullBox, 0);
197706f2543Smrg		    RegionIntersect(pPicture->pCompositeClip,
198706f2543Smrg				     pregWin, pPicture->clientClip);
199706f2543Smrg		}
200706f2543Smrg		pPicture->freeCompClip = TRUE;
201706f2543Smrg		RegionTranslate(pPicture->clientClip,
202706f2543Smrg				 -(pDrawable->x + pPicture->clipOrigin.x),
203706f2543Smrg				 -(pDrawable->y + pPicture->clipOrigin.y));
204706f2543Smrg	    }
205706f2543Smrg	}	/* end of composite clip for a window */
206706f2543Smrg	else
207706f2543Smrg	{
208706f2543Smrg	    BoxRec          pixbounds;
209706f2543Smrg
210706f2543Smrg	    /* XXX should we translate by drawable.x/y here ? */
211706f2543Smrg	    /* If you want pixmaps in offscreen memory, yes */
212706f2543Smrg	    pixbounds.x1 = pDrawable->x;
213706f2543Smrg	    pixbounds.y1 = pDrawable->y;
214706f2543Smrg	    pixbounds.x2 = pDrawable->x + pDrawable->width;
215706f2543Smrg	    pixbounds.y2 = pDrawable->y + pDrawable->height;
216706f2543Smrg
217706f2543Smrg	    if (pPicture->freeCompClip)
218706f2543Smrg	    {
219706f2543Smrg		RegionReset(pPicture->pCompositeClip, &pixbounds);
220706f2543Smrg	    }
221706f2543Smrg	    else
222706f2543Smrg	    {
223706f2543Smrg		pPicture->freeCompClip = TRUE;
224706f2543Smrg		pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
225706f2543Smrg	    }
226706f2543Smrg
227706f2543Smrg	    if (pPicture->clientClipType == CT_REGION)
228706f2543Smrg	    {
229706f2543Smrg		if(pDrawable->x || pDrawable->y) {
230706f2543Smrg		    RegionTranslate(pPicture->clientClip,
231706f2543Smrg				     pDrawable->x + pPicture->clipOrigin.x,
232706f2543Smrg				     pDrawable->y + pPicture->clipOrigin.y);
233706f2543Smrg		    RegionIntersect(pPicture->pCompositeClip,
234706f2543Smrg				     pPicture->pCompositeClip, pPicture->clientClip);
235706f2543Smrg		    RegionTranslate(pPicture->clientClip,
236706f2543Smrg				     -(pDrawable->x + pPicture->clipOrigin.x),
237706f2543Smrg				     -(pDrawable->y + pPicture->clipOrigin.y));
238706f2543Smrg		} else {
239706f2543Smrg		    RegionTranslate(pPicture->pCompositeClip,
240706f2543Smrg				     -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
241706f2543Smrg		    RegionIntersect(pPicture->pCompositeClip,
242706f2543Smrg				     pPicture->pCompositeClip, pPicture->clientClip);
243706f2543Smrg		    RegionTranslate(pPicture->pCompositeClip,
244706f2543Smrg				     pPicture->clipOrigin.x, pPicture->clipOrigin.y);
245706f2543Smrg		}
246706f2543Smrg	    }
247706f2543Smrg	}	/* end of composite clip for pixmap */
248706f2543Smrg    }
249706f2543Smrg}
250706f2543Smrg
251706f2543Smrgint
252706f2543SmrgmiChangePictureTransform (PicturePtr	pPicture,
253706f2543Smrg			  PictTransform *transform)
254706f2543Smrg{
255706f2543Smrg    return Success;
256706f2543Smrg}
257706f2543Smrg
258706f2543Smrgint
259706f2543SmrgmiChangePictureFilter (PicturePtr pPicture,
260706f2543Smrg		       int	  filter,
261706f2543Smrg		       xFixed     *params,
262706f2543Smrg		       int	  nparams)
263706f2543Smrg{
264706f2543Smrg    return Success;
265706f2543Smrg}
266706f2543Smrg
267706f2543Smrg#define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
268706f2543Smrg
269706f2543Smrgstatic inline pixman_bool_t
270706f2543SmrgmiClipPictureReg (pixman_region16_t *	pRegion,
271706f2543Smrg		  pixman_region16_t *	pClip,
272706f2543Smrg		  int		dx,
273706f2543Smrg		  int		dy)
274706f2543Smrg{
275706f2543Smrg    if (pixman_region_n_rects(pRegion) == 1 &&
276706f2543Smrg	pixman_region_n_rects(pClip) == 1)
277706f2543Smrg    {
278706f2543Smrg	pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
279706f2543Smrg	pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
280706f2543Smrg	int	v;
281706f2543Smrg
282706f2543Smrg	if (pRbox->x1 < (v = pCbox->x1 + dx))
283706f2543Smrg	    pRbox->x1 = BOUND(v);
284706f2543Smrg	if (pRbox->x2 > (v = pCbox->x2 + dx))
285706f2543Smrg	    pRbox->x2 = BOUND(v);
286706f2543Smrg	if (pRbox->y1 < (v = pCbox->y1 + dy))
287706f2543Smrg	    pRbox->y1 = BOUND(v);
288706f2543Smrg	if (pRbox->y2 > (v = pCbox->y2 + dy))
289706f2543Smrg	    pRbox->y2 = BOUND(v);
290706f2543Smrg	if (pRbox->x1 >= pRbox->x2 ||
291706f2543Smrg	    pRbox->y1 >= pRbox->y2)
292706f2543Smrg	{
293706f2543Smrg	    pixman_region_init (pRegion);
294706f2543Smrg	}
295706f2543Smrg    }
296706f2543Smrg    else if (!pixman_region_not_empty (pClip))
297706f2543Smrg	return FALSE;
298706f2543Smrg    else
299706f2543Smrg    {
300706f2543Smrg	if (dx || dy)
301706f2543Smrg	    pixman_region_translate (pRegion, -dx, -dy);
302706f2543Smrg	if (!pixman_region_intersect (pRegion, pRegion, pClip))
303706f2543Smrg	    return FALSE;
304706f2543Smrg	if (dx || dy)
305706f2543Smrg	    pixman_region_translate(pRegion, dx, dy);
306706f2543Smrg    }
307706f2543Smrg    return pixman_region_not_empty(pRegion);
308706f2543Smrg}
309706f2543Smrg
310706f2543Smrgstatic __inline Bool
311706f2543SmrgmiClipPictureSrc (RegionPtr	pRegion,
312706f2543Smrg		  PicturePtr	pPicture,
313706f2543Smrg		  int		dx,
314706f2543Smrg		  int		dy)
315706f2543Smrg{
316706f2543Smrg    if (pPicture->clientClipType != CT_NONE)
317706f2543Smrg    {
318706f2543Smrg	Bool result;
319706f2543Smrg
320706f2543Smrg	pixman_region_translate ( pPicture->clientClip,
321706f2543Smrg				  pPicture->clipOrigin.x + dx,
322706f2543Smrg				  pPicture->clipOrigin.y + dy);
323706f2543Smrg
324706f2543Smrg	result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
325706f2543Smrg
326706f2543Smrg	pixman_region_translate ( pPicture->clientClip,
327706f2543Smrg				  - (pPicture->clipOrigin.x + dx),
328706f2543Smrg				  - (pPicture->clipOrigin.y + dy));
329706f2543Smrg
330706f2543Smrg	if (!result)
331706f2543Smrg	    return FALSE;
332706f2543Smrg    }
333706f2543Smrg    return TRUE;
334706f2543Smrg}
335706f2543Smrg
336706f2543Smrgvoid
337706f2543SmrgmiCompositeSourceValidate (PicturePtr	pPicture,
338706f2543Smrg			   INT16	x,
339706f2543Smrg			   INT16	y,
340706f2543Smrg			   CARD16	width,
341706f2543Smrg			   CARD16	height)
342706f2543Smrg{
343706f2543Smrg    DrawablePtr	pDrawable = pPicture->pDrawable;
344706f2543Smrg    ScreenPtr	pScreen;
345706f2543Smrg
346706f2543Smrg    if (!pDrawable)
347706f2543Smrg        return;
348706f2543Smrg
349706f2543Smrg    pScreen = pDrawable->pScreen;
350706f2543Smrg
351706f2543Smrg    if (pScreen->SourceValidate)
352706f2543Smrg    {
353706f2543Smrg	if (pPicture->transform)
354706f2543Smrg	{
355706f2543Smrg	    xPoint	    points[4];
356706f2543Smrg	    int		    i;
357706f2543Smrg	    int		    xmin, ymin, xmax, ymax;
358706f2543Smrg
359706f2543Smrg#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
360706f2543Smrg	    VectorSet (0, x, y);
361706f2543Smrg	    VectorSet (1, x + width, y);
362706f2543Smrg	    VectorSet (2, x, y + height);
363706f2543Smrg	    VectorSet (3, x + width, y + height);
364706f2543Smrg	    xmin = ymin = 32767;
365706f2543Smrg	    xmax = ymax = -32737;
366706f2543Smrg	    for (i = 0; i < 4; i++)
367706f2543Smrg	    {
368706f2543Smrg		PictVector  t;
369706f2543Smrg		t.vector[0] = IntToxFixed (points[i].x);
370706f2543Smrg		t.vector[1] = IntToxFixed (points[i].y);
371706f2543Smrg		t.vector[2] = xFixed1;
372706f2543Smrg		if (pixman_transform_point (pPicture->transform, &t))
373706f2543Smrg		{
374706f2543Smrg		    int	tx = xFixedToInt (t.vector[0]);
375706f2543Smrg		    int ty = xFixedToInt (t.vector[1]);
376706f2543Smrg		    if (tx < xmin) xmin = tx;
377706f2543Smrg		    if (tx > xmax) xmax = tx;
378706f2543Smrg		    if (ty < ymin) ymin = ty;
379706f2543Smrg		    if (ty > ymax) ymax = ty;
380706f2543Smrg		}
381706f2543Smrg	    }
382706f2543Smrg	    x = xmin;
383706f2543Smrg	    y = ymin;
384706f2543Smrg	    width = xmax - xmin;
385706f2543Smrg	    height = ymax - ymin;
386706f2543Smrg	}
387706f2543Smrg        x += pPicture->pDrawable->x;
388706f2543Smrg        y += pPicture->pDrawable->y;
389706f2543Smrg	(*pScreen->SourceValidate) (pDrawable, x, y, width, height,
390706f2543Smrg				    pPicture->subWindowMode);
391706f2543Smrg    }
392706f2543Smrg}
393706f2543Smrg
394706f2543Smrg/*
395706f2543Smrg * returns FALSE if the final region is empty.  Indistinguishable from
396706f2543Smrg * an allocation failure, but rendering ignores those anyways.
397706f2543Smrg */
398706f2543Smrg
399706f2543SmrgBool
400706f2543SmrgmiComputeCompositeRegion (RegionPtr	pRegion,
401706f2543Smrg			  PicturePtr	pSrc,
402706f2543Smrg			  PicturePtr	pMask,
403706f2543Smrg			  PicturePtr	pDst,
404706f2543Smrg			  INT16		xSrc,
405706f2543Smrg			  INT16		ySrc,
406706f2543Smrg			  INT16		xMask,
407706f2543Smrg			  INT16		yMask,
408706f2543Smrg			  INT16		xDst,
409706f2543Smrg			  INT16		yDst,
410706f2543Smrg			  CARD16	width,
411706f2543Smrg			  CARD16	height)
412706f2543Smrg{
413706f2543Smrg
414706f2543Smrg    int		v;
415706f2543Smrg
416706f2543Smrg    pRegion->extents.x1 = xDst;
417706f2543Smrg    v = xDst + width;
418706f2543Smrg    pRegion->extents.x2 = BOUND(v);
419706f2543Smrg    pRegion->extents.y1 = yDst;
420706f2543Smrg    v = yDst + height;
421706f2543Smrg    pRegion->extents.y2 = BOUND(v);
422706f2543Smrg    pRegion->data = 0;
423706f2543Smrg    /* Check for empty operation */
424706f2543Smrg    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
425706f2543Smrg	pRegion->extents.y1 >= pRegion->extents.y2)
426706f2543Smrg    {
427706f2543Smrg	pixman_region_init (pRegion);
428706f2543Smrg	return FALSE;
429706f2543Smrg    }
430706f2543Smrg    /* clip against dst */
431706f2543Smrg    if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
432706f2543Smrg    {
433706f2543Smrg	pixman_region_fini (pRegion);
434706f2543Smrg	return FALSE;
435706f2543Smrg    }
436706f2543Smrg    if (pDst->alphaMap)
437706f2543Smrg    {
438706f2543Smrg	if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
439706f2543Smrg			       -pDst->alphaOrigin.x,
440706f2543Smrg			       -pDst->alphaOrigin.y))
441706f2543Smrg	{
442706f2543Smrg	    pixman_region_fini (pRegion);
443706f2543Smrg	    return FALSE;
444706f2543Smrg	}
445706f2543Smrg    }
446706f2543Smrg    /* clip against src */
447706f2543Smrg    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
448706f2543Smrg    {
449706f2543Smrg	pixman_region_fini (pRegion);
450706f2543Smrg	return FALSE;
451706f2543Smrg    }
452706f2543Smrg    if (pSrc->alphaMap)
453706f2543Smrg    {
454706f2543Smrg	if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
455706f2543Smrg			       xDst - (xSrc - pSrc->alphaOrigin.x),
456706f2543Smrg			       yDst - (ySrc - pSrc->alphaOrigin.y)))
457706f2543Smrg	{
458706f2543Smrg	    pixman_region_fini (pRegion);
459706f2543Smrg	    return FALSE;
460706f2543Smrg	}
461706f2543Smrg    }
462706f2543Smrg    /* clip against mask */
463706f2543Smrg    if (pMask)
464706f2543Smrg    {
465706f2543Smrg	if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
466706f2543Smrg	{
467706f2543Smrg	    pixman_region_fini (pRegion);
468706f2543Smrg	    return FALSE;
469706f2543Smrg	}
470706f2543Smrg	if (pMask->alphaMap)
471706f2543Smrg	{
472706f2543Smrg	    if (!miClipPictureSrc (pRegion, pMask->alphaMap,
473706f2543Smrg				   xDst - (xMask - pMask->alphaOrigin.x),
474706f2543Smrg				   yDst - (yMask - pMask->alphaOrigin.y)))
475706f2543Smrg	    {
476706f2543Smrg		pixman_region_fini (pRegion);
477706f2543Smrg		return FALSE;
478706f2543Smrg	    }
479706f2543Smrg	}
480706f2543Smrg    }
481706f2543Smrg
482706f2543Smrg
483706f2543Smrg    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
484706f2543Smrg    if (pMask)
485706f2543Smrg	miCompositeSourceValidate (pMask, xMask, yMask, width, height);
486706f2543Smrg
487706f2543Smrg    return TRUE;
488706f2543Smrg}
489706f2543Smrg
490706f2543Smrgvoid
491706f2543SmrgmiRenderColorToPixel (PictFormatPtr format,
492706f2543Smrg		      xRenderColor  *color,
493706f2543Smrg		      CARD32	    *pixel)
494706f2543Smrg{
495706f2543Smrg    CARD32	    r, g, b, a;
496706f2543Smrg    miIndexedPtr    pIndexed;
497706f2543Smrg
498706f2543Smrg    switch (format->type) {
499706f2543Smrg    case PictTypeDirect:
500706f2543Smrg	r = color->red >> (16 - Ones (format->direct.redMask));
501706f2543Smrg	g = color->green >> (16 - Ones (format->direct.greenMask));
502706f2543Smrg	b = color->blue >> (16 - Ones (format->direct.blueMask));
503706f2543Smrg	a = color->alpha >> (16 - Ones (format->direct.alphaMask));
504706f2543Smrg	r = r << format->direct.red;
505706f2543Smrg	g = g << format->direct.green;
506706f2543Smrg	b = b << format->direct.blue;
507706f2543Smrg	a = a << format->direct.alpha;
508706f2543Smrg	*pixel = r|g|b|a;
509706f2543Smrg	break;
510706f2543Smrg    case PictTypeIndexed:
511706f2543Smrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
512706f2543Smrg	if (pIndexed->color)
513706f2543Smrg	{
514706f2543Smrg	    r = color->red >> 11;
515706f2543Smrg	    g = color->green >> 11;
516706f2543Smrg	    b = color->blue >> 11;
517706f2543Smrg	    *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
518706f2543Smrg	}
519706f2543Smrg	else
520706f2543Smrg	{
521706f2543Smrg	    r = color->red >> 8;
522706f2543Smrg	    g = color->green >> 8;
523706f2543Smrg	    b = color->blue >> 8;
524706f2543Smrg	    *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
525706f2543Smrg	}
526706f2543Smrg	break;
527706f2543Smrg    }
528706f2543Smrg}
529706f2543Smrg
530706f2543Smrgstatic CARD16
531706f2543SmrgmiFillColor (CARD32 pixel, int bits)
532706f2543Smrg{
533706f2543Smrg    while (bits < 16)
534706f2543Smrg    {
535706f2543Smrg	pixel |= pixel << bits;
536706f2543Smrg	bits <<= 1;
537706f2543Smrg    }
538706f2543Smrg    return (CARD16) pixel;
539706f2543Smrg}
540706f2543Smrg
541706f2543SmrgBool
542706f2543SmrgmiIsSolidAlpha (PicturePtr pSrc)
543706f2543Smrg{
544706f2543Smrg    ScreenPtr	pScreen;
545706f2543Smrg    char	line[1];
546706f2543Smrg
547706f2543Smrg    if (!pSrc->pDrawable)
548706f2543Smrg        return FALSE;
549706f2543Smrg
550706f2543Smrg    pScreen = pSrc->pDrawable->pScreen;
551706f2543Smrg
552706f2543Smrg    /* Alpha-only */
553706f2543Smrg    if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
554706f2543Smrg	return FALSE;
555706f2543Smrg    /* repeat */
556706f2543Smrg    if (!pSrc->repeat)
557706f2543Smrg	return FALSE;
558706f2543Smrg    /* 1x1 */
559706f2543Smrg    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
560706f2543Smrg	return FALSE;
561706f2543Smrg    line[0] = 1;
562706f2543Smrg    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
563706f2543Smrg    switch (pSrc->pDrawable->bitsPerPixel) {
564706f2543Smrg    case 1:
565706f2543Smrg	return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
566706f2543Smrg    case 4:
567706f2543Smrg	return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
568706f2543Smrg    case 8:
569706f2543Smrg	return (CARD8) line[0] == 0xff;
570706f2543Smrg    default:
571706f2543Smrg	return FALSE;
572706f2543Smrg    }
573706f2543Smrg}
574706f2543Smrg
575706f2543Smrgvoid
576706f2543SmrgmiRenderPixelToColor (PictFormatPtr format,
577706f2543Smrg		      CARD32	    pixel,
578706f2543Smrg		      xRenderColor  *color)
579706f2543Smrg{
580706f2543Smrg    CARD32	    r, g, b, a;
581706f2543Smrg    miIndexedPtr    pIndexed;
582706f2543Smrg
583706f2543Smrg    switch (format->type) {
584706f2543Smrg    case PictTypeDirect:
585706f2543Smrg	r = (pixel >> format->direct.red) & format->direct.redMask;
586706f2543Smrg	g = (pixel >> format->direct.green) & format->direct.greenMask;
587706f2543Smrg	b = (pixel >> format->direct.blue) & format->direct.blueMask;
588706f2543Smrg	a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
589706f2543Smrg	color->red = miFillColor (r, Ones (format->direct.redMask));
590706f2543Smrg	color->green = miFillColor (g, Ones (format->direct.greenMask));
591706f2543Smrg	color->blue = miFillColor (b, Ones (format->direct.blueMask));
592706f2543Smrg	color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
593706f2543Smrg	break;
594706f2543Smrg    case PictTypeIndexed:
595706f2543Smrg	pIndexed = (miIndexedPtr) (format->index.devPrivate);
596706f2543Smrg	pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
597706f2543Smrg	r = (pixel >> 16) & 0xff;
598706f2543Smrg	g = (pixel >>  8) & 0xff;
599706f2543Smrg	b = (pixel      ) & 0xff;
600706f2543Smrg	color->red = miFillColor (r, 8);
601706f2543Smrg	color->green = miFillColor (g, 8);
602706f2543Smrg	color->blue = miFillColor (b, 8);
603706f2543Smrg	color->alpha = 0xffff;
604706f2543Smrg	break;
605706f2543Smrg    }
606706f2543Smrg}
607706f2543Smrg
608706f2543SmrgBool
609706f2543SmrgmiPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
610706f2543Smrg{
611706f2543Smrg    PictureScreenPtr    ps;
612706f2543Smrg
613706f2543Smrg    if (!PictureInit (pScreen, formats, nformats))
614706f2543Smrg	return FALSE;
615706f2543Smrg    ps = GetPictureScreen(pScreen);
616706f2543Smrg    ps->CreatePicture = miCreatePicture;
617706f2543Smrg    ps->DestroyPicture = miDestroyPicture;
618706f2543Smrg    ps->ChangePictureClip = miChangePictureClip;
619706f2543Smrg    ps->DestroyPictureClip = miDestroyPictureClip;
620706f2543Smrg    ps->ChangePicture = miChangePicture;
621706f2543Smrg    ps->ValidatePicture = miValidatePicture;
622706f2543Smrg    ps->InitIndexed = miInitIndexed;
623706f2543Smrg    ps->CloseIndexed = miCloseIndexed;
624706f2543Smrg    ps->UpdateIndexed = miUpdateIndexed;
625706f2543Smrg    ps->ChangePictureTransform = miChangePictureTransform;
626706f2543Smrg    ps->ChangePictureFilter = miChangePictureFilter;
627706f2543Smrg    ps->RealizeGlyph = miRealizeGlyph;
628706f2543Smrg    ps->UnrealizeGlyph = miUnrealizeGlyph;
629706f2543Smrg
630706f2543Smrg    /* MI rendering routines */
631706f2543Smrg    ps->Composite	= 0;			/* requires DDX support */
632706f2543Smrg    ps->Glyphs		= miGlyphs;
633706f2543Smrg    ps->CompositeRects	= miCompositeRects;
634706f2543Smrg    ps->Trapezoids	= miTrapezoids;
635706f2543Smrg    ps->Triangles	= miTriangles;
636706f2543Smrg    ps->TriStrip	= miTriStrip;
637706f2543Smrg    ps->TriFan		= miTriFan;
638706f2543Smrg
639706f2543Smrg    ps->RasterizeTrapezoid = 0;			/* requires DDX support */
640706f2543Smrg    ps->AddTraps	= 0;			/* requires DDX support */
641706f2543Smrg    ps->AddTriangles	= 0;			/* requires DDX support */
642706f2543Smrg
643706f2543Smrg    return TRUE;
644706f2543Smrg}
645