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 3605b261ecSmrgint 3735c4bbdfSmrgmiCreatePicture(PicturePtr pPicture) 3805b261ecSmrg{ 3905b261ecSmrg return Success; 4005b261ecSmrg} 4105b261ecSmrg 4205b261ecSmrgvoid 4335c4bbdfSmrgmiDestroyPicture(PicturePtr pPicture) 4405b261ecSmrg{ 4505b261ecSmrg if (pPicture->freeCompClip) 4635c4bbdfSmrg RegionDestroy(pPicture->pCompositeClip); 4705b261ecSmrg} 4805b261ecSmrg 4935c4bbdfSmrgstatic void 5035c4bbdfSmrgmiDestroyPictureClip(PicturePtr pPicture) 5105b261ecSmrg{ 5235c4bbdfSmrg if (pPicture->clientClip) 5335c4bbdfSmrg RegionDestroy(pPicture->clientClip); 5405b261ecSmrg pPicture->clientClip = NULL; 5535c4bbdfSmrg} 5605b261ecSmrg 5735c4bbdfSmrgstatic int 5835c4bbdfSmrgmiChangePictureClip(PicturePtr pPicture, int type, void *value, int n) 5905b261ecSmrg{ 6035c4bbdfSmrg ScreenPtr pScreen = pPicture->pDrawable->pScreen; 6135c4bbdfSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 6235c4bbdfSmrg RegionPtr clientClip; 6335c4bbdfSmrg 6405b261ecSmrg switch (type) { 6505b261ecSmrg case CT_PIXMAP: 6635c4bbdfSmrg /* convert the pixmap to a region */ 6735c4bbdfSmrg clientClip = BitmapToRegion(pScreen, (PixmapPtr) value); 6835c4bbdfSmrg if (!clientClip) 6935c4bbdfSmrg return BadAlloc; 7035c4bbdfSmrg (*pScreen->DestroyPixmap) ((PixmapPtr) value); 7135c4bbdfSmrg break; 7205b261ecSmrg case CT_REGION: 7335c4bbdfSmrg clientClip = value; 7435c4bbdfSmrg break; 7505b261ecSmrg case CT_NONE: 7635c4bbdfSmrg clientClip = 0; 7735c4bbdfSmrg break; 7805b261ecSmrg default: 7935c4bbdfSmrg clientClip = RegionFromRects(n, (xRectangle *) value, type); 8035c4bbdfSmrg if (!clientClip) 8135c4bbdfSmrg return BadAlloc; 8235c4bbdfSmrg free(value); 8335c4bbdfSmrg break; 8405b261ecSmrg } 8505b261ecSmrg (*ps->DestroyPictureClip) (pPicture); 8605b261ecSmrg pPicture->clientClip = clientClip; 8705b261ecSmrg pPicture->stateChanges |= CPClipMask; 8805b261ecSmrg return Success; 8905b261ecSmrg} 9005b261ecSmrg 9135c4bbdfSmrgstatic void 9235c4bbdfSmrgmiChangePicture(PicturePtr pPicture, Mask mask) 9305b261ecSmrg{ 9405b261ecSmrg return; 9505b261ecSmrg} 9605b261ecSmrg 9735c4bbdfSmrgstatic void 9835c4bbdfSmrgmiValidatePicture(PicturePtr pPicture, Mask mask) 9905b261ecSmrg{ 10035c4bbdfSmrg DrawablePtr pDrawable = pPicture->pDrawable; 10135c4bbdfSmrg 10235c4bbdfSmrg if ((mask & (CPClipXOrigin | CPClipYOrigin | CPClipMask | CPSubwindowMode)) 10335c4bbdfSmrg || (pDrawable->serialNumber != 10435c4bbdfSmrg (pPicture->serialNumber & DRAWABLE_SERIAL_BITS))) { 10535c4bbdfSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 10635c4bbdfSmrg WindowPtr pWin = (WindowPtr) pDrawable; 10735c4bbdfSmrg RegionPtr pregWin; 10835c4bbdfSmrg Bool freeTmpClip, freeCompClip; 10935c4bbdfSmrg 11035c4bbdfSmrg if (pPicture->subWindowMode == IncludeInferiors) { 11135c4bbdfSmrg pregWin = NotClippedByChildren(pWin); 11235c4bbdfSmrg freeTmpClip = TRUE; 11335c4bbdfSmrg } 11435c4bbdfSmrg else { 11535c4bbdfSmrg pregWin = &pWin->clipList; 11635c4bbdfSmrg freeTmpClip = FALSE; 11735c4bbdfSmrg } 11835c4bbdfSmrg freeCompClip = pPicture->freeCompClip; 11935c4bbdfSmrg 12035c4bbdfSmrg /* 12135c4bbdfSmrg * if there is no client clip, we can get by with just keeping the 12235c4bbdfSmrg * pointer we got, and remembering whether or not should destroy 12335c4bbdfSmrg * (or maybe re-use) it later. this way, we avoid unnecessary 12435c4bbdfSmrg * copying of regions. (this wins especially if many clients clip 12535c4bbdfSmrg * by children and have no client clip.) 12635c4bbdfSmrg */ 12735c4bbdfSmrg if (!pPicture->clientClip) { 12835c4bbdfSmrg if (freeCompClip) 12935c4bbdfSmrg RegionDestroy(pPicture->pCompositeClip); 13035c4bbdfSmrg pPicture->pCompositeClip = pregWin; 13135c4bbdfSmrg pPicture->freeCompClip = freeTmpClip; 13235c4bbdfSmrg } 13335c4bbdfSmrg else { 13435c4bbdfSmrg /* 13535c4bbdfSmrg * we need one 'real' region to put into the composite clip. if 13635c4bbdfSmrg * pregWin the current composite clip are real, we can get rid of 13735c4bbdfSmrg * one. if pregWin is real and the current composite clip isn't, 13835c4bbdfSmrg * use pregWin for the composite clip. if the current composite 13935c4bbdfSmrg * clip is real and pregWin isn't, use the current composite 14035c4bbdfSmrg * clip. if neither is real, create a new region. 14135c4bbdfSmrg */ 14235c4bbdfSmrg 14335c4bbdfSmrg RegionTranslate(pPicture->clientClip, 14435c4bbdfSmrg pDrawable->x + pPicture->clipOrigin.x, 14535c4bbdfSmrg pDrawable->y + pPicture->clipOrigin.y); 14635c4bbdfSmrg 14735c4bbdfSmrg if (freeCompClip) { 14835c4bbdfSmrg RegionIntersect(pPicture->pCompositeClip, 14935c4bbdfSmrg pregWin, pPicture->clientClip); 15035c4bbdfSmrg if (freeTmpClip) 15135c4bbdfSmrg RegionDestroy(pregWin); 15235c4bbdfSmrg } 15335c4bbdfSmrg else if (freeTmpClip) { 15435c4bbdfSmrg RegionIntersect(pregWin, pregWin, pPicture->clientClip); 15535c4bbdfSmrg pPicture->pCompositeClip = pregWin; 15635c4bbdfSmrg } 15735c4bbdfSmrg else { 15835c4bbdfSmrg pPicture->pCompositeClip = RegionCreate(NullBox, 0); 15935c4bbdfSmrg RegionIntersect(pPicture->pCompositeClip, 16035c4bbdfSmrg pregWin, pPicture->clientClip); 16135c4bbdfSmrg } 16235c4bbdfSmrg pPicture->freeCompClip = TRUE; 16335c4bbdfSmrg RegionTranslate(pPicture->clientClip, 16435c4bbdfSmrg -(pDrawable->x + pPicture->clipOrigin.x), 16535c4bbdfSmrg -(pDrawable->y + pPicture->clipOrigin.y)); 16635c4bbdfSmrg } 16735c4bbdfSmrg } /* end of composite clip for a window */ 16835c4bbdfSmrg else { 16935c4bbdfSmrg BoxRec pixbounds; 17035c4bbdfSmrg 17135c4bbdfSmrg /* XXX should we translate by drawable.x/y here ? */ 17235c4bbdfSmrg /* If you want pixmaps in offscreen memory, yes */ 17335c4bbdfSmrg pixbounds.x1 = pDrawable->x; 17435c4bbdfSmrg pixbounds.y1 = pDrawable->y; 17535c4bbdfSmrg pixbounds.x2 = pDrawable->x + pDrawable->width; 17635c4bbdfSmrg pixbounds.y2 = pDrawable->y + pDrawable->height; 17735c4bbdfSmrg 17835c4bbdfSmrg if (pPicture->freeCompClip) { 17935c4bbdfSmrg RegionReset(pPicture->pCompositeClip, &pixbounds); 18035c4bbdfSmrg } 18135c4bbdfSmrg else { 18235c4bbdfSmrg pPicture->freeCompClip = TRUE; 18335c4bbdfSmrg pPicture->pCompositeClip = RegionCreate(&pixbounds, 1); 18435c4bbdfSmrg } 18535c4bbdfSmrg 18635c4bbdfSmrg if (pPicture->clientClip) { 18735c4bbdfSmrg if (pDrawable->x || pDrawable->y) { 18835c4bbdfSmrg RegionTranslate(pPicture->clientClip, 18935c4bbdfSmrg pDrawable->x + pPicture->clipOrigin.x, 19035c4bbdfSmrg pDrawable->y + pPicture->clipOrigin.y); 19135c4bbdfSmrg RegionIntersect(pPicture->pCompositeClip, 19235c4bbdfSmrg pPicture->pCompositeClip, 19335c4bbdfSmrg pPicture->clientClip); 19435c4bbdfSmrg RegionTranslate(pPicture->clientClip, 19535c4bbdfSmrg -(pDrawable->x + pPicture->clipOrigin.x), 19635c4bbdfSmrg -(pDrawable->y + pPicture->clipOrigin.y)); 19735c4bbdfSmrg } 19835c4bbdfSmrg else { 19935c4bbdfSmrg RegionTranslate(pPicture->pCompositeClip, 20035c4bbdfSmrg -pPicture->clipOrigin.x, 20135c4bbdfSmrg -pPicture->clipOrigin.y); 20235c4bbdfSmrg RegionIntersect(pPicture->pCompositeClip, 20335c4bbdfSmrg pPicture->pCompositeClip, 20435c4bbdfSmrg pPicture->clientClip); 20535c4bbdfSmrg RegionTranslate(pPicture->pCompositeClip, 20635c4bbdfSmrg pPicture->clipOrigin.x, 20735c4bbdfSmrg pPicture->clipOrigin.y); 20835c4bbdfSmrg } 20935c4bbdfSmrg } 21035c4bbdfSmrg } /* end of composite clip for pixmap */ 21105b261ecSmrg } 21205b261ecSmrg} 21305b261ecSmrg 21435c4bbdfSmrgstatic int 21535c4bbdfSmrgmiChangePictureTransform(PicturePtr pPicture, PictTransform * transform) 21605b261ecSmrg{ 21705b261ecSmrg return Success; 21805b261ecSmrg} 21905b261ecSmrg 22035c4bbdfSmrgstatic int 22135c4bbdfSmrgmiChangePictureFilter(PicturePtr pPicture, 22235c4bbdfSmrg int filter, xFixed * params, int nparams) 22305b261ecSmrg{ 22405b261ecSmrg return Success; 22505b261ecSmrg} 22605b261ecSmrg 22705b261ecSmrg#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v)) 22805b261ecSmrg 22905b261ecSmrgstatic inline pixman_bool_t 23035c4bbdfSmrgmiClipPictureReg(pixman_region16_t * pRegion, 23135c4bbdfSmrg pixman_region16_t * pClip, int dx, int dy) 23205b261ecSmrg{ 23305b261ecSmrg if (pixman_region_n_rects(pRegion) == 1 && 23435c4bbdfSmrg pixman_region_n_rects(pClip) == 1) { 23535c4bbdfSmrg pixman_box16_t *pRbox = pixman_region_rectangles(pRegion, NULL); 23635c4bbdfSmrg pixman_box16_t *pCbox = pixman_region_rectangles(pClip, NULL); 23735c4bbdfSmrg int v; 23835c4bbdfSmrg 23935c4bbdfSmrg if (pRbox->x1 < (v = pCbox->x1 + dx)) 24035c4bbdfSmrg pRbox->x1 = BOUND(v); 24135c4bbdfSmrg if (pRbox->x2 > (v = pCbox->x2 + dx)) 24235c4bbdfSmrg pRbox->x2 = BOUND(v); 24335c4bbdfSmrg if (pRbox->y1 < (v = pCbox->y1 + dy)) 24435c4bbdfSmrg pRbox->y1 = BOUND(v); 24535c4bbdfSmrg if (pRbox->y2 > (v = pCbox->y2 + dy)) 24635c4bbdfSmrg pRbox->y2 = BOUND(v); 24735c4bbdfSmrg if (pRbox->x1 >= pRbox->x2 || pRbox->y1 >= pRbox->y2) { 24835c4bbdfSmrg pixman_region_init(pRegion); 24935c4bbdfSmrg } 25005b261ecSmrg } 25135c4bbdfSmrg else if (!pixman_region_not_empty(pClip)) 25235c4bbdfSmrg return FALSE; 25335c4bbdfSmrg else { 25435c4bbdfSmrg if (dx || dy) 25535c4bbdfSmrg pixman_region_translate(pRegion, -dx, -dy); 25635c4bbdfSmrg if (!pixman_region_intersect(pRegion, pRegion, pClip)) 25735c4bbdfSmrg return FALSE; 25835c4bbdfSmrg if (dx || dy) 25935c4bbdfSmrg pixman_region_translate(pRegion, dx, dy); 26005b261ecSmrg } 26105b261ecSmrg return pixman_region_not_empty(pRegion); 26205b261ecSmrg} 26305b261ecSmrg 26435c4bbdfSmrgstatic inline Bool 26535c4bbdfSmrgmiClipPictureSrc(RegionPtr pRegion, PicturePtr pPicture, int dx, int dy) 26605b261ecSmrg{ 26735c4bbdfSmrg if (pPicture->clientClip) { 26835c4bbdfSmrg Bool result; 26935c4bbdfSmrg 27035c4bbdfSmrg pixman_region_translate(pPicture->clientClip, 27135c4bbdfSmrg pPicture->clipOrigin.x + dx, 27235c4bbdfSmrg pPicture->clipOrigin.y + dy); 27335c4bbdfSmrg 27435c4bbdfSmrg result = RegionIntersect(pRegion, pRegion, pPicture->clientClip); 27535c4bbdfSmrg 27635c4bbdfSmrg pixman_region_translate(pPicture->clientClip, 27735c4bbdfSmrg -(pPicture->clipOrigin.x + dx), 27835c4bbdfSmrg -(pPicture->clipOrigin.y + dy)); 27935c4bbdfSmrg 28035c4bbdfSmrg if (!result) 28135c4bbdfSmrg return FALSE; 28205b261ecSmrg } 2836747b715Smrg return TRUE; 28405b261ecSmrg} 28505b261ecSmrg 28635c4bbdfSmrgstatic void 28735c4bbdfSmrgSourceValidateOnePicture(PicturePtr pPicture) 28805b261ecSmrg{ 28935c4bbdfSmrg DrawablePtr pDrawable = pPicture->pDrawable; 29035c4bbdfSmrg ScreenPtr pScreen; 29105b261ecSmrg 29205b261ecSmrg if (!pDrawable) 29305b261ecSmrg return; 29405b261ecSmrg 29505b261ecSmrg pScreen = pDrawable->pScreen; 29635c4bbdfSmrg 297ed6184dfSmrg pScreen->SourceValidate(pDrawable, 0, 0, pDrawable->width, 298ed6184dfSmrg pDrawable->height, pPicture->subWindowMode); 29905b261ecSmrg} 30005b261ecSmrg 30135c4bbdfSmrgvoid 30235c4bbdfSmrgmiCompositeSourceValidate(PicturePtr pPicture) 30335c4bbdfSmrg{ 30435c4bbdfSmrg SourceValidateOnePicture(pPicture); 30535c4bbdfSmrg if (pPicture->alphaMap) 30635c4bbdfSmrg SourceValidateOnePicture(pPicture->alphaMap); 30735c4bbdfSmrg} 30835c4bbdfSmrg 30905b261ecSmrg/* 31005b261ecSmrg * returns FALSE if the final region is empty. Indistinguishable from 31105b261ecSmrg * an allocation failure, but rendering ignores those anyways. 31205b261ecSmrg */ 31305b261ecSmrg 3146747b715SmrgBool 31535c4bbdfSmrgmiComputeCompositeRegion(RegionPtr pRegion, 31635c4bbdfSmrg PicturePtr pSrc, 31735c4bbdfSmrg PicturePtr pMask, 31835c4bbdfSmrg PicturePtr pDst, 31935c4bbdfSmrg INT16 xSrc, 32035c4bbdfSmrg INT16 ySrc, 32135c4bbdfSmrg INT16 xMask, 32235c4bbdfSmrg INT16 yMask, 32335c4bbdfSmrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 32405b261ecSmrg{ 32535c4bbdfSmrg 32635c4bbdfSmrg int v; 32705b261ecSmrg 32805b261ecSmrg pRegion->extents.x1 = xDst; 32905b261ecSmrg v = xDst + width; 33005b261ecSmrg pRegion->extents.x2 = BOUND(v); 33105b261ecSmrg pRegion->extents.y1 = yDst; 33205b261ecSmrg v = yDst + height; 33305b261ecSmrg pRegion->extents.y2 = BOUND(v); 33405b261ecSmrg pRegion->data = 0; 33505b261ecSmrg /* Check for empty operation */ 33605b261ecSmrg if (pRegion->extents.x1 >= pRegion->extents.x2 || 33735c4bbdfSmrg pRegion->extents.y1 >= pRegion->extents.y2) { 33835c4bbdfSmrg pixman_region_init(pRegion); 33935c4bbdfSmrg return FALSE; 34005b261ecSmrg } 34105b261ecSmrg /* clip against dst */ 34235c4bbdfSmrg if (!miClipPictureReg(pRegion, pDst->pCompositeClip, 0, 0)) { 34335c4bbdfSmrg pixman_region_fini(pRegion); 34435c4bbdfSmrg return FALSE; 34505b261ecSmrg } 34635c4bbdfSmrg if (pDst->alphaMap) { 34735c4bbdfSmrg if (!miClipPictureReg(pRegion, pDst->alphaMap->pCompositeClip, 34835c4bbdfSmrg -pDst->alphaOrigin.x, -pDst->alphaOrigin.y)) { 34935c4bbdfSmrg pixman_region_fini(pRegion); 35035c4bbdfSmrg return FALSE; 35135c4bbdfSmrg } 35205b261ecSmrg } 35305b261ecSmrg /* clip against src */ 35435c4bbdfSmrg if (!miClipPictureSrc(pRegion, pSrc, xDst - xSrc, yDst - ySrc)) { 35535c4bbdfSmrg pixman_region_fini(pRegion); 35635c4bbdfSmrg return FALSE; 35705b261ecSmrg } 35835c4bbdfSmrg if (pSrc->alphaMap) { 35935c4bbdfSmrg if (!miClipPictureSrc(pRegion, pSrc->alphaMap, 36035c4bbdfSmrg xDst - (xSrc - pSrc->alphaOrigin.x), 36135c4bbdfSmrg yDst - (ySrc - pSrc->alphaOrigin.y))) { 36235c4bbdfSmrg pixman_region_fini(pRegion); 36335c4bbdfSmrg return FALSE; 36435c4bbdfSmrg } 36505b261ecSmrg } 36605b261ecSmrg /* clip against mask */ 36735c4bbdfSmrg if (pMask) { 36835c4bbdfSmrg if (!miClipPictureSrc(pRegion, pMask, xDst - xMask, yDst - yMask)) { 36935c4bbdfSmrg pixman_region_fini(pRegion); 37035c4bbdfSmrg return FALSE; 37135c4bbdfSmrg } 37235c4bbdfSmrg if (pMask->alphaMap) { 37335c4bbdfSmrg if (!miClipPictureSrc(pRegion, pMask->alphaMap, 37435c4bbdfSmrg xDst - (xMask - pMask->alphaOrigin.x), 37535c4bbdfSmrg yDst - (yMask - pMask->alphaOrigin.y))) { 37635c4bbdfSmrg pixman_region_fini(pRegion); 37735c4bbdfSmrg return FALSE; 37835c4bbdfSmrg } 37935c4bbdfSmrg } 38005b261ecSmrg } 38105b261ecSmrg 38235c4bbdfSmrg miCompositeSourceValidate(pSrc); 38305b261ecSmrg if (pMask) 38435c4bbdfSmrg miCompositeSourceValidate(pMask); 38505b261ecSmrg 38605b261ecSmrg return TRUE; 38705b261ecSmrg} 38805b261ecSmrg 38905b261ecSmrgvoid 39035c4bbdfSmrgmiRenderColorToPixel(PictFormatPtr format, xRenderColor * color, CARD32 *pixel) 39105b261ecSmrg{ 39235c4bbdfSmrg CARD32 r, g, b, a; 39335c4bbdfSmrg miIndexedPtr pIndexed; 39405b261ecSmrg 39505b261ecSmrg switch (format->type) { 39605b261ecSmrg case PictTypeDirect: 39735c4bbdfSmrg r = color->red >> (16 - Ones(format->direct.redMask)); 39835c4bbdfSmrg g = color->green >> (16 - Ones(format->direct.greenMask)); 39935c4bbdfSmrg b = color->blue >> (16 - Ones(format->direct.blueMask)); 40035c4bbdfSmrg a = color->alpha >> (16 - Ones(format->direct.alphaMask)); 40135c4bbdfSmrg r = r << format->direct.red; 40235c4bbdfSmrg g = g << format->direct.green; 40335c4bbdfSmrg b = b << format->direct.blue; 40435c4bbdfSmrg a = a << format->direct.alpha; 40535c4bbdfSmrg *pixel = r | g | b | a; 40635c4bbdfSmrg break; 40705b261ecSmrg case PictTypeIndexed: 40835c4bbdfSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 40935c4bbdfSmrg if (pIndexed->color) { 41035c4bbdfSmrg r = color->red >> 11; 41135c4bbdfSmrg g = color->green >> 11; 41235c4bbdfSmrg b = color->blue >> 11; 41335c4bbdfSmrg *pixel = miIndexToEnt15(pIndexed, (r << 10) | (g << 5) | b); 41435c4bbdfSmrg } 41535c4bbdfSmrg else { 41635c4bbdfSmrg r = color->red >> 8; 41735c4bbdfSmrg g = color->green >> 8; 41835c4bbdfSmrg b = color->blue >> 8; 41935c4bbdfSmrg *pixel = miIndexToEntY24(pIndexed, (r << 16) | (g << 8) | b); 42035c4bbdfSmrg } 42135c4bbdfSmrg break; 42205b261ecSmrg } 42305b261ecSmrg} 42405b261ecSmrg 42505b261ecSmrgstatic CARD16 42635c4bbdfSmrgmiFillColor(CARD32 pixel, int bits) 42705b261ecSmrg{ 42835c4bbdfSmrg while (bits < 16) { 42935c4bbdfSmrg pixel |= pixel << bits; 43035c4bbdfSmrg bits <<= 1; 43105b261ecSmrg } 43205b261ecSmrg return (CARD16) pixel; 43305b261ecSmrg} 43405b261ecSmrg 43505b261ecSmrgBool 43635c4bbdfSmrgmiIsSolidAlpha(PicturePtr pSrc) 43705b261ecSmrg{ 43835c4bbdfSmrg ScreenPtr pScreen; 43935c4bbdfSmrg char line[1]; 44005b261ecSmrg 44105b261ecSmrg if (!pSrc->pDrawable) 44205b261ecSmrg return FALSE; 44305b261ecSmrg 44405b261ecSmrg pScreen = pSrc->pDrawable->pScreen; 44535c4bbdfSmrg 44605b261ecSmrg /* Alpha-only */ 44735c4bbdfSmrg if (PICT_FORMAT_TYPE(pSrc->format) != PICT_TYPE_A) 44835c4bbdfSmrg return FALSE; 44905b261ecSmrg /* repeat */ 45005b261ecSmrg if (!pSrc->repeat) 45135c4bbdfSmrg return FALSE; 45205b261ecSmrg /* 1x1 */ 45305b261ecSmrg if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1) 45435c4bbdfSmrg return FALSE; 45505b261ecSmrg line[0] = 1; 45605b261ecSmrg (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line); 45705b261ecSmrg switch (pSrc->pDrawable->bitsPerPixel) { 45805b261ecSmrg case 1: 45935c4bbdfSmrg return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80; 46005b261ecSmrg case 4: 46135c4bbdfSmrg return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0; 46205b261ecSmrg case 8: 46335c4bbdfSmrg return (CARD8) line[0] == 0xff; 46405b261ecSmrg default: 46535c4bbdfSmrg return FALSE; 46605b261ecSmrg } 46705b261ecSmrg} 46805b261ecSmrg 46905b261ecSmrgvoid 47035c4bbdfSmrgmiRenderPixelToColor(PictFormatPtr format, CARD32 pixel, xRenderColor * color) 47105b261ecSmrg{ 47235c4bbdfSmrg CARD32 r, g, b, a; 47335c4bbdfSmrg miIndexedPtr pIndexed; 47435c4bbdfSmrg 47505b261ecSmrg switch (format->type) { 47605b261ecSmrg case PictTypeDirect: 47735c4bbdfSmrg r = (pixel >> format->direct.red) & format->direct.redMask; 47835c4bbdfSmrg g = (pixel >> format->direct.green) & format->direct.greenMask; 47935c4bbdfSmrg b = (pixel >> format->direct.blue) & format->direct.blueMask; 48035c4bbdfSmrg a = (pixel >> format->direct.alpha) & format->direct.alphaMask; 48135c4bbdfSmrg color->red = miFillColor(r, Ones(format->direct.redMask)); 48235c4bbdfSmrg color->green = miFillColor(g, Ones(format->direct.greenMask)); 48335c4bbdfSmrg color->blue = miFillColor(b, Ones(format->direct.blueMask)); 48435c4bbdfSmrg color->alpha = miFillColor(a, Ones(format->direct.alphaMask)); 48535c4bbdfSmrg break; 48605b261ecSmrg case PictTypeIndexed: 48735c4bbdfSmrg pIndexed = (miIndexedPtr) (format->index.devPrivate); 48835c4bbdfSmrg pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED - 1)]; 48935c4bbdfSmrg r = (pixel >> 16) & 0xff; 49035c4bbdfSmrg g = (pixel >> 8) & 0xff; 49135c4bbdfSmrg b = (pixel) & 0xff; 49235c4bbdfSmrg color->red = miFillColor(r, 8); 49335c4bbdfSmrg color->green = miFillColor(g, 8); 49435c4bbdfSmrg color->blue = miFillColor(b, 8); 49535c4bbdfSmrg color->alpha = 0xffff; 49635c4bbdfSmrg break; 49735c4bbdfSmrg } 49835c4bbdfSmrg} 49935c4bbdfSmrg 50035c4bbdfSmrgstatic void 50135c4bbdfSmrgmiTriStrip(CARD8 op, 50235c4bbdfSmrg PicturePtr pSrc, 50335c4bbdfSmrg PicturePtr pDst, 50435c4bbdfSmrg PictFormatPtr maskFormat, 50535c4bbdfSmrg INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points) 50635c4bbdfSmrg{ 50735c4bbdfSmrg xTriangle *tris, *tri; 50835c4bbdfSmrg int ntri; 50935c4bbdfSmrg 51035c4bbdfSmrg ntri = npoints - 2; 51135c4bbdfSmrg tris = xallocarray(ntri, sizeof(xTriangle)); 51235c4bbdfSmrg if (!tris) 51335c4bbdfSmrg return; 51435c4bbdfSmrg 51535c4bbdfSmrg for (tri = tris; npoints >= 3; npoints--, points++, tri++) { 51635c4bbdfSmrg tri->p1 = points[0]; 51735c4bbdfSmrg tri->p2 = points[1]; 51835c4bbdfSmrg tri->p3 = points[2]; 51905b261ecSmrg } 52035c4bbdfSmrg CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); 52135c4bbdfSmrg free(tris); 52235c4bbdfSmrg} 52335c4bbdfSmrg 52435c4bbdfSmrgstatic void 52535c4bbdfSmrgmiTriFan(CARD8 op, 52635c4bbdfSmrg PicturePtr pSrc, 52735c4bbdfSmrg PicturePtr pDst, 52835c4bbdfSmrg PictFormatPtr maskFormat, 52935c4bbdfSmrg INT16 xSrc, INT16 ySrc, int npoints, xPointFixed * points) 53035c4bbdfSmrg{ 53135c4bbdfSmrg xTriangle *tris, *tri; 53235c4bbdfSmrg xPointFixed *first; 53335c4bbdfSmrg int ntri; 53435c4bbdfSmrg 53535c4bbdfSmrg ntri = npoints - 2; 53635c4bbdfSmrg tris = xallocarray(ntri, sizeof(xTriangle)); 53735c4bbdfSmrg if (!tris) 53835c4bbdfSmrg return; 53935c4bbdfSmrg 54035c4bbdfSmrg first = points++; 54135c4bbdfSmrg for (tri = tris; npoints >= 3; npoints--, points++, tri++) { 54235c4bbdfSmrg tri->p1 = *first; 54335c4bbdfSmrg tri->p2 = points[0]; 54435c4bbdfSmrg tri->p3 = points[1]; 54535c4bbdfSmrg } 54635c4bbdfSmrg CompositeTriangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, tris); 54735c4bbdfSmrg free(tris); 54805b261ecSmrg} 54905b261ecSmrg 5506747b715SmrgBool 55135c4bbdfSmrgmiPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) 55205b261ecSmrg{ 55335c4bbdfSmrg PictureScreenPtr ps; 55435c4bbdfSmrg 55535c4bbdfSmrg if (!PictureInit(pScreen, formats, nformats)) 55635c4bbdfSmrg return FALSE; 55705b261ecSmrg ps = GetPictureScreen(pScreen); 55805b261ecSmrg ps->CreatePicture = miCreatePicture; 55905b261ecSmrg ps->DestroyPicture = miDestroyPicture; 56005b261ecSmrg ps->ChangePictureClip = miChangePictureClip; 56105b261ecSmrg ps->DestroyPictureClip = miDestroyPictureClip; 56205b261ecSmrg ps->ChangePicture = miChangePicture; 56305b261ecSmrg ps->ValidatePicture = miValidatePicture; 56405b261ecSmrg ps->InitIndexed = miInitIndexed; 56505b261ecSmrg ps->CloseIndexed = miCloseIndexed; 56605b261ecSmrg ps->UpdateIndexed = miUpdateIndexed; 56705b261ecSmrg ps->ChangePictureTransform = miChangePictureTransform; 56805b261ecSmrg ps->ChangePictureFilter = miChangePictureFilter; 56905b261ecSmrg ps->RealizeGlyph = miRealizeGlyph; 57005b261ecSmrg ps->UnrealizeGlyph = miUnrealizeGlyph; 57105b261ecSmrg 57205b261ecSmrg /* MI rendering routines */ 57335c4bbdfSmrg ps->Composite = 0; /* requires DDX support */ 57435c4bbdfSmrg ps->Glyphs = miGlyphs; 57535c4bbdfSmrg ps->CompositeRects = miCompositeRects; 57635c4bbdfSmrg ps->Trapezoids = 0; 57735c4bbdfSmrg ps->Triangles = 0; 57835c4bbdfSmrg 57935c4bbdfSmrg ps->RasterizeTrapezoid = 0; /* requires DDX support */ 58035c4bbdfSmrg ps->AddTraps = 0; /* requires DDX support */ 58135c4bbdfSmrg ps->AddTriangles = 0; /* requires DDX support */ 58235c4bbdfSmrg 58335c4bbdfSmrg ps->TriStrip = miTriStrip; /* converts call to CompositeTriangles */ 58435c4bbdfSmrg ps->TriFan = miTriFan; 58505b261ecSmrg 58605b261ecSmrg return TRUE; 58705b261ecSmrg} 588