mipict.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * 305b261ecSmrg * Copyright © 1999 Keith Packard 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that 805b261ecSmrg * copyright notice and this permission notice appear in supporting 905b261ecSmrg * documentation, and that the name of Keith Packard not be used in 1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1105b261ecSmrg * specific, written prior permission. Keith Packard makes no 1205b261ecSmrg * representations about the suitability of this software for any purpose. It 1305b261ecSmrg * is provided "as is" without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2205b261ecSmrg */ 2305b261ecSmrg 2405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2505b261ecSmrg#include <dix-config.h> 2605b261ecSmrg#endif 2705b261ecSmrg 2805b261ecSmrg#include "scrnintstr.h" 2905b261ecSmrg#include "gcstruct.h" 3005b261ecSmrg#include "pixmapstr.h" 3105b261ecSmrg#include "windowstr.h" 3205b261ecSmrg#include "mi.h" 3305b261ecSmrg#include "picturestr.h" 3405b261ecSmrg#include "mipict.h" 3505b261ecSmrg 3605b261ecSmrg#ifndef __GNUC__ 3705b261ecSmrg#define __inline 3805b261ecSmrg#endif 3905b261ecSmrg 4005b261ecSmrgint 4105b261ecSmrgmiCreatePicture (PicturePtr pPicture) 4205b261ecSmrg{ 4305b261ecSmrg return Success; 4405b261ecSmrg} 4505b261ecSmrg 4605b261ecSmrgvoid 4705b261ecSmrgmiDestroyPicture (PicturePtr pPicture) 4805b261ecSmrg{ 4905b261ecSmrg if (pPicture->freeCompClip) 5005b261ecSmrg REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->pCompositeClip); 5105b261ecSmrg} 5205b261ecSmrg 5305b261ecSmrgvoid 5405b261ecSmrgmiDestroyPictureClip (PicturePtr pPicture) 5505b261ecSmrg{ 5605b261ecSmrg switch (pPicture->clientClipType) { 5705b261ecSmrg case CT_NONE: 5805b261ecSmrg return; 5905b261ecSmrg case CT_PIXMAP: 6005b261ecSmrg (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip)); 6105b261ecSmrg break; 6205b261ecSmrg default: 6305b261ecSmrg /* 6405b261ecSmrg * we know we'll never have a list of rectangles, since ChangeClip 6505b261ecSmrg * immediately turns them into a region 6605b261ecSmrg */ 6705b261ecSmrg REGION_DESTROY(pPicture->pDrawable->pScreen, pPicture->clientClip); 6805b261ecSmrg break; 6905b261ecSmrg } 7005b261ecSmrg pPicture->clientClip = NULL; 7105b261ecSmrg pPicture->clientClipType = CT_NONE; 7205b261ecSmrg} 7305b261ecSmrg 7405b261ecSmrgint 7505b261ecSmrgmiChangePictureClip (PicturePtr pPicture, 7605b261ecSmrg int type, 7705b261ecSmrg pointer value, 7805b261ecSmrg int n) 7905b261ecSmrg{ 8005b261ecSmrg ScreenPtr pScreen = pPicture->pDrawable->pScreen; 8105b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 8205b261ecSmrg pointer clientClip; 8305b261ecSmrg int clientClipType; 8405b261ecSmrg 8505b261ecSmrg switch (type) { 8605b261ecSmrg case CT_PIXMAP: 8705b261ecSmrg /* convert the pixmap to a region */ 8805b261ecSmrg clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value); 8905b261ecSmrg if (!clientClip) 9005b261ecSmrg return BadAlloc; 9105b261ecSmrg clientClipType = CT_REGION; 9205b261ecSmrg (*pScreen->DestroyPixmap) ((PixmapPtr) value); 9305b261ecSmrg break; 9405b261ecSmrg case CT_REGION: 9505b261ecSmrg clientClip = value; 9605b261ecSmrg clientClipType = CT_REGION; 9705b261ecSmrg break; 9805b261ecSmrg case CT_NONE: 9905b261ecSmrg clientClip = 0; 10005b261ecSmrg clientClipType = CT_NONE; 10105b261ecSmrg break; 10205b261ecSmrg default: 10305b261ecSmrg clientClip = (pointer) RECTS_TO_REGION(pScreen, n, 10405b261ecSmrg (xRectangle *) value, 10505b261ecSmrg type); 10605b261ecSmrg if (!clientClip) 10705b261ecSmrg return BadAlloc; 10805b261ecSmrg clientClipType = CT_REGION; 10905b261ecSmrg xfree(value); 11005b261ecSmrg break; 11105b261ecSmrg } 11205b261ecSmrg (*ps->DestroyPictureClip) (pPicture); 11305b261ecSmrg pPicture->clientClip = clientClip; 11405b261ecSmrg pPicture->clientClipType = clientClipType; 11505b261ecSmrg pPicture->stateChanges |= CPClipMask; 11605b261ecSmrg return Success; 11705b261ecSmrg} 11805b261ecSmrg 11905b261ecSmrgvoid 12005b261ecSmrgmiChangePicture (PicturePtr pPicture, 12105b261ecSmrg Mask mask) 12205b261ecSmrg{ 12305b261ecSmrg return; 12405b261ecSmrg} 12505b261ecSmrg 12605b261ecSmrgvoid 12705b261ecSmrgmiValidatePicture (PicturePtr pPicture, 12805b261ecSmrg Mask mask) 12905b261ecSmrg{ 13005b261ecSmrg DrawablePtr pDrawable = pPicture->pDrawable; 13105b261ecSmrg 13205b261ecSmrg if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) || 13305b261ecSmrg (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) 13405b261ecSmrg { 13505b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) 13605b261ecSmrg { 13705b261ecSmrg WindowPtr pWin = (WindowPtr) pDrawable; 13805b261ecSmrg RegionPtr pregWin; 13905b261ecSmrg Bool freeTmpClip, freeCompClip; 14005b261ecSmrg 14105b261ecSmrg if (pPicture->subWindowMode == IncludeInferiors) 14205b261ecSmrg { 14305b261ecSmrg pregWin = NotClippedByChildren(pWin); 14405b261ecSmrg freeTmpClip = TRUE; 14505b261ecSmrg } 14605b261ecSmrg else 14705b261ecSmrg { 14805b261ecSmrg pregWin = &pWin->clipList; 14905b261ecSmrg freeTmpClip = FALSE; 15005b261ecSmrg } 15105b261ecSmrg freeCompClip = pPicture->freeCompClip; 15205b261ecSmrg 15305b261ecSmrg /* 15405b261ecSmrg * if there is no client clip, we can get by with just keeping the 15505b261ecSmrg * pointer we got, and remembering whether or not should destroy 15605b261ecSmrg * (or maybe re-use) it later. this way, we avoid unnecessary 15705b261ecSmrg * copying of regions. (this wins especially if many clients clip 15805b261ecSmrg * by children and have no client clip.) 15905b261ecSmrg */ 16005b261ecSmrg if (pPicture->clientClipType == CT_NONE) 16105b261ecSmrg { 16205b261ecSmrg if (freeCompClip) 16305b261ecSmrg REGION_DESTROY(pScreen, pPicture->pCompositeClip); 16405b261ecSmrg pPicture->pCompositeClip = pregWin; 16505b261ecSmrg pPicture->freeCompClip = freeTmpClip; 16605b261ecSmrg } 16705b261ecSmrg else 16805b261ecSmrg { 16905b261ecSmrg /* 17005b261ecSmrg * we need one 'real' region to put into the composite clip. if 17105b261ecSmrg * pregWin the current composite clip are real, we can get rid of 17205b261ecSmrg * one. if pregWin is real and the current composite clip isn't, 17305b261ecSmrg * use pregWin for the composite clip. if the current composite 17405b261ecSmrg * clip is real and pregWin isn't, use the current composite 17505b261ecSmrg * clip. if neither is real, create a new region. 17605b261ecSmrg */ 17705b261ecSmrg 17805b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->clientClip, 17905b261ecSmrg pDrawable->x + pPicture->clipOrigin.x, 18005b261ecSmrg pDrawable->y + pPicture->clipOrigin.y); 18105b261ecSmrg 18205b261ecSmrg if (freeCompClip) 18305b261ecSmrg { 18405b261ecSmrg REGION_INTERSECT(pScreen, pPicture->pCompositeClip, 18505b261ecSmrg pregWin, pPicture->clientClip); 18605b261ecSmrg if (freeTmpClip) 18705b261ecSmrg REGION_DESTROY(pScreen, pregWin); 18805b261ecSmrg } 18905b261ecSmrg else if (freeTmpClip) 19005b261ecSmrg { 19105b261ecSmrg REGION_INTERSECT(pScreen, pregWin, pregWin, pPicture->clientClip); 19205b261ecSmrg pPicture->pCompositeClip = pregWin; 19305b261ecSmrg } 19405b261ecSmrg else 19505b261ecSmrg { 19605b261ecSmrg pPicture->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0); 19705b261ecSmrg REGION_INTERSECT(pScreen, pPicture->pCompositeClip, 19805b261ecSmrg pregWin, pPicture->clientClip); 19905b261ecSmrg } 20005b261ecSmrg pPicture->freeCompClip = TRUE; 20105b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->clientClip, 20205b261ecSmrg -(pDrawable->x + pPicture->clipOrigin.x), 20305b261ecSmrg -(pDrawable->y + pPicture->clipOrigin.y)); 20405b261ecSmrg } 20505b261ecSmrg } /* end of composite clip for a window */ 20605b261ecSmrg else 20705b261ecSmrg { 20805b261ecSmrg BoxRec pixbounds; 20905b261ecSmrg 21005b261ecSmrg /* XXX should we translate by drawable.x/y here ? */ 21105b261ecSmrg /* If you want pixmaps in offscreen memory, yes */ 21205b261ecSmrg pixbounds.x1 = pDrawable->x; 21305b261ecSmrg pixbounds.y1 = pDrawable->y; 21405b261ecSmrg pixbounds.x2 = pDrawable->x + pDrawable->width; 21505b261ecSmrg pixbounds.y2 = pDrawable->y + pDrawable->height; 21605b261ecSmrg 21705b261ecSmrg if (pPicture->freeCompClip) 21805b261ecSmrg { 21905b261ecSmrg REGION_RESET(pScreen, pPicture->pCompositeClip, &pixbounds); 22005b261ecSmrg } 22105b261ecSmrg else 22205b261ecSmrg { 22305b261ecSmrg pPicture->freeCompClip = TRUE; 22405b261ecSmrg pPicture->pCompositeClip = REGION_CREATE(pScreen, &pixbounds, 1); 22505b261ecSmrg } 22605b261ecSmrg 22705b261ecSmrg if (pPicture->clientClipType == CT_REGION) 22805b261ecSmrg { 22905b261ecSmrg if(pDrawable->x || pDrawable->y) { 23005b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->clientClip, 23105b261ecSmrg pDrawable->x + pPicture->clipOrigin.x, 23205b261ecSmrg pDrawable->y + pPicture->clipOrigin.y); 23305b261ecSmrg REGION_INTERSECT(pScreen, pPicture->pCompositeClip, 23405b261ecSmrg pPicture->pCompositeClip, pPicture->clientClip); 23505b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->clientClip, 23605b261ecSmrg -(pDrawable->x + pPicture->clipOrigin.x), 23705b261ecSmrg -(pDrawable->y + pPicture->clipOrigin.y)); 23805b261ecSmrg } else { 23905b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, 24005b261ecSmrg -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); 24105b261ecSmrg REGION_INTERSECT(pScreen, pPicture->pCompositeClip, 24205b261ecSmrg pPicture->pCompositeClip, pPicture->clientClip); 24305b261ecSmrg REGION_TRANSLATE(pScreen, pPicture->pCompositeClip, 24405b261ecSmrg pPicture->clipOrigin.x, pPicture->clipOrigin.y); 24505b261ecSmrg } 24605b261ecSmrg } 24705b261ecSmrg } /* end of composite clip for pixmap */ 24805b261ecSmrg } 24905b261ecSmrg} 25005b261ecSmrg 25105b261ecSmrgint 25205b261ecSmrgmiChangePictureTransform (PicturePtr pPicture, 25305b261ecSmrg PictTransform *transform) 25405b261ecSmrg{ 25505b261ecSmrg return Success; 25605b261ecSmrg} 25705b261ecSmrg 25805b261ecSmrgint 25905b261ecSmrgmiChangePictureFilter (PicturePtr pPicture, 26005b261ecSmrg int filter, 26105b261ecSmrg xFixed *params, 26205b261ecSmrg int nparams) 26305b261ecSmrg{ 26405b261ecSmrg return Success; 26505b261ecSmrg} 26605b261ecSmrg 26705b261ecSmrg#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) 26805b261ecSmrg 26905b261ecSmrgstatic inline pixman_bool_t 27005b261ecSmrgmiClipPictureReg (pixman_region16_t * pRegion, 27105b261ecSmrg pixman_region16_t * pClip, 27205b261ecSmrg int dx, 27305b261ecSmrg int dy) 27405b261ecSmrg{ 27505b261ecSmrg if (pixman_region_n_rects(pRegion) == 1 && 27605b261ecSmrg pixman_region_n_rects(pClip) == 1) 27705b261ecSmrg { 27805b261ecSmrg pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL); 27905b261ecSmrg pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL); 28005b261ecSmrg int v; 28105b261ecSmrg 28205b261ecSmrg if (pRbox->x1 < (v = pCbox->x1 + dx)) 28305b261ecSmrg pRbox->x1 = BOUND(v); 28405b261ecSmrg if (pRbox->x2 > (v = pCbox->x2 + dx)) 28505b261ecSmrg pRbox->x2 = BOUND(v); 28605b261ecSmrg if (pRbox->y1 < (v = pCbox->y1 + dy)) 28705b261ecSmrg pRbox->y1 = BOUND(v); 28805b261ecSmrg if (pRbox->y2 > (v = pCbox->y2 + dy)) 28905b261ecSmrg pRbox->y2 = BOUND(v); 29005b261ecSmrg if (pRbox->x1 >= pRbox->x2 || 29105b261ecSmrg pRbox->y1 >= pRbox->y2) 29205b261ecSmrg { 29305b261ecSmrg pixman_region_init (pRegion); 29405b261ecSmrg } 29505b261ecSmrg } 29605b261ecSmrg else if (!pixman_region_not_empty (pClip)) 29705b261ecSmrg return FALSE; 29805b261ecSmrg else 29905b261ecSmrg { 30005b261ecSmrg if (dx || dy) 30105b261ecSmrg pixman_region_translate (pRegion, -dx, -dy); 30205b261ecSmrg if (!pixman_region_intersect (pRegion, pRegion, pClip)) 30305b261ecSmrg return FALSE; 30405b261ecSmrg if (dx || dy) 30505b261ecSmrg pixman_region_translate(pRegion, dx, dy); 30605b261ecSmrg } 30705b261ecSmrg return pixman_region_not_empty(pRegion); 30805b261ecSmrg} 30905b261ecSmrg 31005b261ecSmrgstatic __inline Bool 31105b261ecSmrgmiClipPictureSrc (RegionPtr pRegion, 31205b261ecSmrg PicturePtr pPicture, 31305b261ecSmrg int dx, 31405b261ecSmrg int dy) 31505b261ecSmrg{ 31605b261ecSmrg /* XXX what to do with clipping from transformed pictures? */ 31705b261ecSmrg if (pPicture->transform || !pPicture->pDrawable) 31805b261ecSmrg return TRUE; 31905b261ecSmrg if (pPicture->repeat) 32005b261ecSmrg { 32105b261ecSmrg if (pPicture->clientClipType != CT_NONE) 32205b261ecSmrg { 32305b261ecSmrg pixman_region_translate ( pRegion, 32405b261ecSmrg dx - pPicture->clipOrigin.x, 32505b261ecSmrg dy - pPicture->clipOrigin.y); 32605b261ecSmrg if (!REGION_INTERSECT (pScreen, pRegion, pRegion, 32705b261ecSmrg (RegionPtr) pPicture->pCompositeClip)) // clientClip)) 32805b261ecSmrg return FALSE; 32905b261ecSmrg pixman_region_translate ( pRegion, 33005b261ecSmrg - (dx - pPicture->clipOrigin.x), 33105b261ecSmrg - (dy - pPicture->clipOrigin.y)); 33205b261ecSmrg } 33305b261ecSmrg return TRUE; 33405b261ecSmrg } 33505b261ecSmrg else 33605b261ecSmrg { 33705b261ecSmrg return miClipPictureReg (pRegion, 33805b261ecSmrg pPicture->pCompositeClip, 33905b261ecSmrg dx, 34005b261ecSmrg dy); 34105b261ecSmrg } 34205b261ecSmrg} 34305b261ecSmrg 34405b261ecSmrgvoid 34505b261ecSmrgmiCompositeSourceValidate (PicturePtr pPicture, 34605b261ecSmrg INT16 x, 34705b261ecSmrg INT16 y, 34805b261ecSmrg CARD16 width, 34905b261ecSmrg CARD16 height) 35005b261ecSmrg{ 35105b261ecSmrg DrawablePtr pDrawable = pPicture->pDrawable; 35205b261ecSmrg ScreenPtr pScreen; 35305b261ecSmrg 35405b261ecSmrg if (!pDrawable) 35505b261ecSmrg return; 35605b261ecSmrg 35705b261ecSmrg pScreen = pDrawable->pScreen; 35805b261ecSmrg 35905b261ecSmrg if (pScreen->SourceValidate) 36005b261ecSmrg { 36105b261ecSmrg x -= pPicture->pDrawable->x; 36205b261ecSmrg y -= pPicture->pDrawable->y; 36305b261ecSmrg if (pPicture->transform) 36405b261ecSmrg { 36505b261ecSmrg xPoint points[4]; 36605b261ecSmrg int i; 36705b261ecSmrg int xmin, ymin, xmax, ymax; 36805b261ecSmrg 36905b261ecSmrg#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; } 37005b261ecSmrg VectorSet (0, x, y); 37105b261ecSmrg VectorSet (1, x + width, y); 37205b261ecSmrg VectorSet (2, x, y + height); 37305b261ecSmrg VectorSet (3, x + width, y + height); 37405b261ecSmrg xmin = ymin = 32767; 37505b261ecSmrg xmax = ymax = -32737; 37605b261ecSmrg for (i = 0; i < 4; i++) 37705b261ecSmrg { 37805b261ecSmrg PictVector t; 37905b261ecSmrg t.vector[0] = IntToxFixed (points[i].x); 38005b261ecSmrg t.vector[1] = IntToxFixed (points[i].y); 38105b261ecSmrg t.vector[2] = xFixed1; 38205b261ecSmrg if (PictureTransformPoint (pPicture->transform, &t)) 38305b261ecSmrg { 38405b261ecSmrg int tx = xFixedToInt (t.vector[0]); 38505b261ecSmrg int ty = xFixedToInt (t.vector[1]); 38605b261ecSmrg if (tx < xmin) xmin = tx; 38705b261ecSmrg if (tx > xmax) xmax = tx; 38805b261ecSmrg if (ty < ymin) ymin = ty; 38905b261ecSmrg if (ty > ymax) ymax = ty; 39005b261ecSmrg } 39105b261ecSmrg } 39205b261ecSmrg x = xmin; 39305b261ecSmrg y = ymin; 39405b261ecSmrg width = xmax - xmin; 39505b261ecSmrg height = ymax - ymin; 39605b261ecSmrg } 39705b261ecSmrg (*pScreen->SourceValidate) (pDrawable, x, y, width, height); 39805b261ecSmrg } 39905b261ecSmrg} 40005b261ecSmrg 40105b261ecSmrg/* 40205b261ecSmrg * returns FALSE if the final region is empty. Indistinguishable from 40305b261ecSmrg * an allocation failure, but rendering ignores those anyways. 40405b261ecSmrg */ 40505b261ecSmrg 40605b261ecSmrg_X_EXPORT Bool 40705b261ecSmrgmiComputeCompositeRegion (RegionPtr pRegion, 40805b261ecSmrg PicturePtr pSrc, 40905b261ecSmrg PicturePtr pMask, 41005b261ecSmrg PicturePtr pDst, 41105b261ecSmrg INT16 xSrc, 41205b261ecSmrg INT16 ySrc, 41305b261ecSmrg INT16 xMask, 41405b261ecSmrg INT16 yMask, 41505b261ecSmrg INT16 xDst, 41605b261ecSmrg INT16 yDst, 41705b261ecSmrg CARD16 width, 41805b261ecSmrg CARD16 height) 41905b261ecSmrg{ 42005b261ecSmrg 42105b261ecSmrg int v; 42205b261ecSmrg 42305b261ecSmrg pRegion->extents.x1 = xDst; 42405b261ecSmrg v = xDst + width; 42505b261ecSmrg pRegion->extents.x2 = BOUND(v); 42605b261ecSmrg pRegion->extents.y1 = yDst; 42705b261ecSmrg v = yDst + height; 42805b261ecSmrg pRegion->extents.y2 = BOUND(v); 42905b261ecSmrg pRegion->data = 0; 43005b261ecSmrg /* Check for empty operation */ 43105b261ecSmrg if (pRegion->extents.x1 >= pRegion->extents.x2 || 43205b261ecSmrg pRegion->extents.y1 >= pRegion->extents.y2) 43305b261ecSmrg { 43405b261ecSmrg pixman_region_init (pRegion); 43505b261ecSmrg return FALSE; 43605b261ecSmrg } 43705b261ecSmrg /* clip against dst */ 43805b261ecSmrg if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) 43905b261ecSmrg { 44005b261ecSmrg pixman_region_fini (pRegion); 44105b261ecSmrg return FALSE; 44205b261ecSmrg } 44305b261ecSmrg if (pDst->alphaMap) 44405b261ecSmrg { 44505b261ecSmrg if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, 44605b261ecSmrg -pDst->alphaOrigin.x, 44705b261ecSmrg -pDst->alphaOrigin.y)) 44805b261ecSmrg { 44905b261ecSmrg pixman_region_fini (pRegion); 45005b261ecSmrg return FALSE; 45105b261ecSmrg } 45205b261ecSmrg } 45305b261ecSmrg /* clip against src */ 45405b261ecSmrg if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) 45505b261ecSmrg { 45605b261ecSmrg pixman_region_fini (pRegion); 45705b261ecSmrg return FALSE; 45805b261ecSmrg } 45905b261ecSmrg if (pSrc->alphaMap) 46005b261ecSmrg { 46105b261ecSmrg if (!miClipPictureSrc (pRegion, pSrc->alphaMap, 46205b261ecSmrg xDst - (xSrc + pSrc->alphaOrigin.x), 46305b261ecSmrg yDst - (ySrc + pSrc->alphaOrigin.y))) 46405b261ecSmrg { 46505b261ecSmrg pixman_region_fini (pRegion); 46605b261ecSmrg return FALSE; 46705b261ecSmrg } 46805b261ecSmrg } 46905b261ecSmrg /* clip against mask */ 47005b261ecSmrg if (pMask) 47105b261ecSmrg { 47205b261ecSmrg if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) 47305b261ecSmrg { 47405b261ecSmrg pixman_region_fini (pRegion); 47505b261ecSmrg return FALSE; 47605b261ecSmrg } 47705b261ecSmrg if (pMask->alphaMap) 47805b261ecSmrg { 47905b261ecSmrg if (!miClipPictureSrc (pRegion, pMask->alphaMap, 48005b261ecSmrg xDst - (xMask + pMask->alphaOrigin.x), 48105b261ecSmrg yDst - (yMask + pMask->alphaOrigin.y))) 48205b261ecSmrg { 48305b261ecSmrg pixman_region_fini (pRegion); 48405b261ecSmrg return FALSE; 48505b261ecSmrg } 48605b261ecSmrg } 48705b261ecSmrg } 48805b261ecSmrg 48905b261ecSmrg 49005b261ecSmrg miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); 49105b261ecSmrg if (pMask) 49205b261ecSmrg miCompositeSourceValidate (pMask, xMask, yMask, width, height); 49305b261ecSmrg 49405b261ecSmrg return TRUE; 49505b261ecSmrg} 49605b261ecSmrg 49705b261ecSmrgvoid 49805b261ecSmrgmiRenderColorToPixel (PictFormatPtr format, 49905b261ecSmrg xRenderColor *color, 50005b261ecSmrg CARD32 *pixel) 50105b261ecSmrg{ 50205b261ecSmrg CARD32 r, g, b, a; 50305b261ecSmrg miIndexedPtr pIndexed; 50405b261ecSmrg 50505b261ecSmrg switch (format->type) { 50605b261ecSmrg case PictTypeDirect: 50705b261ecSmrg r = color->red >> (16 - Ones (format->direct.redMask)); 50805b261ecSmrg g = color->green >> (16 - Ones (format->direct.greenMask)); 50905b261ecSmrg b = color->blue >> (16 - Ones (format->direct.blueMask)); 51005b261ecSmrg a = color->alpha >> (16 - Ones (format->direct.alphaMask)); 51105b261ecSmrg r = r << format->direct.red; 51205b261ecSmrg g = g << format->direct.green; 51305b261ecSmrg b = b << format->direct.blue; 51405b261ecSmrg a = a << format->direct.alpha; 51505b261ecSmrg *pixel = r|g|b|a; 51605b261ecSmrg break; 51705b261ecSmrg case PictTypeIndexed: 51805b261ecSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 51905b261ecSmrg if (pIndexed->color) 52005b261ecSmrg { 52105b261ecSmrg r = color->red >> 11; 52205b261ecSmrg g = color->green >> 11; 52305b261ecSmrg b = color->blue >> 11; 52405b261ecSmrg *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); 52505b261ecSmrg } 52605b261ecSmrg else 52705b261ecSmrg { 52805b261ecSmrg r = color->red >> 8; 52905b261ecSmrg g = color->green >> 8; 53005b261ecSmrg b = color->blue >> 8; 53105b261ecSmrg *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); 53205b261ecSmrg } 53305b261ecSmrg break; 53405b261ecSmrg } 53505b261ecSmrg} 53605b261ecSmrg 53705b261ecSmrgstatic CARD16 53805b261ecSmrgmiFillColor (CARD32 pixel, int bits) 53905b261ecSmrg{ 54005b261ecSmrg while (bits < 16) 54105b261ecSmrg { 54205b261ecSmrg pixel |= pixel << bits; 54305b261ecSmrg bits <<= 1; 54405b261ecSmrg } 54505b261ecSmrg return (CARD16) pixel; 54605b261ecSmrg} 54705b261ecSmrg 54805b261ecSmrgBool 54905b261ecSmrgmiIsSolidAlpha (PicturePtr pSrc) 55005b261ecSmrg{ 55105b261ecSmrg ScreenPtr pScreen; 55205b261ecSmrg char line[1]; 55305b261ecSmrg 55405b261ecSmrg if (!pSrc->pDrawable) 55505b261ecSmrg return FALSE; 55605b261ecSmrg 55705b261ecSmrg pScreen = pSrc->pDrawable->pScreen; 55805b261ecSmrg 55905b261ecSmrg /* Alpha-only */ 56005b261ecSmrg if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) 56105b261ecSmrg return FALSE; 56205b261ecSmrg /* repeat */ 56305b261ecSmrg if (!pSrc->repeat) 56405b261ecSmrg return FALSE; 56505b261ecSmrg /* 1x1 */ 56605b261ecSmrg if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) 56705b261ecSmrg return FALSE; 56805b261ecSmrg line[0] = 1; 56905b261ecSmrg (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); 57005b261ecSmrg switch (pSrc->pDrawable->bitsPerPixel) { 57105b261ecSmrg case 1: 57205b261ecSmrg return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; 57305b261ecSmrg case 4: 57405b261ecSmrg return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; 57505b261ecSmrg case 8: 57605b261ecSmrg return (CARD8) line[0] == 0xff; 57705b261ecSmrg default: 57805b261ecSmrg return FALSE; 57905b261ecSmrg } 58005b261ecSmrg} 58105b261ecSmrg 58205b261ecSmrgvoid 58305b261ecSmrgmiRenderPixelToColor (PictFormatPtr format, 58405b261ecSmrg CARD32 pixel, 58505b261ecSmrg xRenderColor *color) 58605b261ecSmrg{ 58705b261ecSmrg CARD32 r, g, b, a; 58805b261ecSmrg miIndexedPtr pIndexed; 58905b261ecSmrg 59005b261ecSmrg switch (format->type) { 59105b261ecSmrg case PictTypeDirect: 59205b261ecSmrg r = (pixel >> format->direct.red) & format->direct.redMask; 59305b261ecSmrg g = (pixel >> format->direct.green) & format->direct.greenMask; 59405b261ecSmrg b = (pixel >> format->direct.blue) & format->direct.blueMask; 59505b261ecSmrg a = (pixel >> format->direct.alpha) & format->direct.alphaMask; 59605b261ecSmrg color->red = miFillColor (r, Ones (format->direct.redMask)); 59705b261ecSmrg color->green = miFillColor (g, Ones (format->direct.greenMask)); 59805b261ecSmrg color->blue = miFillColor (b, Ones (format->direct.blueMask)); 59905b261ecSmrg color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); 60005b261ecSmrg break; 60105b261ecSmrg case PictTypeIndexed: 60205b261ecSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 60305b261ecSmrg pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; 60405b261ecSmrg r = (pixel >> 16) & 0xff; 60505b261ecSmrg g = (pixel >> 8) & 0xff; 60605b261ecSmrg b = (pixel ) & 0xff; 60705b261ecSmrg color->red = miFillColor (r, 8); 60805b261ecSmrg color->green = miFillColor (g, 8); 60905b261ecSmrg color->blue = miFillColor (b, 8); 61005b261ecSmrg color->alpha = 0xffff; 61105b261ecSmrg break; 61205b261ecSmrg } 61305b261ecSmrg} 61405b261ecSmrg 61505b261ecSmrg_X_EXPORT Bool 61605b261ecSmrgmiPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) 61705b261ecSmrg{ 61805b261ecSmrg PictureScreenPtr ps; 61905b261ecSmrg 62005b261ecSmrg if (!PictureInit (pScreen, formats, nformats)) 62105b261ecSmrg return FALSE; 62205b261ecSmrg ps = GetPictureScreen(pScreen); 62305b261ecSmrg ps->CreatePicture = miCreatePicture; 62405b261ecSmrg ps->DestroyPicture = miDestroyPicture; 62505b261ecSmrg ps->ChangePictureClip = miChangePictureClip; 62605b261ecSmrg ps->DestroyPictureClip = miDestroyPictureClip; 62705b261ecSmrg ps->ChangePicture = miChangePicture; 62805b261ecSmrg ps->ValidatePicture = miValidatePicture; 62905b261ecSmrg ps->InitIndexed = miInitIndexed; 63005b261ecSmrg ps->CloseIndexed = miCloseIndexed; 63105b261ecSmrg ps->UpdateIndexed = miUpdateIndexed; 63205b261ecSmrg ps->ChangePictureTransform = miChangePictureTransform; 63305b261ecSmrg ps->ChangePictureFilter = miChangePictureFilter; 63405b261ecSmrg ps->RealizeGlyph = miRealizeGlyph; 63505b261ecSmrg ps->UnrealizeGlyph = miUnrealizeGlyph; 63605b261ecSmrg 63705b261ecSmrg /* MI rendering routines */ 63805b261ecSmrg ps->Composite = 0; /* requires DDX support */ 63905b261ecSmrg ps->Glyphs = miGlyphs; 64005b261ecSmrg ps->CompositeRects = miCompositeRects; 64105b261ecSmrg ps->Trapezoids = miTrapezoids; 64205b261ecSmrg ps->Triangles = miTriangles; 64305b261ecSmrg ps->TriStrip = miTriStrip; 64405b261ecSmrg ps->TriFan = miTriFan; 64505b261ecSmrg 64605b261ecSmrg ps->RasterizeTrapezoid = 0; /* requires DDX support */ 64705b261ecSmrg ps->AddTraps = 0; /* requires DDX support */ 64805b261ecSmrg ps->AddTriangles = 0; /* requires DDX support */ 64905b261ecSmrg 65005b261ecSmrg return TRUE; 65105b261ecSmrg} 652