aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/render/mipict.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/render/mipict.c')
-rw-r--r--xorg-server/render/mipict.c1216
1 files changed, 606 insertions, 610 deletions
diff --git a/xorg-server/render/mipict.c b/xorg-server/render/mipict.c
index 1623b335f..9a44c2729 100644
--- a/xorg-server/render/mipict.c
+++ b/xorg-server/render/mipict.c
@@ -1,610 +1,606 @@
-/*
- *
- * 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)
- RegionDestroy(pPicture->pCompositeClip);
-}
-
-void
-miDestroyPictureClip (PicturePtr pPicture)
-{
- switch (pPicture->clientClipType) {
- case CT_NONE:
- return;
- case CT_PIXMAP:
- (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
- break;
- default:
- /*
- * we know we'll never have a list of rectangles, since ChangeClip
- * immediately turns them into a region
- */
- RegionDestroy(pPicture->clientClip);
- break;
- }
- pPicture->clientClip = NULL;
- pPicture->clientClipType = CT_NONE;
-}
-
-int
-miChangePictureClip (PicturePtr pPicture,
- int type,
- pointer value,
- int n)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- pointer clientClip;
- int clientClipType;
-
- switch (type) {
- case CT_PIXMAP:
- /* convert the pixmap to a region */
- clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value);
- if (!clientClip)
- return BadAlloc;
- clientClipType = CT_REGION;
- (*pScreen->DestroyPixmap) ((PixmapPtr) value);
- break;
- case CT_REGION:
- clientClip = value;
- clientClipType = CT_REGION;
- break;
- case CT_NONE:
- clientClip = 0;
- clientClipType = CT_NONE;
- break;
- default:
- clientClip = (pointer) RegionFromRects(n,
- (xRectangle *) value,
- type);
- if (!clientClip)
- return BadAlloc;
- clientClipType = CT_REGION;
- free(value);
- break;
- }
- (*ps->DestroyPictureClip) (pPicture);
- pPicture->clientClip = clientClip;
- pPicture->clientClipType = clientClipType;
- pPicture->stateChanges |= CPClipMask;
- return Success;
-}
-
-void
-miChangePicture (PicturePtr pPicture,
- Mask mask)
-{
- return;
-}
-
-void
-miValidatePicture (PicturePtr pPicture,
- Mask mask)
-{
- DrawablePtr pDrawable = pPicture->pDrawable;
-
- if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
- (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
- {
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWin = (WindowPtr) pDrawable;
- RegionPtr pregWin;
- Bool freeTmpClip, freeCompClip;
-
- if (pPicture->subWindowMode == IncludeInferiors)
- {
- pregWin = NotClippedByChildren(pWin);
- freeTmpClip = TRUE;
- }
- else
- {
- pregWin = &pWin->clipList;
- freeTmpClip = FALSE;
- }
- freeCompClip = pPicture->freeCompClip;
-
- /*
- * if there is no client clip, we can get by with just keeping the
- * pointer we got, and remembering whether or not should destroy
- * (or maybe re-use) it later. this way, we avoid unnecessary
- * copying of regions. (this wins especially if many clients clip
- * by children and have no client clip.)
- */
- if (pPicture->clientClipType == CT_NONE)
- {
- if (freeCompClip)
- RegionDestroy(pPicture->pCompositeClip);
- pPicture->pCompositeClip = pregWin;
- pPicture->freeCompClip = freeTmpClip;
- }
- else
- {
- /*
- * we need one 'real' region to put into the composite clip. if
- * pregWin the current composite clip are real, we can get rid of
- * one. if pregWin is real and the current composite clip isn't,
- * use pregWin for the composite clip. if the current composite
- * clip is real and pregWin isn't, use the current composite
- * clip. if neither is real, create a new region.
- */
-
- RegionTranslate(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
-
- if (freeCompClip)
- {
- RegionIntersect(pPicture->pCompositeClip,
- pregWin, pPicture->clientClip);
- if (freeTmpClip)
- RegionDestroy(pregWin);
- }
- else if (freeTmpClip)
- {
- RegionIntersect(pregWin, pregWin, pPicture->clientClip);
- pPicture->pCompositeClip = pregWin;
- }
- else
- {
- pPicture->pCompositeClip = RegionCreate(NullBox, 0);
- RegionIntersect(pPicture->pCompositeClip,
- pregWin, pPicture->clientClip);
- }
- pPicture->freeCompClip = TRUE;
- RegionTranslate(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- }
- } /* end of composite clip for a window */
- else
- {
- BoxRec pixbounds;
-
- /* XXX should we translate by drawable.x/y here ? */
- /* If you want pixmaps in offscreen memory, yes */
- pixbounds.x1 = pDrawable->x;
- pixbounds.y1 = pDrawable->y;
- pixbounds.x2 = pDrawable->x + pDrawable->width;
- pixbounds.y2 = pDrawable->y + pDrawable->height;
-
- if (pPicture->freeCompClip)
- {
- RegionReset(pPicture->pCompositeClip, &pixbounds);
- }
- else
- {
- pPicture->freeCompClip = TRUE;
- pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
- }
-
- if (pPicture->clientClipType == CT_REGION)
- {
- if(pDrawable->x || pDrawable->y) {
- RegionTranslate(pPicture->clientClip,
- pDrawable->x + pPicture->clipOrigin.x,
- pDrawable->y + pPicture->clipOrigin.y);
- RegionIntersect(pPicture->pCompositeClip,
- pPicture->pCompositeClip, pPicture->clientClip);
- RegionTranslate(pPicture->clientClip,
- -(pDrawable->x + pPicture->clipOrigin.x),
- -(pDrawable->y + pPicture->clipOrigin.y));
- } else {
- RegionTranslate(pPicture->pCompositeClip,
- -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
- RegionIntersect(pPicture->pCompositeClip,
- pPicture->pCompositeClip, pPicture->clientClip);
- RegionTranslate(pPicture->pCompositeClip,
- pPicture->clipOrigin.x, pPicture->clipOrigin.y);
- }
- }
- } /* end of composite clip for pixmap */
- }
-}
-
-int
-miChangePictureTransform (PicturePtr pPicture,
- PictTransform *transform)
-{
- return Success;
-}
-
-int
-miChangePictureFilter (PicturePtr pPicture,
- int filter,
- xFixed *params,
- int nparams)
-{
- return Success;
-}
-
-#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
-
-static inline pixman_bool_t
-miClipPictureReg (pixman_region16_t * pRegion,
- pixman_region16_t * pClip,
- int dx,
- int dy)
-{
- if (pixman_region_n_rects(pRegion) == 1 &&
- pixman_region_n_rects(pClip) == 1)
- {
- pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
- pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL);
- int v;
-
- if (pRbox->x1 < (v = pCbox->x1 + dx))
- pRbox->x1 = BOUND(v);
- if (pRbox->x2 > (v = pCbox->x2 + dx))
- pRbox->x2 = BOUND(v);
- if (pRbox->y1 < (v = pCbox->y1 + dy))
- pRbox->y1 = BOUND(v);
- if (pRbox->y2 > (v = pCbox->y2 + dy))
- pRbox->y2 = BOUND(v);
- if (pRbox->x1 >= pRbox->x2 ||
- pRbox->y1 >= pRbox->y2)
- {
- pixman_region_init (pRegion);
- }
- }
- else if (!pixman_region_not_empty (pClip))
- return FALSE;
- else
- {
- if (dx || dy)
- pixman_region_translate (pRegion, -dx, -dy);
- if (!pixman_region_intersect (pRegion, pRegion, pClip))
- return FALSE;
- if (dx || dy)
- pixman_region_translate(pRegion, dx, dy);
- }
- return pixman_region_not_empty(pRegion);
-}
-
-static __inline Bool
-miClipPictureSrc (RegionPtr pRegion,
- PicturePtr pPicture,
- int dx,
- int dy)
-{
- if (pPicture->clientClipType != CT_NONE)
- {
- Bool result;
-
- pixman_region_translate ( pPicture->clientClip,
- pPicture->clipOrigin.x + dx,
- pPicture->clipOrigin.y + dy);
-
- result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
-
- pixman_region_translate ( pPicture->clientClip,
- - (pPicture->clipOrigin.x + dx),
- - (pPicture->clipOrigin.y + dy));
-
- if (!result)
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-SourceValidateOnePicture (PicturePtr pPicture)
-{
- DrawablePtr pDrawable = pPicture->pDrawable;
- ScreenPtr pScreen;
-
- if (!pDrawable)
- return;
-
- pScreen = pDrawable->pScreen;
-
- if (pScreen->SourceValidate)
- {
- pScreen->SourceValidate (
- pDrawable, 0, 0, pDrawable->width, pDrawable->height, pPicture->subWindowMode);
- }
-}
-
-void
-miCompositeSourceValidate (PicturePtr pPicture)
-{
- SourceValidateOnePicture (pPicture);
- if (pPicture->alphaMap)
- SourceValidateOnePicture (pPicture->alphaMap);
-}
-
-/*
- * returns FALSE if the final region is empty. Indistinguishable from
- * an allocation failure, but rendering ignores those anyways.
- */
-
-Bool
-miComputeCompositeRegion (RegionPtr pRegion,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
-{
-
- int v;
-
- pRegion->extents.x1 = xDst;
- v = xDst + width;
- pRegion->extents.x2 = BOUND(v);
- pRegion->extents.y1 = yDst;
- v = yDst + height;
- pRegion->extents.y2 = BOUND(v);
- pRegion->data = 0;
- /* Check for empty operation */
- if (pRegion->extents.x1 >= pRegion->extents.x2 ||
- pRegion->extents.y1 >= pRegion->extents.y2)
- {
- pixman_region_init (pRegion);
- return FALSE;
- }
- /* clip against dst */
- if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pDst->alphaMap)
- {
- if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
- -pDst->alphaOrigin.x,
- -pDst->alphaOrigin.y))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against src */
- if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pSrc->alphaMap)
- {
- if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
- xDst - (xSrc - pSrc->alphaOrigin.x),
- yDst - (ySrc - pSrc->alphaOrigin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- /* clip against mask */
- if (pMask)
- {
- if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- if (pMask->alphaMap)
- {
- if (!miClipPictureSrc (pRegion, pMask->alphaMap,
- xDst - (xMask - pMask->alphaOrigin.x),
- yDst - (yMask - pMask->alphaOrigin.y)))
- {
- pixman_region_fini (pRegion);
- return FALSE;
- }
- }
- }
-
-
- miCompositeSourceValidate (pSrc);
- if (pMask)
- miCompositeSourceValidate (pMask);
-
- return TRUE;
-}
-
-void
-miRenderColorToPixel (PictFormatPtr format,
- xRenderColor *color,
- CARD32 *pixel)
-{
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
-
- switch (format->type) {
- case PictTypeDirect:
- r = color->red >> (16 - Ones (format->direct.redMask));
- g = color->green >> (16 - Ones (format->direct.greenMask));
- b = color->blue >> (16 - Ones (format->direct.blueMask));
- a = color->alpha >> (16 - Ones (format->direct.alphaMask));
- r = r << format->direct.red;
- g = g << format->direct.green;
- b = b << format->direct.blue;
- a = a << format->direct.alpha;
- *pixel = r|g|b|a;
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- if (pIndexed->color)
- {
- r = color->red >> 11;
- g = color->green >> 11;
- b = color->blue >> 11;
- *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
- }
- else
- {
- r = color->red >> 8;
- g = color->green >> 8;
- b = color->blue >> 8;
- *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
- }
- break;
- }
-}
-
-static CARD16
-miFillColor (CARD32 pixel, int bits)
-{
- while (bits < 16)
- {
- pixel |= pixel << bits;
- bits <<= 1;
- }
- return (CARD16) pixel;
-}
-
-Bool
-miIsSolidAlpha (PicturePtr pSrc)
-{
- ScreenPtr pScreen;
- char line[1];
-
- if (!pSrc->pDrawable)
- return FALSE;
-
- pScreen = pSrc->pDrawable->pScreen;
-
- /* Alpha-only */
- if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
- return FALSE;
- /* repeat */
- if (!pSrc->repeat)
- return FALSE;
- /* 1x1 */
- if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
- return FALSE;
- line[0] = 1;
- (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
- switch (pSrc->pDrawable->bitsPerPixel) {
- case 1:
- return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
- case 4:
- return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
- case 8:
- return (CARD8) line[0] == 0xff;
- default:
- return FALSE;
- }
-}
-
-void
-miRenderPixelToColor (PictFormatPtr format,
- CARD32 pixel,
- xRenderColor *color)
-{
- CARD32 r, g, b, a;
- miIndexedPtr pIndexed;
-
- switch (format->type) {
- case PictTypeDirect:
- r = (pixel >> format->direct.red) & format->direct.redMask;
- g = (pixel >> format->direct.green) & format->direct.greenMask;
- b = (pixel >> format->direct.blue) & format->direct.blueMask;
- a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
- color->red = miFillColor (r, Ones (format->direct.redMask));
- color->green = miFillColor (g, Ones (format->direct.greenMask));
- color->blue = miFillColor (b, Ones (format->direct.blueMask));
- color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
- break;
- case PictTypeIndexed:
- pIndexed = (miIndexedPtr) (format->index.devPrivate);
- pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
- r = (pixel >> 16) & 0xff;
- g = (pixel >> 8) & 0xff;
- b = (pixel ) & 0xff;
- color->red = miFillColor (r, 8);
- color->green = miFillColor (g, 8);
- color->blue = miFillColor (b, 8);
- color->alpha = 0xffff;
- break;
- }
-}
-
-Bool
-miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
-{
- PictureScreenPtr ps;
-
- if (!PictureInit (pScreen, formats, nformats))
- return FALSE;
- ps = GetPictureScreen(pScreen);
- ps->CreatePicture = miCreatePicture;
- ps->DestroyPicture = miDestroyPicture;
- ps->ChangePictureClip = miChangePictureClip;
- ps->DestroyPictureClip = miDestroyPictureClip;
- ps->ChangePicture = miChangePicture;
- ps->ValidatePicture = miValidatePicture;
- ps->InitIndexed = miInitIndexed;
- ps->CloseIndexed = miCloseIndexed;
- ps->UpdateIndexed = miUpdateIndexed;
- ps->ChangePictureTransform = miChangePictureTransform;
- ps->ChangePictureFilter = miChangePictureFilter;
- ps->RealizeGlyph = miRealizeGlyph;
- ps->UnrealizeGlyph = miUnrealizeGlyph;
-
- /* MI rendering routines */
- ps->Composite = 0; /* requires DDX support */
- ps->Glyphs = miGlyphs;
- ps->CompositeRects = miCompositeRects;
- ps->Trapezoids = 0;
- ps->Triangles = 0;
-
- ps->RasterizeTrapezoid = 0; /* requires DDX support */
- ps->AddTraps = 0; /* requires DDX support */
- ps->AddTriangles = 0; /* requires DDX support */
-
- return TRUE;
-}
+/*
+ *
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "picturestr.h"
+#include "mipict.h"
+
+int
+miCreatePicture (PicturePtr pPicture)
+{
+ return Success;
+}
+
+void
+miDestroyPicture (PicturePtr pPicture)
+{
+ if (pPicture->freeCompClip)
+ RegionDestroy(pPicture->pCompositeClip);
+}
+
+void
+miDestroyPictureClip (PicturePtr pPicture)
+{
+ switch (pPicture->clientClipType) {
+ case CT_NONE:
+ return;
+ case CT_PIXMAP:
+ (*pPicture->pDrawable->pScreen->DestroyPixmap) ((PixmapPtr) (pPicture->clientClip));
+ break;
+ default:
+ /*
+ * we know we'll never have a list of rectangles, since ChangeClip
+ * immediately turns them into a region
+ */
+ RegionDestroy(pPicture->clientClip);
+ break;
+ }
+ pPicture->clientClip = NULL;
+ pPicture->clientClipType = CT_NONE;
+}
+
+int
+miChangePictureClip (PicturePtr pPicture,
+ int type,
+ pointer value,
+ int n)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ pointer clientClip;
+ int clientClipType;
+
+ switch (type) {
+ case CT_PIXMAP:
+ /* convert the pixmap to a region */
+ clientClip = (pointer) BitmapToRegion(pScreen, (PixmapPtr) value);
+ if (!clientClip)
+ return BadAlloc;
+ clientClipType = CT_REGION;
+ (*pScreen->DestroyPixmap) ((PixmapPtr) value);
+ break;
+ case CT_REGION:
+ clientClip = value;
+ clientClipType = CT_REGION;
+ break;
+ case CT_NONE:
+ clientClip = 0;
+ clientClipType = CT_NONE;
+ break;
+ default:
+ clientClip = (pointer) RegionFromRects(n,
+ (xRectangle *) value,
+ type);
+ if (!clientClip)
+ return BadAlloc;
+ clientClipType = CT_REGION;
+ free(value);
+ break;
+ }
+ (*ps->DestroyPictureClip) (pPicture);
+ pPicture->clientClip = clientClip;
+ pPicture->clientClipType = clientClipType;
+ pPicture->stateChanges |= CPClipMask;
+ return Success;
+}
+
+void
+miChangePicture (PicturePtr pPicture,
+ Mask mask)
+{
+ return;
+}
+
+void
+miValidatePicture (PicturePtr pPicture,
+ Mask mask)
+{
+ DrawablePtr pDrawable = pPicture->pDrawable;
+
+ if ((mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)) ||
+ (pDrawable->serialNumber != (pPicture->serialNumber & DRAWABLE_SERIAL_BITS)))
+ {
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ RegionPtr pregWin;
+ Bool freeTmpClip, freeCompClip;
+
+ if (pPicture->subWindowMode == IncludeInferiors)
+ {
+ pregWin = NotClippedByChildren(pWin);
+ freeTmpClip = TRUE;
+ }
+ else
+ {
+ pregWin = &pWin->clipList;
+ freeTmpClip = FALSE;
+ }
+ freeCompClip = pPicture->freeCompClip;
+
+ /*
+ * if there is no client clip, we can get by with just keeping the
+ * pointer we got, and remembering whether or not should destroy
+ * (or maybe re-use) it later. this way, we avoid unnecessary
+ * copying of regions. (this wins especially if many clients clip
+ * by children and have no client clip.)
+ */
+ if (pPicture->clientClipType == CT_NONE)
+ {
+ if (freeCompClip)
+ RegionDestroy(pPicture->pCompositeClip);
+ pPicture->pCompositeClip = pregWin;
+ pPicture->freeCompClip = freeTmpClip;
+ }
+ else
+ {
+ /*
+ * we need one 'real' region to put into the composite clip. if
+ * pregWin the current composite clip are real, we can get rid of
+ * one. if pregWin is real and the current composite clip isn't,
+ * use pregWin for the composite clip. if the current composite
+ * clip is real and pregWin isn't, use the current composite
+ * clip. if neither is real, create a new region.
+ */
+
+ RegionTranslate(pPicture->clientClip,
+ pDrawable->x + pPicture->clipOrigin.x,
+ pDrawable->y + pPicture->clipOrigin.y);
+
+ if (freeCompClip)
+ {
+ RegionIntersect(pPicture->pCompositeClip,
+ pregWin, pPicture->clientClip);
+ if (freeTmpClip)
+ RegionDestroy(pregWin);
+ }
+ else if (freeTmpClip)
+ {
+ RegionIntersect(pregWin, pregWin, pPicture->clientClip);
+ pPicture->pCompositeClip = pregWin;
+ }
+ else
+ {
+ pPicture->pCompositeClip = RegionCreate(NullBox, 0);
+ RegionIntersect(pPicture->pCompositeClip,
+ pregWin, pPicture->clientClip);
+ }
+ pPicture->freeCompClip = TRUE;
+ RegionTranslate(pPicture->clientClip,
+ -(pDrawable->x + pPicture->clipOrigin.x),
+ -(pDrawable->y + pPicture->clipOrigin.y));
+ }
+ } /* end of composite clip for a window */
+ else
+ {
+ BoxRec pixbounds;
+
+ /* XXX should we translate by drawable.x/y here ? */
+ /* If you want pixmaps in offscreen memory, yes */
+ pixbounds.x1 = pDrawable->x;
+ pixbounds.y1 = pDrawable->y;
+ pixbounds.x2 = pDrawable->x + pDrawable->width;
+ pixbounds.y2 = pDrawable->y + pDrawable->height;
+
+ if (pPicture->freeCompClip)
+ {
+ RegionReset(pPicture->pCompositeClip, &pixbounds);
+ }
+ else
+ {
+ pPicture->freeCompClip = TRUE;
+ pPicture->pCompositeClip = RegionCreate(&pixbounds, 1);
+ }
+
+ if (pPicture->clientClipType == CT_REGION)
+ {
+ if(pDrawable->x || pDrawable->y) {
+ RegionTranslate(pPicture->clientClip,
+ pDrawable->x + pPicture->clipOrigin.x,
+ pDrawable->y + pPicture->clipOrigin.y);
+ RegionIntersect(pPicture->pCompositeClip,
+ pPicture->pCompositeClip, pPicture->clientClip);
+ RegionTranslate(pPicture->clientClip,
+ -(pDrawable->x + pPicture->clipOrigin.x),
+ -(pDrawable->y + pPicture->clipOrigin.y));
+ } else {
+ RegionTranslate(pPicture->pCompositeClip,
+ -pPicture->clipOrigin.x, -pPicture->clipOrigin.y);
+ RegionIntersect(pPicture->pCompositeClip,
+ pPicture->pCompositeClip, pPicture->clientClip);
+ RegionTranslate(pPicture->pCompositeClip,
+ pPicture->clipOrigin.x, pPicture->clipOrigin.y);
+ }
+ }
+ } /* end of composite clip for pixmap */
+ }
+}
+
+int
+miChangePictureTransform (PicturePtr pPicture,
+ PictTransform *transform)
+{
+ return Success;
+}
+
+int
+miChangePictureFilter (PicturePtr pPicture,
+ int filter,
+ xFixed *params,
+ int nparams)
+{
+ return Success;
+}
+
+#define BOUND(v) (INT16) ((v) < MINSHORT ? MINSHORT : (v) > MAXSHORT ? MAXSHORT : (v))
+
+static inline pixman_bool_t
+miClipPictureReg (pixman_region16_t * pRegion,
+ pixman_region16_t * pClip,
+ int dx,
+ int dy)
+{
+ if (pixman_region_n_rects(pRegion) == 1 &&
+ pixman_region_n_rects(pClip) == 1)
+ {
+ pixman_box16_t * pRbox = pixman_region_rectangles(pRegion, NULL);
+ pixman_box16_t * pCbox = pixman_region_rectangles(pClip, NULL);
+ int v;
+
+ if (pRbox->x1 < (v = pCbox->x1 + dx))
+ pRbox->x1 = BOUND(v);
+ if (pRbox->x2 > (v = pCbox->x2 + dx))
+ pRbox->x2 = BOUND(v);
+ if (pRbox->y1 < (v = pCbox->y1 + dy))
+ pRbox->y1 = BOUND(v);
+ if (pRbox->y2 > (v = pCbox->y2 + dy))
+ pRbox->y2 = BOUND(v);
+ if (pRbox->x1 >= pRbox->x2 ||
+ pRbox->y1 >= pRbox->y2)
+ {
+ pixman_region_init (pRegion);
+ }
+ }
+ else if (!pixman_region_not_empty (pClip))
+ return FALSE;
+ else
+ {
+ if (dx || dy)
+ pixman_region_translate (pRegion, -dx, -dy);
+ if (!pixman_region_intersect (pRegion, pRegion, pClip))
+ return FALSE;
+ if (dx || dy)
+ pixman_region_translate(pRegion, dx, dy);
+ }
+ return pixman_region_not_empty(pRegion);
+}
+
+static inline Bool
+miClipPictureSrc (RegionPtr pRegion,
+ PicturePtr pPicture,
+ int dx,
+ int dy)
+{
+ if (pPicture->clientClipType != CT_NONE)
+ {
+ Bool result;
+
+ pixman_region_translate ( pPicture->clientClip,
+ pPicture->clipOrigin.x + dx,
+ pPicture->clipOrigin.y + dy);
+
+ result = RegionIntersect(pRegion, pRegion, pPicture->clientClip);
+
+ pixman_region_translate ( pPicture->clientClip,
+ - (pPicture->clipOrigin.x + dx),
+ - (pPicture->clipOrigin.y + dy));
+
+ if (!result)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+SourceValidateOnePicture (PicturePtr pPicture)
+{
+ DrawablePtr pDrawable = pPicture->pDrawable;
+ ScreenPtr pScreen;
+
+ if (!pDrawable)
+ return;
+
+ pScreen = pDrawable->pScreen;
+
+ if (pScreen->SourceValidate)
+ {
+ pScreen->SourceValidate (
+ pDrawable, 0, 0, pDrawable->width, pDrawable->height, pPicture->subWindowMode);
+ }
+}
+
+void
+miCompositeSourceValidate (PicturePtr pPicture)
+{
+ SourceValidateOnePicture (pPicture);
+ if (pPicture->alphaMap)
+ SourceValidateOnePicture (pPicture->alphaMap);
+}
+
+/*
+ * returns FALSE if the final region is empty. Indistinguishable from
+ * an allocation failure, but rendering ignores those anyways.
+ */
+
+Bool
+miComputeCompositeRegion (RegionPtr pRegion,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+
+ int v;
+
+ pRegion->extents.x1 = xDst;
+ v = xDst + width;
+ pRegion->extents.x2 = BOUND(v);
+ pRegion->extents.y1 = yDst;
+ v = yDst + height;
+ pRegion->extents.y2 = BOUND(v);
+ pRegion->data = 0;
+ /* Check for empty operation */
+ if (pRegion->extents.x1 >= pRegion->extents.x2 ||
+ pRegion->extents.y1 >= pRegion->extents.y2)
+ {
+ pixman_region_init (pRegion);
+ return FALSE;
+ }
+ /* clip against dst */
+ if (!miClipPictureReg (pRegion, pDst->pCompositeClip, 0, 0))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pDst->alphaMap)
+ {
+ if (!miClipPictureReg (pRegion, pDst->alphaMap->pCompositeClip,
+ -pDst->alphaOrigin.x,
+ -pDst->alphaOrigin.y))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ /* clip against src */
+ if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pSrc->alphaMap)
+ {
+ if (!miClipPictureSrc (pRegion, pSrc->alphaMap,
+ xDst - (xSrc - pSrc->alphaOrigin.x),
+ yDst - (ySrc - pSrc->alphaOrigin.y)))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ /* clip against mask */
+ if (pMask)
+ {
+ if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ if (pMask->alphaMap)
+ {
+ if (!miClipPictureSrc (pRegion, pMask->alphaMap,
+ xDst - (xMask - pMask->alphaOrigin.x),
+ yDst - (yMask - pMask->alphaOrigin.y)))
+ {
+ pixman_region_fini (pRegion);
+ return FALSE;
+ }
+ }
+ }
+
+
+ miCompositeSourceValidate (pSrc);
+ if (pMask)
+ miCompositeSourceValidate (pMask);
+
+ return TRUE;
+}
+
+void
+miRenderColorToPixel (PictFormatPtr format,
+ xRenderColor *color,
+ CARD32 *pixel)
+{
+ CARD32 r, g, b, a;
+ miIndexedPtr pIndexed;
+
+ switch (format->type) {
+ case PictTypeDirect:
+ r = color->red >> (16 - Ones (format->direct.redMask));
+ g = color->green >> (16 - Ones (format->direct.greenMask));
+ b = color->blue >> (16 - Ones (format->direct.blueMask));
+ a = color->alpha >> (16 - Ones (format->direct.alphaMask));
+ r = r << format->direct.red;
+ g = g << format->direct.green;
+ b = b << format->direct.blue;
+ a = a << format->direct.alpha;
+ *pixel = r|g|b|a;
+ break;
+ case PictTypeIndexed:
+ pIndexed = (miIndexedPtr) (format->index.devPrivate);
+ if (pIndexed->color)
+ {
+ r = color->red >> 11;
+ g = color->green >> 11;
+ b = color->blue >> 11;
+ *pixel = miIndexToEnt15 (pIndexed, (r << 10) | (g << 5) | b);
+ }
+ else
+ {
+ r = color->red >> 8;
+ g = color->green >> 8;
+ b = color->blue >> 8;
+ *pixel = miIndexToEntY24 (pIndexed, (r << 16) | (g << 8) | b);
+ }
+ break;
+ }
+}
+
+static CARD16
+miFillColor (CARD32 pixel, int bits)
+{
+ while (bits < 16)
+ {
+ pixel |= pixel << bits;
+ bits <<= 1;
+ }
+ return (CARD16) pixel;
+}
+
+Bool
+miIsSolidAlpha (PicturePtr pSrc)
+{
+ ScreenPtr pScreen;
+ char line[1];
+
+ if (!pSrc->pDrawable)
+ return FALSE;
+
+ pScreen = pSrc->pDrawable->pScreen;
+
+ /* Alpha-only */
+ if (PICT_FORMAT_TYPE (pSrc->format) != PICT_TYPE_A)
+ return FALSE;
+ /* repeat */
+ if (!pSrc->repeat)
+ return FALSE;
+ /* 1x1 */
+ if (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1)
+ return FALSE;
+ line[0] = 1;
+ (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, 1, 1, ZPixmap, ~0L, line);
+ switch (pSrc->pDrawable->bitsPerPixel) {
+ case 1:
+ return (CARD8) line[0] == 1 || (CARD8) line[0] == 0x80;
+ case 4:
+ return (CARD8) line[0] == 0xf || (CARD8) line[0] == 0xf0;
+ case 8:
+ return (CARD8) line[0] == 0xff;
+ default:
+ return FALSE;
+ }
+}
+
+void
+miRenderPixelToColor (PictFormatPtr format,
+ CARD32 pixel,
+ xRenderColor *color)
+{
+ CARD32 r, g, b, a;
+ miIndexedPtr pIndexed;
+
+ switch (format->type) {
+ case PictTypeDirect:
+ r = (pixel >> format->direct.red) & format->direct.redMask;
+ g = (pixel >> format->direct.green) & format->direct.greenMask;
+ b = (pixel >> format->direct.blue) & format->direct.blueMask;
+ a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
+ color->red = miFillColor (r, Ones (format->direct.redMask));
+ color->green = miFillColor (g, Ones (format->direct.greenMask));
+ color->blue = miFillColor (b, Ones (format->direct.blueMask));
+ color->alpha = miFillColor (a, Ones (format->direct.alphaMask));
+ break;
+ case PictTypeIndexed:
+ pIndexed = (miIndexedPtr) (format->index.devPrivate);
+ pixel = pIndexed->rgba[pixel & (MI_MAX_INDEXED-1)];
+ r = (pixel >> 16) & 0xff;
+ g = (pixel >> 8) & 0xff;
+ b = (pixel ) & 0xff;
+ color->red = miFillColor (r, 8);
+ color->green = miFillColor (g, 8);
+ color->blue = miFillColor (b, 8);
+ color->alpha = 0xffff;
+ break;
+ }
+}
+
+Bool
+miPictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ PictureScreenPtr ps;
+
+ if (!PictureInit (pScreen, formats, nformats))
+ return FALSE;
+ ps = GetPictureScreen(pScreen);
+ ps->CreatePicture = miCreatePicture;
+ ps->DestroyPicture = miDestroyPicture;
+ ps->ChangePictureClip = miChangePictureClip;
+ ps->DestroyPictureClip = miDestroyPictureClip;
+ ps->ChangePicture = miChangePicture;
+ ps->ValidatePicture = miValidatePicture;
+ ps->InitIndexed = miInitIndexed;
+ ps->CloseIndexed = miCloseIndexed;
+ ps->UpdateIndexed = miUpdateIndexed;
+ ps->ChangePictureTransform = miChangePictureTransform;
+ ps->ChangePictureFilter = miChangePictureFilter;
+ ps->RealizeGlyph = miRealizeGlyph;
+ ps->UnrealizeGlyph = miUnrealizeGlyph;
+
+ /* MI rendering routines */
+ ps->Composite = 0; /* requires DDX support */
+ ps->Glyphs = miGlyphs;
+ ps->CompositeRects = miCompositeRects;
+ ps->Trapezoids = 0;
+ ps->Triangles = 0;
+
+ ps->RasterizeTrapezoid = 0; /* requires DDX support */
+ ps->AddTraps = 0; /* requires DDX support */
+ ps->AddTriangles = 0; /* requires DDX support */
+
+ return TRUE;
+}