/* * Copyright © 2004 Eric Anholt * * 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 Eric Anholt not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Eric Anholt makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ERIC ANHOLT 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. */ /* $Header: /cvs/xorg/xc/programs/Xserver/miext/cw/cw_render.c,v 1.14 2005/07/03 07:02:01 daniels Exp $ */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif #include <string.h> #include "gcstruct.h" #include "windowstr.h" #include "cw.h" #ifdef RENDER #define cwPsDecl(pScreen) \ PictureScreenPtr ps = GetPictureScreen (pScreen); \ cwScreenPtr pCwScreen = getCwScreen (pScreen) #define cwPicturePrivate \ cwPicturePtr pPicturePrivate = getCwPicture(pPicture) #define cwSrcPictureDecl \ int src_picture_x_off, src_picture_y_off; \ PicturePtr pBackingSrcPicture = cwGetBackingPicture(pSrcPicture, \ &src_picture_x_off,\ &src_picture_y_off) #define cwDstPictureDecl \ int dst_picture_x_off, dst_picture_y_off; \ PicturePtr pBackingDstPicture = cwGetBackingPicture(pDstPicture, \ &dst_picture_x_off,\ &dst_picture_y_off) #define cwMskPictureDecl \ int msk_picture_x_off = 0, msk_picture_y_off = 0; \ PicturePtr pBackingMskPicture = (!pMskPicture ? 0 : \ cwGetBackingPicture(pMskPicture, \ &msk_picture_x_off,\ &msk_picture_y_off)) #define cwPsUnwrap(elt) { \ ps->elt = pCwScreen->elt; \ } #define cwPsWrap(elt,func) { \ pCwScreen->elt = ps->elt; \ ps->elt = func; \ } static cwPicturePtr cwCreatePicturePrivate (PicturePtr pPicture) { WindowPtr pWindow = (WindowPtr) pPicture->pDrawable; PixmapPtr pPixmap = getCwPixmap (pWindow); int error; cwPicturePtr pPicturePrivate; pPicturePrivate = malloc (sizeof (cwPictureRec)); if (!pPicturePrivate) return NULL; pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable, pPicture->pFormat, 0, 0, serverClient, &error); if (!pPicturePrivate->pBackingPicture) { free (pPicturePrivate); return NULL; } /* * Ensure that this serial number does not match the window's */ pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber; pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1; setCwPicture(pPicture, pPicturePrivate); return pPicturePrivate; } static void cwDestroyPicturePrivate (PicturePtr pPicture) { cwPicturePrivate; if (pPicturePrivate) { if (pPicturePrivate->pBackingPicture) FreePicture (pPicturePrivate->pBackingPicture, 0); free (pPicturePrivate); setCwPicture(pPicture, NULL); } } static PicturePtr cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off) { cwPicturePrivate; if (pPicturePrivate) { DrawablePtr pDrawable = pPicture->pDrawable; WindowPtr pWindow = (WindowPtr) pDrawable; PixmapPtr pPixmap = getCwPixmap (pWindow); *x_off = pDrawable->x - pPixmap->screen_x; *y_off = pDrawable->y - pPixmap->screen_y; return pPicturePrivate->pBackingPicture; } else { *x_off = *y_off = 0; return pPicture; } } static void cwDestroyPicture (PicturePtr pPicture) { ScreenPtr pScreen = pPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwPsUnwrap(DestroyPicture); cwDestroyPicturePrivate (pPicture); (*ps->DestroyPicture) (pPicture); cwPsWrap(DestroyPicture, cwDestroyPicture); } static void cwChangePicture (PicturePtr pPicture, Mask mask) { ScreenPtr pScreen = pPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwPicturePtr pPicturePrivate = getCwPicture(pPicture); cwPsUnwrap(ChangePicture); (*ps->ChangePicture) (pPicture, mask); if (pPicturePrivate) pPicturePrivate->stateChanges |= mask; cwPsWrap(ChangePicture, cwChangePicture); } static void cwValidatePicture (PicturePtr pPicture, Mask mask) { DrawablePtr pDrawable = pPicture->pDrawable; ScreenPtr pScreen = pDrawable->pScreen; cwPsDecl(pScreen); cwPicturePrivate; cwPsUnwrap(ValidatePicture); /* * Must call ValidatePicture to ensure pPicture->pCompositeClip is valid */ (*ps->ValidatePicture) (pPicture, mask); if (!cwDrawableIsRedirWindow (pDrawable)) { if (pPicturePrivate) cwDestroyPicturePrivate (pPicture); } else { PicturePtr pBackingPicture; DrawablePtr pBackingDrawable; int x_off, y_off; pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off); if (pPicturePrivate && pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable) { cwDestroyPicturePrivate (pPicture); pPicturePrivate = 0; } if (!pPicturePrivate) { pPicturePrivate = cwCreatePicturePrivate (pPicture); if (!pPicturePrivate) { cwPsWrap(ValidatePicture, cwValidatePicture); return; } } pBackingPicture = pPicturePrivate->pBackingPicture; /* * Always copy transform and filters because there's no * indication of when they've changed */ SetPictureTransform(pBackingPicture, pPicture->transform); if (pBackingPicture->filter != pPicture->filter || pPicture->filter_nparams > 0) { char *filter = PictureGetFilterName (pPicture->filter); SetPictureFilter(pBackingPicture, filter, strlen (filter), pPicture->filter_params, pPicture->filter_nparams); } pPicturePrivate->stateChanges |= mask; if (pPicturePrivate->serialNumber != pDrawable->serialNumber || (pPicturePrivate->stateChanges & (CPClipXOrigin|CPClipYOrigin|CPClipMask))) { SetPictureClipRegion (pBackingPicture, x_off - pDrawable->x, y_off - pDrawable->y, pPicture->pCompositeClip); pPicturePrivate->serialNumber = pDrawable->serialNumber; pPicturePrivate->stateChanges &= ~(CPClipXOrigin | CPClipYOrigin | CPClipMask); } CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture); ValidatePicture (pBackingPicture); } cwPsWrap(ValidatePicture, cwValidatePicture); } static void cwComposite (CARD8 op, PicturePtr pSrcPicture, PicturePtr pMskPicture, PicturePtr pDstPicture, INT16 xSrc, INT16 ySrc, INT16 xMsk, INT16 yMsk, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwSrcPictureDecl; cwMskPictureDecl; cwDstPictureDecl; cwPsUnwrap(Composite); (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture, xSrc + src_picture_x_off, ySrc + src_picture_y_off, xMsk + msk_picture_x_off, yMsk + msk_picture_y_off, xDst + dst_picture_x_off, yDst + dst_picture_y_off, width, height); cwPsWrap(Composite, cwComposite); } static void cwCompositeRects (CARD8 op, PicturePtr pDstPicture, xRenderColor *color, int nRect, xRectangle *rects) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwDstPictureDecl; int i; cwPsUnwrap(CompositeRects); for (i = 0; i < nRect; i++) { rects[i].x += dst_picture_x_off; rects[i].y += dst_picture_y_off; } (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects); cwPsWrap(CompositeRects, cwCompositeRects); } static void cwTrapezoids (CARD8 op, PicturePtr pSrcPicture, PicturePtr pDstPicture, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwSrcPictureDecl; cwDstPictureDecl; int i; cwPsUnwrap(Trapezoids); if (dst_picture_x_off || dst_picture_y_off) { for (i = 0; i < ntrap; i++) { traps[i].top += dst_picture_y_off << 16; traps[i].bottom += dst_picture_y_off << 16; traps[i].left.p1.x += dst_picture_x_off << 16; traps[i].left.p1.y += dst_picture_y_off << 16; traps[i].left.p2.x += dst_picture_x_off << 16; traps[i].left.p2.y += dst_picture_y_off << 16; traps[i].right.p1.x += dst_picture_x_off << 16; traps[i].right.p1.y += dst_picture_y_off << 16; traps[i].right.p2.x += dst_picture_x_off << 16; traps[i].right.p2.y += dst_picture_y_off << 16; } } (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, xSrc + src_picture_x_off, ySrc + src_picture_y_off, ntrap, traps); cwPsWrap(Trapezoids, cwTrapezoids); } static void cwTriangles (CARD8 op, PicturePtr pSrcPicture, PicturePtr pDstPicture, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int ntri, xTriangle *tris) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwSrcPictureDecl; cwDstPictureDecl; int i; cwPsUnwrap(Triangles); if (dst_picture_x_off || dst_picture_y_off) { for (i = 0; i < ntri; i++) { tris[i].p1.x += dst_picture_x_off << 16; tris[i].p1.y += dst_picture_y_off << 16; tris[i].p2.x += dst_picture_x_off << 16; tris[i].p2.y += dst_picture_y_off << 16; tris[i].p3.x += dst_picture_x_off << 16; tris[i].p3.y += dst_picture_y_off << 16; } } (*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, xSrc + src_picture_x_off, ySrc + src_picture_y_off, ntri, tris); cwPsWrap(Triangles, cwTriangles); } static void cwTriStrip (CARD8 op, PicturePtr pSrcPicture, PicturePtr pDstPicture, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int npoint, xPointFixed *points) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwSrcPictureDecl; cwDstPictureDecl; int i; cwPsUnwrap(TriStrip); if (dst_picture_x_off || dst_picture_y_off) { for (i = 0; i < npoint; i++) { points[i].x += dst_picture_x_off << 16; points[i].y += dst_picture_y_off << 16; } } (*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, xSrc + src_picture_x_off, ySrc + src_picture_y_off, npoint, points); cwPsWrap(TriStrip, cwTriStrip); } static void cwTriFan (CARD8 op, PicturePtr pSrcPicture, PicturePtr pDstPicture, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int npoint, xPointFixed *points) { ScreenPtr pScreen = pDstPicture->pDrawable->pScreen; cwPsDecl(pScreen); cwSrcPictureDecl; cwDstPictureDecl; int i; cwPsUnwrap(TriFan); if (dst_picture_x_off || dst_picture_y_off) { for (i = 0; i < npoint; i++) { points[i].x += dst_picture_x_off << 16; points[i].y += dst_picture_y_off << 16; } } (*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat, xSrc + src_picture_x_off, ySrc + src_picture_y_off, npoint, points); cwPsWrap(TriFan, cwTriFan); } void cwInitializeRender (ScreenPtr pScreen) { cwPsDecl (pScreen); cwPsWrap(DestroyPicture, cwDestroyPicture); cwPsWrap(ChangePicture, cwChangePicture); cwPsWrap(ValidatePicture, cwValidatePicture); cwPsWrap(Composite, cwComposite); cwPsWrap(CompositeRects, cwCompositeRects); cwPsWrap(Trapezoids, cwTrapezoids); cwPsWrap(Triangles, cwTriangles); cwPsWrap(TriStrip, cwTriStrip); cwPsWrap(TriFan, cwTriFan); /* There is no need to wrap AddTraps as far as we can tell. AddTraps can * only be done on alpha-only pictures, and we won't be getting * alpha-only window pictures, so there's no need to translate. */ } void cwFiniRender (ScreenPtr pScreen) { cwPsDecl (pScreen); cwPsUnwrap(DestroyPicture); cwPsUnwrap(ChangePicture); cwPsUnwrap(ValidatePicture); cwPsUnwrap(Composite); cwPsUnwrap(CompositeRects); cwPsUnwrap(Trapezoids); cwPsUnwrap(Triangles); cwPsUnwrap(TriStrip); cwPsUnwrap(TriFan); } #endif /* RENDER */