610 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			610 lines
		
	
	
		
			19 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"
 | |
| 
 | |
| int
 | |
| miCreatePicture(PicturePtr pPicture)
 | |
| {
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| void
 | |
| miDestroyPicture(PicturePtr pPicture)
 | |
| {
 | |
|     if (pPicture->freeCompClip)
 | |
|         RegionDestroy(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
 | |
|          */
 | |
|         RegionDestroy(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) BitmapToRegion(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) RegionFromRects(n, (xRectangle *) value, type);
 | |
|         if (!clientClip)
 | |
|             return BadAlloc;
 | |
|         clientClipType = CT_REGION;
 | |
|         free(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)
 | |
|                     RegionDestroy(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.
 | |
|                  */
 | |
| 
 | |
|                 RegionTranslate(pPicture->clientClip,
 | |
|                                 pDrawable->x + pPicture->clipOrigin.x,
 | |
|                                 pDrawable->y + pPicture->clipOrigin.y);
 | |
| 
 | |
|                 if (freeCompClip) {
 | |
|                     RegionIntersect(pPicture->pCompositeClip,
 | |
|                                     pregWin, pPicture->clientClip);
 | |
|                     if (freeTmpClip)
 | |
|                         RegionDestroy(pregWin);
 | |
|                 }
 | |
|                 else if (freeTmpClip) {
 | |
|                     RegionIntersect(pregWin, pregWin, pPicture->clientClip);
 | |
|                     pPicture->pCompositeClip = pregWin;
 | |
|                 }
 | |
|                 else {
 | |
|                     pPicture->pCompositeClip = RegionCreate(NullBox, 0);
 | |
|                     RegionIntersect(pPicture->pCompositeClip,
 | |
|                                     pregWin, pPicture->clientClip);
 | |
|                 }
 | |
|                 pPicture->freeCompClip = TRUE;
 | |
|                 RegionTranslate(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) {
 | |
|                 RegionReset(pPicture->pCompositeClip, &pixbounds);
 | |
|             }
 | |
|             else {
 | |
|                 pPicture->freeCompClip = TRUE;
 | |
|                 pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
 | |
|             }
 | |
| 
 | |
|             if (pPicture->clientClipType == CT_REGION) {
 | |
|                 if (pDrawable->x || pDrawable->y) {
 | |
|                     RegionTranslate(pPicture->clientClip,
 | |
|                                     pDrawable->x + pPicture->clipOrigin.x,
 | |
|                                     pDrawable->y + pPicture->clipOrigin.y);
 | |
|                     RegionIntersect(pPicture->pCompositeClip,
 | |
|                                     pPicture->pCompositeClip,
 | |
|                                     pPicture->clientClip);
 | |
|                     RegionTranslate(pPicture->clientClip,
 | |
|                                     -(pDrawable->x + pPicture->clipOrigin.x),
 | |
|                                     -(pDrawable->y + pPicture->clipOrigin.y));
 | |
|                 }
 | |
|                 else {
 | |
|                     RegionTranslate(pPicture->pCompositeClip,
 | |
|                                     -pPicture->clipOrigin.x,
 | |
|                                     -pPicture->clipOrigin.y);
 | |
|                     RegionIntersect(pPicture->pCompositeClip,
 | |
|                                     pPicture->pCompositeClip,
 | |
|                                     pPicture->clientClip);
 | |
|                     RegionTranslate(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)
 | |
| {
 | |
|     if (pPicture->clientClipType != CT_NONE) {
 | |
|         Bool result;
 | |
| 
 | |
|         pixman_region_translate(pPicture->clientClip,
 | |
|                                 pPicture->clipOrigin.x + dx,
 | |
|                                 pPicture->clipOrigin.y + dy);
 | |
| 
 | |
|         result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
 | |
| 
 | |
|         pixman_region_translate(pPicture->clientClip,
 | |
|                                 -(pPicture->clipOrigin.x + dx),
 | |
|                                 -(pPicture->clipOrigin.y + dy));
 | |
| 
 | |
|         if (!result)
 | |
|             return FALSE;
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| SourceValidateOnePicture(PicturePtr pPicture)
 | |
| {
 | |
|     DrawablePtr pDrawable = pPicture->pDrawable;
 | |
|     ScreenPtr pScreen;
 | |
| 
 | |
|     if (!pDrawable)
 | |
|         return;
 | |
| 
 | |
|     pScreen = pDrawable->pScreen;
 | |
| 
 | |
|     if (pScreen->SourceValidate) {
 | |
|         pScreen->SourceValidate(pDrawable, 0, 0, pDrawable->width,
 | |
|                                 pDrawable->height, pPicture->subWindowMode);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| miCompositeSourceValidate(PicturePtr pPicture)
 | |
| {
 | |
|     SourceValidateOnePicture(pPicture);
 | |
|     if (pPicture->alphaMap)
 | |
|         SourceValidateOnePicture(pPicture->alphaMap);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * 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);
 | |
|     if (pMask)
 | |
|         miCompositeSourceValidate(pMask);
 | |
| 
 | |
|     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;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| miTriStrip(CARD8 op,
 | |
|            PicturePtr pSrc,
 | |
|            PicturePtr pDst,
 | |
|            PictFormatPtr maskFormat,
 | |
|            INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
 | |
| {
 | |
|     xTriangle *tris, *tri;
 | |
|     int ntri;
 | |
| 
 | |
|     ntri = npoints - 2;
 | |
|     tris = malloc(ntri * sizeof(xTriangle));
 | |
|     if (!tris)
 | |
|         return;
 | |
| 
 | |
|     for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
 | |
|         tri->p1 = points[0];
 | |
|         tri->p2 = points[1];
 | |
|         tri->p3 = points[2];
 | |
|     }
 | |
|     CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
 | |
|     free(tris);
 | |
| }
 | |
| 
 | |
| void
 | |
| miTriFan(CARD8 op,
 | |
|          PicturePtr pSrc,
 | |
|          PicturePtr pDst,
 | |
|          PictFormatPtr maskFormat,
 | |
|          INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points)
 | |
| {
 | |
|     xTriangle *tris, *tri;
 | |
|     xPointFixed *first;
 | |
|     int ntri;
 | |
| 
 | |
|     ntri = npoints - 2;
 | |
|     tris = malloc(ntri * sizeof(xTriangle));
 | |
|     if (!tris)
 | |
|         return;
 | |
| 
 | |
|     first = points++;
 | |
|     for (tri = tris; npoints >= 3; npoints--, points++, tri++) {
 | |
|         tri->p1 = *first;
 | |
|         tri->p2 = points[0];
 | |
|         tri->p3 = points[1];
 | |
|     }
 | |
|     CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris);
 | |
|     free(tris);
 | |
| }
 | |
| 
 | |
| 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 = 0;
 | |
|     ps->Triangles = 0;
 | |
| 
 | |
|     ps->RasterizeTrapezoid = 0; /* requires DDX support */
 | |
|     ps->AddTraps = 0;           /* requires DDX support */
 | |
|     ps->AddTriangles = 0;       /* requires DDX support */
 | |
| 
 | |
|     ps->TriStrip = miTriStrip;  /* converts call to CompositeTriangles */
 | |
|     ps->TriFan = miTriFan;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 |