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 (PictureTransformPoint (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.
 | |
|  */
 | |
| 
 | |
| _X_EXPORT 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;
 | |
|     }
 | |
| }
 | |
| 
 | |
| _X_EXPORT 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;
 | |
| }
 |