mipict.c revision 6747b715
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) 506747b715Smrg RegionDestroy(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 */ 676747b715Smrg RegionDestroy(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 */ 886747b715Smrg clientClip = (pointer) BitmapToRegion(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: 1036747b715Smrg clientClip = (pointer) RegionFromRects(n, 10405b261ecSmrg (xRectangle *) value, 10505b261ecSmrg type); 10605b261ecSmrg if (!clientClip) 10705b261ecSmrg return BadAlloc; 10805b261ecSmrg clientClipType = CT_REGION; 1096747b715Smrg free(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) 1636747b715Smrg RegionDestroy(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 1786747b715Smrg RegionTranslate(pPicture->clientClip, 17905b261ecSmrg pDrawable->x + pPicture->clipOrigin.x, 18005b261ecSmrg pDrawable->y + pPicture->clipOrigin.y); 18105b261ecSmrg 18205b261ecSmrg if (freeCompClip) 18305b261ecSmrg { 1846747b715Smrg RegionIntersect(pPicture->pCompositeClip, 18505b261ecSmrg pregWin, pPicture->clientClip); 18605b261ecSmrg if (freeTmpClip) 1876747b715Smrg RegionDestroy(pregWin); 18805b261ecSmrg } 18905b261ecSmrg else if (freeTmpClip) 19005b261ecSmrg { 1916747b715Smrg RegionIntersect(pregWin, pregWin, pPicture->clientClip); 19205b261ecSmrg pPicture->pCompositeClip = pregWin; 19305b261ecSmrg } 19405b261ecSmrg else 19505b261ecSmrg { 1966747b715Smrg pPicture->pCompositeClip = RegionCreate(NullBox, 0); 1976747b715Smrg RegionIntersect(pPicture->pCompositeClip, 19805b261ecSmrg pregWin, pPicture->clientClip); 19905b261ecSmrg } 20005b261ecSmrg pPicture->freeCompClip = TRUE; 2016747b715Smrg RegionTranslate(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 { 2196747b715Smrg RegionReset(pPicture->pCompositeClip, &pixbounds); 22005b261ecSmrg } 22105b261ecSmrg else 22205b261ecSmrg { 22305b261ecSmrg pPicture->freeCompClip = TRUE; 2246747b715Smrg pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); 22505b261ecSmrg } 22605b261ecSmrg 22705b261ecSmrg if (pPicture->clientClipType == CT_REGION) 22805b261ecSmrg { 22905b261ecSmrg if(pDrawable->x || pDrawable->y) { 2306747b715Smrg RegionTranslate(pPicture->clientClip, 23105b261ecSmrg pDrawable->x + pPicture->clipOrigin.x, 23205b261ecSmrg pDrawable->y + pPicture->clipOrigin.y); 2336747b715Smrg RegionIntersect(pPicture->pCompositeClip, 23405b261ecSmrg pPicture->pCompositeClip, pPicture->clientClip); 2356747b715Smrg RegionTranslate(pPicture->clientClip, 23605b261ecSmrg -(pDrawable->x + pPicture->clipOrigin.x), 23705b261ecSmrg -(pDrawable->y + pPicture->clipOrigin.y)); 23805b261ecSmrg } else { 2396747b715Smrg RegionTranslate(pPicture->pCompositeClip, 24005b261ecSmrg -pPicture->clipOrigin.x, -pPicture->clipOrigin.y); 2416747b715Smrg RegionIntersect(pPicture->pCompositeClip, 24205b261ecSmrg pPicture->pCompositeClip, pPicture->clientClip); 2436747b715Smrg RegionTranslate(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{ 3166747b715Smrg if (pPicture->clientClipType != CT_NONE) 31705b261ecSmrg { 3186747b715Smrg Bool result; 3196747b715Smrg 3206747b715Smrg pixman_region_translate ( pPicture->clientClip, 3216747b715Smrg pPicture->clipOrigin.x + dx, 3226747b715Smrg pPicture->clipOrigin.y + dy); 3236747b715Smrg 3246747b715Smrg result = RegionIntersect(pRegion, pRegion, pPicture->clientClip); 3256747b715Smrg 3266747b715Smrg pixman_region_translate ( pPicture->clientClip, 3276747b715Smrg - (pPicture->clipOrigin.x + dx), 3286747b715Smrg - (pPicture->clipOrigin.y + dy)); 3296747b715Smrg 3306747b715Smrg if (!result) 3316747b715Smrg return FALSE; 33205b261ecSmrg } 3336747b715Smrg return TRUE; 33405b261ecSmrg} 33505b261ecSmrg 33605b261ecSmrgvoid 33705b261ecSmrgmiCompositeSourceValidate (PicturePtr pPicture, 33805b261ecSmrg INT16 x, 33905b261ecSmrg INT16 y, 34005b261ecSmrg CARD16 width, 34105b261ecSmrg CARD16 height) 34205b261ecSmrg{ 34305b261ecSmrg DrawablePtr pDrawable = pPicture->pDrawable; 34405b261ecSmrg ScreenPtr pScreen; 34505b261ecSmrg 34605b261ecSmrg if (!pDrawable) 34705b261ecSmrg return; 34805b261ecSmrg 34905b261ecSmrg pScreen = pDrawable->pScreen; 35005b261ecSmrg 35105b261ecSmrg if (pScreen->SourceValidate) 35205b261ecSmrg { 35305b261ecSmrg if (pPicture->transform) 35405b261ecSmrg { 35505b261ecSmrg xPoint points[4]; 35605b261ecSmrg int i; 35705b261ecSmrg int xmin, ymin, xmax, ymax; 35805b261ecSmrg 35905b261ecSmrg#define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; } 36005b261ecSmrg VectorSet (0, x, y); 36105b261ecSmrg VectorSet (1, x + width, y); 36205b261ecSmrg VectorSet (2, x, y + height); 36305b261ecSmrg VectorSet (3, x + width, y + height); 36405b261ecSmrg xmin = ymin = 32767; 36505b261ecSmrg xmax = ymax = -32737; 36605b261ecSmrg for (i = 0; i < 4; i++) 36705b261ecSmrg { 36805b261ecSmrg PictVector t; 36905b261ecSmrg t.vector[0] = IntToxFixed (points[i].x); 37005b261ecSmrg t.vector[1] = IntToxFixed (points[i].y); 37105b261ecSmrg t.vector[2] = xFixed1; 3724642e01fSmrg if (pixman_transform_point (pPicture->transform, &t)) 37305b261ecSmrg { 37405b261ecSmrg int tx = xFixedToInt (t.vector[0]); 37505b261ecSmrg int ty = xFixedToInt (t.vector[1]); 37605b261ecSmrg if (tx < xmin) xmin = tx; 37705b261ecSmrg if (tx > xmax) xmax = tx; 37805b261ecSmrg if (ty < ymin) ymin = ty; 37905b261ecSmrg if (ty > ymax) ymax = ty; 38005b261ecSmrg } 38105b261ecSmrg } 38205b261ecSmrg x = xmin; 38305b261ecSmrg y = ymin; 38405b261ecSmrg width = xmax - xmin; 38505b261ecSmrg height = ymax - ymin; 38605b261ecSmrg } 3876747b715Smrg x += pPicture->pDrawable->x; 3886747b715Smrg y += pPicture->pDrawable->y; 38905b261ecSmrg (*pScreen->SourceValidate) (pDrawable, x, y, width, height); 39005b261ecSmrg } 39105b261ecSmrg} 39205b261ecSmrg 39305b261ecSmrg/* 39405b261ecSmrg * returns FALSE if the final region is empty. Indistinguishable from 39505b261ecSmrg * an allocation failure, but rendering ignores those anyways. 39605b261ecSmrg */ 39705b261ecSmrg 3986747b715SmrgBool 39905b261ecSmrgmiComputeCompositeRegion (RegionPtr pRegion, 40005b261ecSmrg PicturePtr pSrc, 40105b261ecSmrg PicturePtr pMask, 40205b261ecSmrg PicturePtr pDst, 40305b261ecSmrg INT16 xSrc, 40405b261ecSmrg INT16 ySrc, 40505b261ecSmrg INT16 xMask, 40605b261ecSmrg INT16 yMask, 40705b261ecSmrg INT16 xDst, 40805b261ecSmrg INT16 yDst, 40905b261ecSmrg CARD16 width, 41005b261ecSmrg CARD16 height) 41105b261ecSmrg{ 41205b261ecSmrg 41305b261ecSmrg int v; 41405b261ecSmrg 41505b261ecSmrg pRegion->extents.x1 = xDst; 41605b261ecSmrg v = xDst + width; 41705b261ecSmrg pRegion->extents.x2 = BOUND(v); 41805b261ecSmrg pRegion->extents.y1 = yDst; 41905b261ecSmrg v = yDst + height; 42005b261ecSmrg pRegion->extents.y2 = BOUND(v); 42105b261ecSmrg pRegion->data = 0; 42205b261ecSmrg /* Check for empty operation */ 42305b261ecSmrg if (pRegion->extents.x1 >= pRegion->extents.x2 || 42405b261ecSmrg pRegion->extents.y1 >= pRegion->extents.y2) 42505b261ecSmrg { 42605b261ecSmrg pixman_region_init (pRegion); 42705b261ecSmrg return FALSE; 42805b261ecSmrg } 42905b261ecSmrg /* clip against dst */ 43005b261ecSmrg if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0)) 43105b261ecSmrg { 43205b261ecSmrg pixman_region_fini (pRegion); 43305b261ecSmrg return FALSE; 43405b261ecSmrg } 43505b261ecSmrg if (pDst->alphaMap) 43605b261ecSmrg { 43705b261ecSmrg if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip, 43805b261ecSmrg -pDst->alphaOrigin.x, 43905b261ecSmrg -pDst->alphaOrigin.y)) 44005b261ecSmrg { 44105b261ecSmrg pixman_region_fini (pRegion); 44205b261ecSmrg return FALSE; 44305b261ecSmrg } 44405b261ecSmrg } 44505b261ecSmrg /* clip against src */ 44605b261ecSmrg if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc)) 44705b261ecSmrg { 44805b261ecSmrg pixman_region_fini (pRegion); 44905b261ecSmrg return FALSE; 45005b261ecSmrg } 45105b261ecSmrg if (pSrc->alphaMap) 45205b261ecSmrg { 45305b261ecSmrg if (!miClipPictureSrc (pRegion, pSrc->alphaMap, 4546747b715Smrg xDst - (xSrc - pSrc->alphaOrigin.x), 4556747b715Smrg yDst - (ySrc - pSrc->alphaOrigin.y))) 45605b261ecSmrg { 45705b261ecSmrg pixman_region_fini (pRegion); 45805b261ecSmrg return FALSE; 45905b261ecSmrg } 46005b261ecSmrg } 46105b261ecSmrg /* clip against mask */ 46205b261ecSmrg if (pMask) 46305b261ecSmrg { 46405b261ecSmrg if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask)) 46505b261ecSmrg { 46605b261ecSmrg pixman_region_fini (pRegion); 46705b261ecSmrg return FALSE; 46805b261ecSmrg } 46905b261ecSmrg if (pMask->alphaMap) 47005b261ecSmrg { 47105b261ecSmrg if (!miClipPictureSrc (pRegion, pMask->alphaMap, 4726747b715Smrg xDst - (xMask - pMask->alphaOrigin.x), 4736747b715Smrg yDst - (yMask - pMask->alphaOrigin.y))) 47405b261ecSmrg { 47505b261ecSmrg pixman_region_fini (pRegion); 47605b261ecSmrg return FALSE; 47705b261ecSmrg } 47805b261ecSmrg } 47905b261ecSmrg } 48005b261ecSmrg 48105b261ecSmrg 48205b261ecSmrg miCompositeSourceValidate (pSrc, xSrc, ySrc, width, height); 48305b261ecSmrg if (pMask) 48405b261ecSmrg miCompositeSourceValidate (pMask, xMask, yMask, width, height); 48505b261ecSmrg 48605b261ecSmrg return TRUE; 48705b261ecSmrg} 48805b261ecSmrg 48905b261ecSmrgvoid 49005b261ecSmrgmiRenderColorToPixel (PictFormatPtr format, 49105b261ecSmrg xRenderColor *color, 49205b261ecSmrg CARD32 *pixel) 49305b261ecSmrg{ 49405b261ecSmrg CARD32 r, g, b, a; 49505b261ecSmrg miIndexedPtr pIndexed; 49605b261ecSmrg 49705b261ecSmrg switch (format->type) { 49805b261ecSmrg case PictTypeDirect: 49905b261ecSmrg r = color->red >> (16 - Ones (format->direct.redMask)); 50005b261ecSmrg g = color->green >> (16 - Ones (format->direct.greenMask)); 50105b261ecSmrg b = color->blue >> (16 - Ones (format->direct.blueMask)); 50205b261ecSmrg a = color->alpha >> (16 - Ones (format->direct.alphaMask)); 50305b261ecSmrg r = r << format->direct.red; 50405b261ecSmrg g = g << format->direct.green; 50505b261ecSmrg b = b << format->direct.blue; 50605b261ecSmrg a = a << format->direct.alpha; 50705b261ecSmrg *pixel = r|g|b|a; 50805b261ecSmrg break; 50905b261ecSmrg case PictTypeIndexed: 51005b261ecSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 51105b261ecSmrg if (pIndexed->color) 51205b261ecSmrg { 51305b261ecSmrg r = color->red >> 11; 51405b261ecSmrg g = color->green >> 11; 51505b261ecSmrg b = color->blue >> 11; 51605b261ecSmrg *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b); 51705b261ecSmrg } 51805b261ecSmrg else 51905b261ecSmrg { 52005b261ecSmrg r = color->red >> 8; 52105b261ecSmrg g = color->green >> 8; 52205b261ecSmrg b = color->blue >> 8; 52305b261ecSmrg *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b); 52405b261ecSmrg } 52505b261ecSmrg break; 52605b261ecSmrg } 52705b261ecSmrg} 52805b261ecSmrg 52905b261ecSmrgstatic CARD16 53005b261ecSmrgmiFillColor (CARD32 pixel, int bits) 53105b261ecSmrg{ 53205b261ecSmrg while (bits < 16) 53305b261ecSmrg { 53405b261ecSmrg pixel |= pixel << bits; 53505b261ecSmrg bits <<= 1; 53605b261ecSmrg } 53705b261ecSmrg return (CARD16) pixel; 53805b261ecSmrg} 53905b261ecSmrg 54005b261ecSmrgBool 54105b261ecSmrgmiIsSolidAlpha (PicturePtr pSrc) 54205b261ecSmrg{ 54305b261ecSmrg ScreenPtr pScreen; 54405b261ecSmrg char line[1]; 54505b261ecSmrg 54605b261ecSmrg if (!pSrc->pDrawable) 54705b261ecSmrg return FALSE; 54805b261ecSmrg 54905b261ecSmrg pScreen = pSrc->pDrawable->pScreen; 55005b261ecSmrg 55105b261ecSmrg /* Alpha-only */ 55205b261ecSmrg if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A) 55305b261ecSmrg return FALSE; 55405b261ecSmrg /* repeat */ 55505b261ecSmrg if (!pSrc->repeat) 55605b261ecSmrg return FALSE; 55705b261ecSmrg /* 1x1 */ 55805b261ecSmrg if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) 55905b261ecSmrg return FALSE; 56005b261ecSmrg line[0] = 1; 56105b261ecSmrg (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); 56205b261ecSmrg switch (pSrc->pDrawable->bitsPerPixel) { 56305b261ecSmrg case 1: 56405b261ecSmrg return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; 56505b261ecSmrg case 4: 56605b261ecSmrg return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; 56705b261ecSmrg case 8: 56805b261ecSmrg return (CARD8) line[0] == 0xff; 56905b261ecSmrg default: 57005b261ecSmrg return FALSE; 57105b261ecSmrg } 57205b261ecSmrg} 57305b261ecSmrg 57405b261ecSmrgvoid 57505b261ecSmrgmiRenderPixelToColor (PictFormatPtr format, 57605b261ecSmrg CARD32 pixel, 57705b261ecSmrg xRenderColor *color) 57805b261ecSmrg{ 57905b261ecSmrg CARD32 r, g, b, a; 58005b261ecSmrg miIndexedPtr pIndexed; 58105b261ecSmrg 58205b261ecSmrg switch (format->type) { 58305b261ecSmrg case PictTypeDirect: 58405b261ecSmrg r = (pixel >> format->direct.red) & format->direct.redMask; 58505b261ecSmrg g = (pixel >> format->direct.green) & format->direct.greenMask; 58605b261ecSmrg b = (pixel >> format->direct.blue) & format->direct.blueMask; 58705b261ecSmrg a = (pixel >> format->direct.alpha) & format->direct.alphaMask; 58805b261ecSmrg color->red = miFillColor (r, Ones (format->direct.redMask)); 58905b261ecSmrg color->green = miFillColor (g, Ones (format->direct.greenMask)); 59005b261ecSmrg color->blue = miFillColor (b, Ones (format->direct.blueMask)); 59105b261ecSmrg color->alpha = miFillColor (a, Ones (format->direct.alphaMask)); 59205b261ecSmrg break; 59305b261ecSmrg case PictTypeIndexed: 59405b261ecSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 59505b261ecSmrg pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)]; 59605b261ecSmrg r = (pixel >> 16) & 0xff; 59705b261ecSmrg g = (pixel >> 8) & 0xff; 59805b261ecSmrg b = (pixel ) & 0xff; 59905b261ecSmrg color->red = miFillColor (r, 8); 60005b261ecSmrg color->green = miFillColor (g, 8); 60105b261ecSmrg color->blue = miFillColor (b, 8); 60205b261ecSmrg color->alpha = 0xffff; 60305b261ecSmrg break; 60405b261ecSmrg } 60505b261ecSmrg} 60605b261ecSmrg 6076747b715SmrgBool 60805b261ecSmrgmiPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats) 60905b261ecSmrg{ 61005b261ecSmrg PictureScreenPtr ps; 61105b261ecSmrg 61205b261ecSmrg if (!PictureInit (pScreen, formats, nformats)) 61305b261ecSmrg return FALSE; 61405b261ecSmrg ps = GetPictureScreen(pScreen); 61505b261ecSmrg ps->CreatePicture = miCreatePicture; 61605b261ecSmrg ps->DestroyPicture = miDestroyPicture; 61705b261ecSmrg ps->ChangePictureClip = miChangePictureClip; 61805b261ecSmrg ps->DestroyPictureClip = miDestroyPictureClip; 61905b261ecSmrg ps->ChangePicture = miChangePicture; 62005b261ecSmrg ps->ValidatePicture = miValidatePicture; 62105b261ecSmrg ps->InitIndexed = miInitIndexed; 62205b261ecSmrg ps->CloseIndexed = miCloseIndexed; 62305b261ecSmrg ps->UpdateIndexed = miUpdateIndexed; 62405b261ecSmrg ps->ChangePictureTransform = miChangePictureTransform; 62505b261ecSmrg ps->ChangePictureFilter = miChangePictureFilter; 62605b261ecSmrg ps->RealizeGlyph = miRealizeGlyph; 62705b261ecSmrg ps->UnrealizeGlyph = miUnrealizeGlyph; 62805b261ecSmrg 62905b261ecSmrg /* MI rendering routines */ 63005b261ecSmrg ps->Composite = 0; /* requires DDX support */ 63105b261ecSmrg ps->Glyphs = miGlyphs; 63205b261ecSmrg ps->CompositeRects = miCompositeRects; 63305b261ecSmrg ps->Trapezoids = miTrapezoids; 63405b261ecSmrg ps->Triangles = miTriangles; 63505b261ecSmrg ps->TriStrip = miTriStrip; 63605b261ecSmrg ps->TriFan = miTriFan; 63705b261ecSmrg 63805b261ecSmrg ps->RasterizeTrapezoid = 0; /* requires DDX support */ 63905b261ecSmrg ps->AddTraps = 0; /* requires DDX support */ 64005b261ecSmrg ps->AddTriangles = 0; /* requires DDX support */ 64105b261ecSmrg 64205b261ecSmrg return TRUE; 64305b261ecSmrg} 644