123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- /*
- *
- * Copyright © 1999 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "scrnintstr.h"
- #include "gcstruct.h"
- #include "pixmapstr.h"
- #include "windowstr.h"
- #include "mi.h"
- #include "picturestr.h"
- #include "mipict.h"
- #ifndef __GNUC__
- #define __inline
- #endif
- int
- miCreatePicture(PicturePtr pPicture)
- {
- return Success;
- }
- void
- miDestroyPicture(PicturePtr pPicture)
- {
- if (pPicture->freeCompClip)
- REGION_DESTROY(pPicture->pCompositeClip);
- }
- void
- miDestroyPictureClip(PicturePtr pPicture)
- {
- switch (pPicture->clientClipType) {
- case CT_NONE:
- return;
- case CT_PIXMAP:
- (*pPicture->pDrawable->pScreen->
- DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
- break;
- default:
- /*
- * we know we'll never have a list of rectangles, since ChangeClip
- * immediately turns them into a region
- */
- REGION_DESTROY(pPicture->clientClip);
- break;
- }
- pPicture->clientClip = NULL;
- pPicture->clientClipType = CT_NONE;
- }
- int
- miChangePictureClip(PicturePtr pPicture, int type, pointer value, int n)
- {
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- pointer clientClip;
- int clientClipType;
- switch (type) {
- case CT_PIXMAP:
- /* convert the pixmap to a region */
- clientClip = (pointer) BITMAP_TO_REGION(pScreen, (PixmapPtr) value);
- if (!clientClip)
- return BadAlloc;
- clientClipType = CT_REGION;
- (*pScreen->DestroyPixmap) ((PixmapPtr) value);
- break;
- case CT_REGION:
- clientClip = value;
- clientClipType = CT_REGION;
- break;
- case CT_NONE:
- clientClip = 0;
- clientClipType = CT_NONE;
- break;
- default:
- clientClip = (pointer) RECTS_TO_REGION(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)
- REGION_DESTROY(pPicture->pCompositeClip);
- pPicture->pCompositeClip = pregWin;
- pPicture->freeCompClip = freeTmpClip;
- }
- else {
- /*
- * we need one 'real' region to put into the composite clip. if
- * pregWin the current composite clip are real, we can get rid of
- * one. if pregWin is real and the current composite clip isn't,
- * use pregWin for the composite clip. if the current composite
- * clip is real and pregWin isn't, use the current composite
- * clip. if neither is real, create a new region.
- */
- REGION_TRANSLATE(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
- if (freeCompClip) {
- REGION_INTERSECT(pPicture->pCompositeClip,
- pregWin, pPicture->clientClip);
- if (freeTmpClip)
- REGION_DESTROY(pregWin);
- }
- else if (freeTmpClip) {
- REGION_INTERSECT(pregWin, pregWin,
- pPicture->clientClip);
- pPicture->pCompositeClip = pregWin;
- }
- else {
- pPicture->pCompositeClip =
- REGION_CREATE(NullBox, 0);
- REGION_INTERSECT(pPicture->pCompositeClip, pregWin,
- pPicture->clientClip);
- }
- pPicture->freeCompClip = TRUE;
- REGION_TRANSLATE(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- }
- } /* end of composite clip for a window */
- else {
- BoxRec pixbounds;
- /* XXX should we translate by drawable.x/y here ? */
- /* If you want pixmaps in offscreen memory, yes */
- pixbounds.x1 = pDrawable->x;
- pixbounds.y1 = pDrawable->y;
- pixbounds.x2 = pDrawable->x + pDrawable->width;
- pixbounds.y2 = pDrawable->y + pDrawable->height;
- if (pPicture->freeCompClip) {
- REGION_RESET(pPicture->pCompositeClip, &pixbounds);
- }
- else {
- pPicture->freeCompClip = TRUE;
- pPicture->pCompositeClip =
- REGION_CREATE(&pixbounds, 1);
- }
- if (pPicture->clientClipType == CT_REGION) {
- if (pDrawable->x || pDrawable->y) {
- REGION_TRANSLATE(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
- REGION_INTERSECT(pPicture->pCompositeClip,
- pPicture->pCompositeClip,
- pPicture->clientClip);
- REGION_TRANSLATE(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- }
- else {
- REGION_TRANSLATE(pPicture->pCompositeClip,
- -pPicture->clipOrigin.x,
- -pPicture->clipOrigin.y);
- REGION_INTERSECT(pPicture->pCompositeClip,
- pPicture->pCompositeClip,
- pPicture->clientClip);
- REGION_TRANSLATE(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 Bool
- miClipPictureReg(RegionPtr pRegion, RegionPtr pClip, int dx, int dy)
- {
- if (REGION_NUM_RECTS(pRegion) == 1 && REGION_NUM_RECTS(pClip) == 1) {
- BoxPtr pRbox = REGION_RECTS(pRegion);
- BoxPtr pCbox = REGION_RECTS(pClip);
- 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) {
- REGION_EMPTY(pRegion);
- }
- }
- else if (!REGION_NOTEMPTY(pClip))
- return FALSE;
- else {
- if (dx || dy)
- REGION_TRANSLATE(pRegion, -dx, -dy);
- if (!REGION_INTERSECT(pRegion, pRegion, pClip))
- return FALSE;
- if (dx || dy)
- REGION_TRANSLATE(pRegion, dx, dy);
- }
- return REGION_NOTEMPTY(pRegion);
- }
- static __inline Bool
- miClipPictureSrc(RegionPtr pRegion, PicturePtr pPicture, int dx, int dy)
- {
- /* XXX what to do with clipping from transformed pictures? */
- if (pPicture->transform || !pPicture->pDrawable)
- return TRUE;
- if (pPicture->repeat) {
- if (pPicture->clientClipType != CT_NONE) {
- REGION_TRANSLATE(pRegion,
- dx - pPicture->clipOrigin.x,
- dy - pPicture->clipOrigin.y);
- if (!REGION_INTERSECT(pRegion, pRegion,
- (RegionPtr) pPicture->clientClip))
- return FALSE;
- REGION_TRANSLATE(pRegion,
- -(dx - pPicture->clipOrigin.x),
- -(dy - pPicture->clipOrigin.y));
- }
- return TRUE;
- }
- else {
- return miClipPictureReg(pRegion, pPicture->pCompositeClip, dx, dy);
- }
- }
- static void
- miCompositeSourceValidate(PicturePtr pPicture,
- INT16 x, INT16 y, CARD16 width, CARD16 height)
- {
- DrawablePtr pDrawable = pPicture->pDrawable;
- ScreenPtr pScreen;
- if (!pDrawable)
- return;
- pScreen = pDrawable->pScreen;
- if (pScreen->SourceValidate) {
- x -= pPicture->pDrawable->x;
- y -= pPicture->pDrawable->y;
- if (pPicture->transform) {
- xPoint points[4];
- int i;
- int xmin, ymin, xmax, ymax;
- #define VectorSet(i,_x,_y) { points[i].x = _x; points[i].y = _y; }
- VectorSet(0, x, y);
- VectorSet(1, x + width, y);
- VectorSet(2, x, y + height);
- VectorSet(3, x + width, y + height);
- xmin = ymin = 32767;
- xmax = ymax = -32737;
- for (i = 0; i < 4; i++) {
- PictVector t;
- t.vector[0] = IntToxFixed(points[i].x);
- t.vector[1] = IntToxFixed(points[i].y);
- t.vector[2] = xFixed1;
- if (PictureTransformPoint(pPicture->transform, &t)) {
- int tx = xFixedToInt(t.vector[0]);
- int ty = xFixedToInt(t.vector[1]);
- if (tx < xmin)
- xmin = tx;
- if (tx > xmax)
- xmax = tx;
- if (ty < ymin)
- ymin = ty;
- if (ty > ymax)
- ymax = ty;
- }
- }
- x = xmin;
- y = ymin;
- width = xmax - xmin;
- height = ymax - ymin;
- }
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
- }
- }
- /*
- * returns FALSE if the final region is empty. Indistinguishable from
- * an allocation failure, but rendering ignores those anyways.
- */
- _X_EXPORT Bool
- miComputeCompositeRegion(RegionPtr pRegion,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
- {
- int v;
- pRegion->extents.x1 = xDst;
- v = xDst + width;
- pRegion->extents.x2 = BOUND(v);
- pRegion->extents.y1 = yDst;
- v = yDst + height;
- pRegion->extents.y2 = BOUND(v);
- pRegion->data = 0;
- /* Check for empty operation */
- if (pRegion->extents.x1 >= pRegion->extents.x2 ||
- pRegion->extents.y1 >= pRegion->extents.y2) {
- REGION_EMPTY(pRegion);
- return FALSE;
- }
- /* clip against dst */
- if (!miClipPictureReg(pRegion, pDst->pCompositeClip, 0, 0)) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- if (pDst->alphaMap) {
- if (!miClipPictureReg(pRegion, pDst->alphaMap->pCompositeClip,
- -pDst->alphaOrigin.x, -pDst->alphaOrigin.y)) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- }
- /* clip against src */
- if (!miClipPictureSrc(pRegion, pSrc, xDst - xSrc, yDst - ySrc)) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- if (pSrc->alphaMap) {
- if (!miClipPictureSrc(pRegion, pSrc->alphaMap,
- xDst - (xSrc + pSrc->alphaOrigin.x),
- yDst - (ySrc + pSrc->alphaOrigin.y))) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- }
- /* clip against mask */
- if (pMask) {
- if (!miClipPictureSrc(pRegion, pMask, xDst - xMask, yDst - yMask)) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- if (pMask->alphaMap) {
- if (!miClipPictureSrc(pRegion, pMask->alphaMap,
- xDst - (xMask + pMask->alphaOrigin.x),
- yDst - (yMask + pMask->alphaOrigin.y))) {
- REGION_UNINIT(pRegion);
- return FALSE;
- }
- }
- }
- miCompositeSourceValidate(pSrc, xSrc, ySrc, width, height);
- if (pMask)
- miCompositeSourceValidate(pMask, xMask, yMask, width, height);
- return TRUE;
- }
- void
- miRenderColorToPixel(PictFormatPtr format, xRenderColor * color, CARD32 *pixel)
- {
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
- switch (format->type) {
- case PictTypeDirect:
- r = color->red >> (16 - Ones(format->direct.redMask));
- g = color->green >> (16 - Ones(format->direct.greenMask));
- b = color->blue >> (16 - Ones(format->direct.blueMask));
- a = color->alpha >> (16 - Ones(format->direct.alphaMask));
- r = r << format->direct.red;
- g = g << format->direct.green;
- b = b << format->direct.blue;
- a = a << format->direct.alpha;
- *pixel = r | g | b | a;
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- if (pIndexed->color) {
- r = color->red >> 11;
- g = color->green >> 11;
- b = color->blue >> 11;
- *pixel = miIndexToEnt15(pIndexed, (r << 10) | (g << 5) | b);
- }
- else {
- r = color->red >> 8;
- g = color->green >> 8;
- b = color->blue >> 8;
- *pixel = miIndexToEntY24(pIndexed, (r << 16) | (g << 8) | b);
- }
- break;
- }
- }
- static CARD16
- miFillColor(CARD32 pixel, int bits)
- {
- while (bits < 16) {
- pixel |= pixel << bits;
- bits <<= 1;
- }
- return (CARD16) pixel;
- }
- Bool
- miIsSolidAlpha(PicturePtr pSrc)
- {
- ScreenPtr pScreen;
- char line[1];
- if (!pSrc->pDrawable)
- return FALSE;
- pScreen = pSrc->pDrawable->pScreen;
- /* Alpha-only */
- if (PICT_FORMAT_TYPE(pSrc->format) != PICT_TYPE_A)
- return FALSE;
- /* repeat */
- if (!pSrc->repeat)
- return FALSE;
- /* 1x1 */
- if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
- return FALSE;
- line[0] = 1;
- (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
- switch (pSrc->pDrawable->bitsPerPixel) {
- case 1:
- return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
- case 4:
- return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
- case 8:
- return (CARD8) line[0] == 0xff;
- default:
- return FALSE;
- }
- }
- void
- miRenderPixelToColor(PictFormatPtr format, CARD32 pixel, xRenderColor * color)
- {
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
- switch (format->type) {
- case PictTypeDirect:
- r = (pixel >> format->direct.red) & format->direct.redMask;
- g = (pixel >> format->direct.green) & format->direct.greenMask;
- b = (pixel >> format->direct.blue) & format->direct.blueMask;
- a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
- color->red = miFillColor(r, Ones(format->direct.redMask));
- color->green = miFillColor(g, Ones(format->direct.greenMask));
- color->blue = miFillColor(b, Ones(format->direct.blueMask));
- color->alpha = miFillColor(a, Ones(format->direct.alphaMask));
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED - 1)];
- r = (pixel >> 16) & 0xff;
- g = (pixel >> 8) & 0xff;
- b = (pixel) & 0xff;
- color->red = miFillColor(r, 8);
- color->green = miFillColor(g, 8);
- color->blue = miFillColor(b, 8);
- color->alpha = 0xffff;
- break;
- }
- }
- _X_EXPORT Bool
- miPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
- {
- PictureScreenPtr ps;
- if (!PictureInit(pScreen, formats, nformats))
- return FALSE;
- ps = GetPictureScreen(pScreen);
- ps->CreatePicture = miCreatePicture;
- ps->DestroyPicture = miDestroyPicture;
- ps->ChangePictureClip = miChangePictureClip;
- ps->DestroyPictureClip = miDestroyPictureClip;
- ps->ChangePicture = miChangePicture;
- ps->ValidatePicture = miValidatePicture;
- ps->InitIndexed = miInitIndexed;
- ps->CloseIndexed = miCloseIndexed;
- ps->UpdateIndexed = miUpdateIndexed;
- ps->ChangePictureTransform = miChangePictureTransform;
- ps->ChangePictureFilter = miChangePictureFilter;
- ps->RealizeGlyph = miRealizeGlyph;
- ps->UnrealizeGlyph = miUnrealizeGlyph;
- /* MI rendering routines */
- ps->Composite = 0; /* requires DDX support */
- ps->Glyphs = miGlyphs;
- ps->CompositeRects = miCompositeRects;
- ps->Trapezoids = miTrapezoids;
- ps->Triangles = miTriangles;
- ps->TriStrip = miTriStrip;
- ps->TriFan = miTriFan;
- ps->RasterizeTrapezoid = 0; /* requires DDX support */
- ps->AddTraps = 0; /* requires DDX support */
- ps->AddTriangles = 0; /* requires DDX support */
- return TRUE;
- }
|