652 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			652 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 *
 | 
						|
 * Copyright © 1999 Keith Packard
 | 
						|
 *
 | 
						|
 * Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
 * documentation for any purpose is hereby granted without fee, provided that
 | 
						|
 * the above copyright notice appear in all copies and that both that
 | 
						|
 * copyright notice and this permission notice appear in supporting
 | 
						|
 * documentation, and that the name of Keith Packard not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Keith Packard makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | 
						|
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | 
						|
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | 
						|
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | 
						|
 * PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "mi.h"
 | 
						|
#include "picturestr.h"
 | 
						|
#include "mipict.h"
 | 
						|
 | 
						|
#ifndef __GNUC__
 | 
						|
#define __inline
 | 
						|
#endif
 | 
						|
 | 
						|
int
 | 
						|
miCreatePicture (PicturePtr pPicture)
 | 
						|
{
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miDestroyPicture (PicturePtr pPicture)
 | 
						|
{
 | 
						|
    if (pPicture->freeCompClip)
 | 
						|
	REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->pCompositeClip);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miDestroyPictureClip (PicturePtr pPicture)
 | 
						|
{
 | 
						|
    switch (pPicture->clientClipType) {
 | 
						|
    case CT_NONE:
 | 
						|
	return;
 | 
						|
    case CT_PIXMAP:
 | 
						|
	(*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	/*
 | 
						|
	 * we know we'll never have a list of rectangles, since ChangeClip
 | 
						|
	 * immediately turns them into a region
 | 
						|
	 */
 | 
						|
	REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->clientClip);
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    pPicture->clientClip = NULL;
 | 
						|
    pPicture->clientClipType = CT_NONE;
 | 
						|
}    
 | 
						|
 | 
						|
int
 | 
						|
miChangePictureClip (PicturePtr    pPicture,
 | 
						|
		     int	   type,
 | 
						|
		     pointer	   value,
 | 
						|
		     int	   n)
 | 
						|
{
 | 
						|
    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
 | 
						|
    PictureScreenPtr    ps = GetPictureScreen(pScreen);
 | 
						|
    pointer		clientClip;
 | 
						|
    int			clientClipType;
 | 
						|
    
 | 
						|
    switch (type) {
 | 
						|
    case CT_PIXMAP:
 | 
						|
	/* convert the pixmap to a region */
 | 
						|
	clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value);
 | 
						|
	if (!clientClip)
 | 
						|
	    return BadAlloc;
 | 
						|
	clientClipType = CT_REGION;
 | 
						|
	(*pScreen->DestroyPixmap) ((PixmapPtr) value);
 | 
						|
	break;
 | 
						|
    case CT_REGION:
 | 
						|
	clientClip = value;
 | 
						|
	clientClipType = CT_REGION;
 | 
						|
	break;
 | 
						|
    case CT_NONE:
 | 
						|
	clientClip = 0;
 | 
						|
	clientClipType = CT_NONE;
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	clientClip = (pointer) RECTS_TO_REGION(pScreen, n,
 | 
						|
					       (xRectangle *) value,
 | 
						|
					       type);
 | 
						|
	if (!clientClip)
 | 
						|
	    return BadAlloc;
 | 
						|
	clientClipType = CT_REGION;
 | 
						|
	xfree(value);
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    (*ps->DestroyPictureClip) (pPicture);
 | 
						|
    pPicture->clientClip = clientClip;
 | 
						|
    pPicture->clientClipType = clientClipType;
 | 
						|
    pPicture->stateChanges |= CPClipMask;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miChangePicture (PicturePtr pPicture,
 | 
						|
		 Mask       mask)
 | 
						|
{
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miValidatePicture (PicturePtr pPicture,
 | 
						|
		   Mask       mask)
 | 
						|
{
 | 
						|
    DrawablePtr	    pDrawable = pPicture->pDrawable;
 | 
						|
 | 
						|
    if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
 | 
						|
	(pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
 | 
						|
    {
 | 
						|
	if (pDrawable->type == DRAWABLE_WINDOW)
 | 
						|
	{
 | 
						|
	    WindowPtr       pWin = (WindowPtr) pDrawable;
 | 
						|
	    RegionPtr       pregWin;
 | 
						|
	    Bool            freeTmpClip, freeCompClip;
 | 
						|
 | 
						|
	    if (pPicture->subWindowMode == IncludeInferiors)
 | 
						|
	    {
 | 
						|
		pregWin = NotClippedByChildren(pWin);
 | 
						|
		freeTmpClip = TRUE;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pregWin = &pWin->clipList;
 | 
						|
		freeTmpClip = FALSE;
 | 
						|
	    }
 | 
						|
	    freeCompClip = pPicture->freeCompClip;
 | 
						|
 | 
						|
	    /*
 | 
						|
	     * if there is no client clip, we can get by with just keeping the
 | 
						|
	     * pointer we got, and remembering whether or not should destroy
 | 
						|
	     * (or maybe re-use) it later.  this way, we avoid unnecessary
 | 
						|
	     * copying of regions.  (this wins especially if many clients clip
 | 
						|
	     * by children and have no client clip.)
 | 
						|
	     */
 | 
						|
	    if (pPicture->clientClipType == CT_NONE)
 | 
						|
	    {
 | 
						|
		if (freeCompClip)
 | 
						|
		    REGION_DESTROY(pScreen, pPicture->pCompositeClip);
 | 
						|
		pPicture->pCompositeClip = pregWin;
 | 
						|
		pPicture->freeCompClip = freeTmpClip;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		/*
 | 
						|
		 * we need one 'real' region to put into the composite clip. if
 | 
						|
		 * pregWin the current composite clip are real, we can get rid of
 | 
						|
		 * one. if pregWin is real and the current composite clip isn't,
 | 
						|
		 * use pregWin for the composite clip. if the current composite
 | 
						|
		 * clip is real and pregWin isn't, use the current composite
 | 
						|
		 * clip. if neither is real, create a new region.
 | 
						|
		 */
 | 
						|
 | 
						|
		REGION_TRANSLATE(pScreen, pPicture->clientClip,
 | 
						|
				 pDrawable->x + pPicture->clipOrigin.x,
 | 
						|
				 pDrawable->y + pPicture->clipOrigin.y);
 | 
						|
 | 
						|
		if (freeCompClip)
 | 
						|
		{
 | 
						|
		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
 | 
						|
				     pregWin, pPicture->clientClip);
 | 
						|
		    if (freeTmpClip)
 | 
						|
			REGION_DESTROY(pScreen, pregWin);
 | 
						|
		}
 | 
						|
		else if (freeTmpClip)
 | 
						|
		{
 | 
						|
		    REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip);
 | 
						|
		    pPicture->pCompositeClip = pregWin;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
		    pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
 | 
						|
		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
 | 
						|
				     pregWin, pPicture->clientClip);
 | 
						|
		}
 | 
						|
		pPicture->freeCompClip = TRUE;
 | 
						|
		REGION_TRANSLATE(pScreen, pPicture->clientClip,
 | 
						|
				 -(pDrawable->x + pPicture->clipOrigin.x),
 | 
						|
				 -(pDrawable->y + pPicture->clipOrigin.y));
 | 
						|
	    }
 | 
						|
	}	/* end of composite clip for a window */
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    BoxRec          pixbounds;
 | 
						|
 | 
						|
	    /* XXX should we translate by drawable.x/y here ? */
 | 
						|
	    /* If you want pixmaps in offscreen memory, yes */
 | 
						|
	    pixbounds.x1 = pDrawable->x;
 | 
						|
	    pixbounds.y1 = pDrawable->y;
 | 
						|
	    pixbounds.x2 = pDrawable->x + pDrawable->width;
 | 
						|
	    pixbounds.y2 = pDrawable->y + pDrawable->height;
 | 
						|
 | 
						|
	    if (pPicture->freeCompClip)
 | 
						|
	    {
 | 
						|
		REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds);
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pPicture->freeCompClip = TRUE;
 | 
						|
		pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1);
 | 
						|
	    }
 | 
						|
 | 
						|
	    if (pPicture->clientClipType == CT_REGION)
 | 
						|
	    {
 | 
						|
		if(pDrawable->x || pDrawable->y) {
 | 
						|
		    REGION_TRANSLATE(pScreen, pPicture->clientClip,
 | 
						|
				     pDrawable->x + pPicture->clipOrigin.x, 
 | 
						|
				     pDrawable->y + pPicture->clipOrigin.y);
 | 
						|
		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
 | 
						|
				     pPicture->pCompositeClip, pPicture->clientClip);
 | 
						|
		    REGION_TRANSLATE(pScreen, pPicture->clientClip,
 | 
						|
				     -(pDrawable->x + pPicture->clipOrigin.x), 
 | 
						|
				     -(pDrawable->y + pPicture->clipOrigin.y));
 | 
						|
		} else {
 | 
						|
		    REGION_TRANSLATE(pScreen, pPicture->pCompositeClip,
 | 
						|
				     -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
 | 
						|
		    REGION_INTERSECT(pScreen, pPicture->pCompositeClip,
 | 
						|
				     pPicture->pCompositeClip, pPicture->clientClip);
 | 
						|
		    REGION_TRANSLATE(pScreen, pPicture->pCompositeClip,
 | 
						|
				     pPicture->clipOrigin.x, pPicture->clipOrigin.y);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}	/* end of composite clip for pixmap */
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
miChangePictureTransform (PicturePtr	pPicture,
 | 
						|
			  PictTransform *transform)
 | 
						|
{
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
miChangePictureFilter (PicturePtr pPicture,
 | 
						|
		       int	  filter,
 | 
						|
		       xFixed     *params,
 | 
						|
		       int	  nparams)
 | 
						|
{
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
#define BOUND(v)	(INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
 | 
						|
 | 
						|
static inline pixman_bool_t
 | 
						|
miClipPictureReg (pixman_region16_t *	pRegion,
 | 
						|
		  pixman_region16_t *	pClip,
 | 
						|
		  int		dx,
 | 
						|
		  int		dy)
 | 
						|
{
 | 
						|
    if (pixman_region_n_rects(pRegion) == 1 &&
 | 
						|
	pixman_region_n_rects(pClip) == 1)
 | 
						|
    {
 | 
						|
	pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
 | 
						|
	pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
 | 
						|
	int	v;
 | 
						|
	
 | 
						|
	if (pRbox->x1 < (v = pCbox->x1 + dx))
 | 
						|
	    pRbox->x1 = BOUND(v);
 | 
						|
	if (pRbox->x2 > (v = pCbox->x2 + dx))
 | 
						|
	    pRbox->x2 = BOUND(v);
 | 
						|
	if (pRbox->y1 < (v = pCbox->y1 + dy))
 | 
						|
	    pRbox->y1 = BOUND(v);
 | 
						|
	if (pRbox->y2 > (v = pCbox->y2 + dy))
 | 
						|
	    pRbox->y2 = BOUND(v);
 | 
						|
	if (pRbox->x1 >= pRbox->x2 ||
 | 
						|
	    pRbox->y1 >= pRbox->y2)
 | 
						|
	{
 | 
						|
	    pixman_region_init (pRegion);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else if (!pixman_region_not_empty (pClip))
 | 
						|
	return FALSE;
 | 
						|
    else
 | 
						|
    {
 | 
						|
	if (dx || dy)
 | 
						|
	    pixman_region_translate (pRegion, -dx, -dy);
 | 
						|
	if (!pixman_region_intersect (pRegion, pRegion, pClip))
 | 
						|
	    return FALSE;
 | 
						|
	if (dx || dy)
 | 
						|
	    pixman_region_translate(pRegion, dx, dy);
 | 
						|
    }
 | 
						|
    return pixman_region_not_empty(pRegion);
 | 
						|
}
 | 
						|
 | 
						|
static __inline Bool
 | 
						|
miClipPictureSrc (RegionPtr	pRegion,
 | 
						|
		  PicturePtr	pPicture,
 | 
						|
		  int		dx,
 | 
						|
		  int		dy)
 | 
						|
{
 | 
						|
    /* XXX what to do with clipping from transformed pictures? */
 | 
						|
    if (pPicture->transform || !pPicture->pDrawable)
 | 
						|
	return TRUE;
 | 
						|
    if (pPicture->repeat)
 | 
						|
    {
 | 
						|
	if (pPicture->clientClipType != CT_NONE)
 | 
						|
	{
 | 
						|
	    pixman_region_translate ( pRegion, 
 | 
						|
			     dx - pPicture->clipOrigin.x,
 | 
						|
			     dy - pPicture->clipOrigin.y);
 | 
						|
	    if (!REGION_INTERSECT (pScreen, pRegion, pRegion, 
 | 
						|
				   (RegionPtr) pPicture->pCompositeClip)) // clientClip))
 | 
						|
		return FALSE;
 | 
						|
	    pixman_region_translate ( pRegion, 
 | 
						|
			     - (dx - pPicture->clipOrigin.x),
 | 
						|
			     - (dy - pPicture->clipOrigin.y));
 | 
						|
	}
 | 
						|
	return TRUE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	return miClipPictureReg (pRegion,
 | 
						|
				 pPicture->pCompositeClip,
 | 
						|
				 dx,
 | 
						|
				 dy);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miCompositeSourceValidate (PicturePtr	pPicture,
 | 
						|
			   INT16	x,
 | 
						|
			   INT16	y,
 | 
						|
			   CARD16	width,
 | 
						|
			   CARD16	height)
 | 
						|
{
 | 
						|
    DrawablePtr	pDrawable = pPicture->pDrawable;
 | 
						|
    ScreenPtr	pScreen;
 | 
						|
 | 
						|
    if (!pDrawable)
 | 
						|
        return;
 | 
						|
 | 
						|
    pScreen = pDrawable->pScreen;
 | 
						|
    
 | 
						|
    if (pScreen->SourceValidate)
 | 
						|
    {
 | 
						|
        x -= pPicture->pDrawable->x;
 | 
						|
        y -= pPicture->pDrawable->y;
 | 
						|
	if (pPicture->transform)
 | 
						|
	{
 | 
						|
	    xPoint	    points[4];
 | 
						|
	    int		    i;
 | 
						|
	    int		    xmin, ymin, xmax, ymax;
 | 
						|
 | 
						|
#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
 | 
						|
	    VectorSet (0, x, y);
 | 
						|
	    VectorSet (1, x + width, y);
 | 
						|
	    VectorSet (2, x, y + height);
 | 
						|
	    VectorSet (3, x + width, y + height);
 | 
						|
	    xmin = ymin = 32767;
 | 
						|
	    xmax = ymax = -32737;
 | 
						|
	    for (i = 0; i < 4; i++)
 | 
						|
	    {
 | 
						|
		PictVector  t;
 | 
						|
		t.vector[0] = IntToxFixed (points[i].x);
 | 
						|
		t.vector[1] = IntToxFixed (points[i].y);
 | 
						|
		t.vector[2] = xFixed1;
 | 
						|
		if (pixman_transform_point (pPicture->transform, &t))
 | 
						|
		{
 | 
						|
		    int	tx = xFixedToInt (t.vector[0]);
 | 
						|
		    int ty = xFixedToInt (t.vector[1]);
 | 
						|
		    if (tx < xmin) xmin = tx;
 | 
						|
		    if (tx > xmax) xmax = tx;
 | 
						|
		    if (ty < ymin) ymin = ty;
 | 
						|
		    if (ty > ymax) ymax = ty;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    x = xmin;
 | 
						|
	    y = ymin;
 | 
						|
	    width = xmax - xmin;
 | 
						|
	    height = ymax - ymin;
 | 
						|
	}
 | 
						|
	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * returns FALSE if the final region is empty.  Indistinguishable from
 | 
						|
 * an allocation failure, but rendering ignores those anyways.
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
miComputeCompositeRegion (RegionPtr	pRegion,
 | 
						|
			  PicturePtr	pSrc,
 | 
						|
			  PicturePtr	pMask,
 | 
						|
			  PicturePtr	pDst,
 | 
						|
			  INT16		xSrc,
 | 
						|
			  INT16		ySrc,
 | 
						|
			  INT16		xMask,
 | 
						|
			  INT16		yMask,
 | 
						|
			  INT16		xDst,
 | 
						|
			  INT16		yDst,
 | 
						|
			  CARD16	width,
 | 
						|
			  CARD16	height)
 | 
						|
{
 | 
						|
    
 | 
						|
    int		v;
 | 
						|
 | 
						|
    pRegion->extents.x1 = xDst;
 | 
						|
    v = xDst + width;
 | 
						|
    pRegion->extents.x2 = BOUND(v);
 | 
						|
    pRegion->extents.y1 = yDst;
 | 
						|
    v = yDst + height;
 | 
						|
    pRegion->extents.y2 = BOUND(v);
 | 
						|
    pRegion->data = 0;
 | 
						|
    /* Check for empty operation */
 | 
						|
    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
 | 
						|
	pRegion->extents.y1 >= pRegion->extents.y2)
 | 
						|
    {
 | 
						|
	pixman_region_init (pRegion);
 | 
						|
	return FALSE;
 | 
						|
    }
 | 
						|
    /* clip against dst */
 | 
						|
    if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
 | 
						|
    {
 | 
						|
	pixman_region_fini (pRegion);
 | 
						|
	return FALSE;
 | 
						|
    }
 | 
						|
    if (pDst->alphaMap)
 | 
						|
    {
 | 
						|
	if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
 | 
						|
			       -pDst->alphaOrigin.x,
 | 
						|
			       -pDst->alphaOrigin.y))
 | 
						|
	{
 | 
						|
	    pixman_region_fini (pRegion);
 | 
						|
	    return FALSE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /* clip against src */
 | 
						|
    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
 | 
						|
    {
 | 
						|
	pixman_region_fini (pRegion);
 | 
						|
	return FALSE;
 | 
						|
    }
 | 
						|
    if (pSrc->alphaMap)
 | 
						|
    {
 | 
						|
	if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
 | 
						|
			       xDst - (xSrc + pSrc->alphaOrigin.x),
 | 
						|
			       yDst - (ySrc + pSrc->alphaOrigin.y)))
 | 
						|
	{
 | 
						|
	    pixman_region_fini (pRegion);
 | 
						|
	    return FALSE;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /* clip against mask */
 | 
						|
    if (pMask)
 | 
						|
    {
 | 
						|
	if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
 | 
						|
	{
 | 
						|
	    pixman_region_fini (pRegion);
 | 
						|
	    return FALSE;
 | 
						|
	}	
 | 
						|
	if (pMask->alphaMap)
 | 
						|
	{
 | 
						|
	    if (!miClipPictureSrc (pRegion, pMask->alphaMap,
 | 
						|
				   xDst - (xMask + pMask->alphaOrigin.x),
 | 
						|
				   yDst - (yMask + pMask->alphaOrigin.y)))
 | 
						|
	    {
 | 
						|
		pixman_region_fini (pRegion);
 | 
						|
		return FALSE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height);
 | 
						|
    if (pMask)
 | 
						|
	miCompositeSourceValidate (pMask, xMask, yMask, width, height);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miRenderColorToPixel (PictFormatPtr format,
 | 
						|
		      xRenderColor  *color,
 | 
						|
		      CARD32	    *pixel)
 | 
						|
{
 | 
						|
    CARD32	    r, g, b, a;
 | 
						|
    miIndexedPtr    pIndexed;
 | 
						|
 | 
						|
    switch (format->type) {
 | 
						|
    case PictTypeDirect:
 | 
						|
	r = color->red >> (16 - Ones (format->direct.redMask));
 | 
						|
	g = color->green >> (16 - Ones (format->direct.greenMask));
 | 
						|
	b = color->blue >> (16 - Ones (format->direct.blueMask));
 | 
						|
	a = color->alpha >> (16 - Ones (format->direct.alphaMask));
 | 
						|
	r = r << format->direct.red;
 | 
						|
	g = g << format->direct.green;
 | 
						|
	b = b << format->direct.blue;
 | 
						|
	a = a << format->direct.alpha;
 | 
						|
	*pixel = r|g|b|a;
 | 
						|
	break;
 | 
						|
    case PictTypeIndexed:
 | 
						|
	pIndexed = (miIndexedPtr) (format->index.devPrivate);
 | 
						|
	if (pIndexed->color)
 | 
						|
	{
 | 
						|
	    r = color->red >> 11;
 | 
						|
	    g = color->green >> 11;
 | 
						|
	    b = color->blue >> 11;
 | 
						|
	    *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    r = color->red >> 8;
 | 
						|
	    g = color->green >> 8;
 | 
						|
	    b = color->blue >> 8;
 | 
						|
	    *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
 | 
						|
	}
 | 
						|
	break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static CARD16
 | 
						|
miFillColor (CARD32 pixel, int bits)
 | 
						|
{
 | 
						|
    while (bits < 16)
 | 
						|
    {
 | 
						|
	pixel |= pixel << bits;
 | 
						|
	bits <<= 1;
 | 
						|
    }
 | 
						|
    return (CARD16) pixel;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
miIsSolidAlpha (PicturePtr pSrc)
 | 
						|
{
 | 
						|
    ScreenPtr	pScreen;
 | 
						|
    char	line[1];
 | 
						|
 | 
						|
    if (!pSrc->pDrawable)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    pScreen = pSrc->pDrawable->pScreen;
 | 
						|
    
 | 
						|
    /* Alpha-only */
 | 
						|
    if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
 | 
						|
	return FALSE;
 | 
						|
    /* repeat */
 | 
						|
    if (!pSrc->repeat)
 | 
						|
	return FALSE;
 | 
						|
    /* 1x1 */
 | 
						|
    if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
 | 
						|
	return FALSE;
 | 
						|
    line[0] = 1;
 | 
						|
    (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
 | 
						|
    switch (pSrc->pDrawable->bitsPerPixel) {
 | 
						|
    case 1:
 | 
						|
	return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
 | 
						|
    case 4:
 | 
						|
	return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
 | 
						|
    case 8:
 | 
						|
	return (CARD8) line[0] == 0xff;
 | 
						|
    default:
 | 
						|
	return FALSE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
miRenderPixelToColor (PictFormatPtr format,
 | 
						|
		      CARD32	    pixel,
 | 
						|
		      xRenderColor  *color)
 | 
						|
{
 | 
						|
    CARD32	    r, g, b, a;
 | 
						|
    miIndexedPtr    pIndexed;
 | 
						|
    
 | 
						|
    switch (format->type) {
 | 
						|
    case PictTypeDirect:
 | 
						|
	r = (pixel >> format->direct.red) & format->direct.redMask;
 | 
						|
	g = (pixel >> format->direct.green) & format->direct.greenMask;
 | 
						|
	b = (pixel >> format->direct.blue) & format->direct.blueMask;
 | 
						|
	a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
 | 
						|
	color->red = miFillColor (r, Ones (format->direct.redMask));
 | 
						|
	color->green = miFillColor (g, Ones (format->direct.greenMask));
 | 
						|
	color->blue = miFillColor (b, Ones (format->direct.blueMask));
 | 
						|
	color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
 | 
						|
	break;
 | 
						|
    case PictTypeIndexed:
 | 
						|
	pIndexed = (miIndexedPtr) (format->index.devPrivate);
 | 
						|
	pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
 | 
						|
	r = (pixel >> 16) & 0xff;
 | 
						|
	g = (pixel >>  8) & 0xff;
 | 
						|
	b = (pixel      ) & 0xff;
 | 
						|
	color->red = miFillColor (r, 8);
 | 
						|
	color->green = miFillColor (g, 8);
 | 
						|
	color->blue = miFillColor (b, 8);
 | 
						|
	color->alpha = 0xffff;
 | 
						|
	break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
 | 
						|
{
 | 
						|
    PictureScreenPtr    ps;
 | 
						|
    
 | 
						|
    if (!PictureInit (pScreen, formats, nformats))
 | 
						|
	return FALSE;
 | 
						|
    ps = GetPictureScreen(pScreen);
 | 
						|
    ps->CreatePicture = miCreatePicture;
 | 
						|
    ps->DestroyPicture = miDestroyPicture;
 | 
						|
    ps->ChangePictureClip = miChangePictureClip;
 | 
						|
    ps->DestroyPictureClip = miDestroyPictureClip;
 | 
						|
    ps->ChangePicture = miChangePicture;
 | 
						|
    ps->ValidatePicture = miValidatePicture;
 | 
						|
    ps->InitIndexed = miInitIndexed;
 | 
						|
    ps->CloseIndexed = miCloseIndexed;
 | 
						|
    ps->UpdateIndexed = miUpdateIndexed;
 | 
						|
    ps->ChangePictureTransform = miChangePictureTransform;
 | 
						|
    ps->ChangePictureFilter = miChangePictureFilter;
 | 
						|
    ps->RealizeGlyph = miRealizeGlyph;
 | 
						|
    ps->UnrealizeGlyph = miUnrealizeGlyph;
 | 
						|
 | 
						|
    /* MI rendering routines */
 | 
						|
    ps->Composite	= 0;			/* requires DDX support */
 | 
						|
    ps->Glyphs		= miGlyphs;
 | 
						|
    ps->CompositeRects	= miCompositeRects;
 | 
						|
    ps->Trapezoids	= miTrapezoids;
 | 
						|
    ps->Triangles	= miTriangles;
 | 
						|
    ps->TriStrip	= miTriStrip;
 | 
						|
    ps->TriFan		= miTriFan;
 | 
						|
    
 | 
						|
    ps->RasterizeTrapezoid = 0;			/* requires DDX support */
 | 
						|
    ps->AddTraps	= 0;			/* requires DDX support */
 | 
						|
    ps->AddTriangles	= 0;			/* requires DDX support */
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 |