/* * Copyright © 2004 David Reveman * * 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 * David Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * David Reveman makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN 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. * * Author: David Reveman */ #include "xgl.h" #include "fb.h" #ifdef RENDER #define XGL_PICTURE_FALLBACK_PROLOGUE(pPicture, func) \ xglSyncDamageBoxBits (pPicture->pDrawable); \ XGL_PICTURE_SCREEN_UNWRAP (func) #define XGL_PICTURE_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \ XGL_PICTURE_SCREEN_WRAP (func, xglfunc); \ xglAddCurrentSurfaceDamage (pPicture->pDrawable) void xglComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pDst->pDrawable->pScreen; XGL_SCREEN_PRIV (pScreen); if (xglComp (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst + pDst->pDrawable->x, yDst + pDst->pDrawable->y, width, height, NULL, NULL)) { xglAddCurrentBitDamage (pDst->pDrawable); return; } pPictureScreen = GetPictureScreen (pScreen); if (!xglSyncBits (pSrc->pDrawable, NullBox)) FatalError (XGL_SW_FAILURE_STRING); if (pMask) { if (!xglSyncBits (pMask->pDrawable, NullBox)) FatalError (XGL_SW_FAILURE_STRING); } if (op == PictOpSrc) { XGL_DRAWABLE_PIXMAP (pDst->pDrawable); if (!xglMapPixmapBits (pPixmap)) FatalError (XGL_SW_FAILURE_STRING); } else xglSyncDamageBoxBits (pDst->pDrawable); XGL_PICTURE_SCREEN_UNWRAP (Composite); (*pPictureScreen->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); XGL_PICTURE_SCREEN_WRAP (Composite, xglComposite); if (op == PictOpSrc) { RegionRec region; xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; if (pMask) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; } if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; xglAddSurfaceDamage (pDst->pDrawable, ®ion); REGION_UNINIT (pDst->pDrawable->pScreen, ®ion); } else xglAddCurrentSurfaceDamage (pDst->pDrawable); } void xglAddTriangles (PicturePtr pDst, INT16 xOff, INT16 yOff, int ntri, xTriangle *tris) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pDst->pDrawable->pScreen; XGL_SCREEN_PRIV (pScreen); XGL_DRAWABLE_PIXMAP_PRIV (pDst->pDrawable); pPictureScreen = GetPictureScreen (pScreen); pPixmapPriv->damageBox.x1 = 0; pPixmapPriv->damageBox.y1 = 0; pPixmapPriv->damageBox.x2 = pDst->pDrawable->width; pPixmapPriv->damageBox.y2 = pDst->pDrawable->height; XGL_PICTURE_FALLBACK_PROLOGUE (pDst, AddTriangles); (*pPictureScreen->AddTriangles) (pDst, xOff, yOff, ntri, tris); XGL_PICTURE_FALLBACK_EPILOGUE (pDst, AddTriangles, xglAddTriangles); } void xglChangePicture (PicturePtr pPicture, Mask mask) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pPicture->pDrawable->pScreen; XGL_SCREEN_PRIV (pScreen); XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable); pPictureScreen = GetPictureScreen (pScreen); if (pPicture->stateChanges & CPRepeat) pPixmapPriv->pictureMask |= xglPCFillMask; if (pPicture->stateChanges & CPComponentAlpha) pPixmapPriv->pictureMask |= xglPCComponentAlphaMask; if (pPicture->stateChanges & CPDither) pPixmapPriv->pictureMask |= xglPCDitherMask; XGL_PICTURE_SCREEN_UNWRAP (ChangePicture); (*pPictureScreen->ChangePicture) (pPicture, mask); XGL_PICTURE_SCREEN_WRAP (ChangePicture, xglChangePicture); } int xglChangePictureTransform (PicturePtr pPicture, PictTransform *transform) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pPicture->pDrawable->pScreen; int ret; XGL_SCREEN_PRIV (pScreen); XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable); pPictureScreen = GetPictureScreen (pScreen); pPixmapPriv->pictureMask |= xglPCTransformMask; XGL_PICTURE_SCREEN_UNWRAP (ChangePictureTransform); ret = (*pPictureScreen->ChangePictureTransform) (pPicture, transform); XGL_PICTURE_SCREEN_WRAP (ChangePictureTransform, xglChangePictureTransform); return ret; } int xglChangePictureFilter (PicturePtr pPicture, int filter, xFixed *params, int nparams) { PictureScreenPtr pPictureScreen; ScreenPtr pScreen = pPicture->pDrawable->pScreen; int ret; XGL_SCREEN_PRIV (pScreen); XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable); pPictureScreen = GetPictureScreen (pScreen); pPixmapPriv->pictureMask |= xglPCFilterMask; XGL_PICTURE_SCREEN_UNWRAP (ChangePictureFilter); ret = (*pPictureScreen->ChangePictureFilter) (pPicture, filter, params, nparams); XGL_PICTURE_SCREEN_WRAP (ChangePictureFilter, xglChangePictureFilter); return ret; } void xglUpdatePicture (PicturePtr pPicture) { glitz_surface_t *surface; XGL_DRAWABLE_PIXMAP_PRIV (pPicture->pDrawable); surface = pPixmapPriv->surface; if (pPixmapPriv->pictureMask & xglPCFillMask) { if (pPicture->repeat) glitz_surface_set_fill (surface, GLITZ_FILL_REPEAT); else glitz_surface_set_fill (surface, GLITZ_FILL_TRANSPARENT); } if (pPixmapPriv->pictureMask & xglPCFilterMask) { switch (pPicture->filter) { case PictFilterNearest: case PictFilterFast: glitz_surface_set_filter (surface, GLITZ_FILTER_NEAREST, NULL, 0); break; case PictFilterGood: case PictFilterBest: case PictFilterBilinear: glitz_surface_set_filter (surface, GLITZ_FILTER_BILINEAR, NULL, 0); break; case PictFilterConvolution: glitz_surface_set_filter (surface, GLITZ_FILTER_CONVOLUTION, (glitz_fixed16_16_t *) pPicture->filter_params, pPicture->filter_nparams); break; } } if (pPixmapPriv->pictureMask & xglPCTransformMask) { glitz_surface_set_transform (surface, (glitz_transform_t *) pPicture->transform); } if (pPixmapPriv->pictureMask & xglPCComponentAlphaMask) { if (pPicture->componentAlpha) glitz_surface_set_component_alpha (surface, 1); else glitz_surface_set_component_alpha (surface, 0); } if (pPixmapPriv->pictureMask & xglPCDitherMask) { if (pPicture->dither) glitz_surface_set_dither (surface, 1); else glitz_surface_set_dither (surface, 0); } pPixmapPriv->pictureMask &= ~XGL_PICTURE_CHANGES (~0); } static int xglVisualDepth (ScreenPtr pScreen, VisualPtr pVisual) { DepthPtr pDepth; int d, v; for (d = 0; d < pScreen->numDepths; d++) { pDepth = &pScreen->allowedDepths[d]; for (v = 0; v < pDepth->numVids; v++) if (pDepth->vids[v] == pVisual->vid) return pDepth->depth; } return 0; } typedef struct _xglformatInit { CARD32 format; CARD8 depth; } xglFormatInitRec, *xglFormatInitPtr; static int xglAddFormat (xglFormatInitPtr formats, int nformat, CARD32 format, CARD8 depth) { int n; for (n = 0; n < nformat; n++) if (formats[n].format == format && formats[n].depth == depth) return nformat; formats[nformat].format = format; formats[nformat].depth = depth; return ++nformat; } #define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n)) - 1)) Bool xglPictureInit (ScreenPtr pScreen) { int f, nformats = 0; PictFormatPtr pFormats; xglFormatInitRec formats[64]; CARD32 format; CARD8 depth; VisualPtr pVisual; int v; int bpp; int r, g, b; int d; DepthPtr pDepth; /* formats required by protocol */ formats[nformats].format = PICT_a1; formats[nformats].depth = 1; nformats++; formats[nformats].format = PICT_a4; formats[nformats].depth = 4; nformats++; formats[nformats].format = PICT_a8; formats[nformats].depth = 8; nformats++; formats[nformats].format = PICT_a8r8g8b8; formats[nformats].depth = 32; nformats++; /* now look through the depths and visuals adding other formats */ for (v = 0; v < pScreen->numVisuals; v++) { pVisual = &pScreen->visuals[v]; depth = xglVisualDepth (pScreen, pVisual); if (!depth) continue; bpp = BitsPerPixel (depth); switch (pVisual->class) { case DirectColor: case TrueColor: r = Ones (pVisual->redMask); g = Ones (pVisual->greenMask); b = Ones (pVisual->blueMask); if (pVisual->offsetBlue == 0 && pVisual->offsetGreen == b && pVisual->offsetRed == b + g) { format = PICT_FORMAT (bpp, PICT_TYPE_ARGB, 0, r, g, b); nformats = xglAddFormat (formats, nformats, format, depth); } break; case StaticColor: case PseudoColor: case StaticGray: case GrayScale: break; } } /* walk supported depths and add missing Direct formats */ for (d = 0; d < pScreen->numDepths; d++) { pDepth = &pScreen->allowedDepths[d]; bpp = BitsPerPixel (pDepth->depth); format = 0; switch (bpp) { case 16: if (pDepth->depth == 15) nformats = xglAddFormat (formats, nformats, PICT_x1r5g5b5, pDepth->depth); if (pDepth->depth == 16) nformats = xglAddFormat (formats, nformats, PICT_r5g6b5, pDepth->depth); break; case 24: if (pDepth->depth == 24) nformats = xglAddFormat (formats, nformats, PICT_r8g8b8, pDepth->depth); break; case 32: if (pDepth->depth == 24) nformats = xglAddFormat (formats, nformats, PICT_x8r8g8b8, pDepth->depth); break; } } pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec)); if (!pFormats) return 0; memset (pFormats, '\0', nformats * sizeof (PictFormatRec)); for (f = 0; f < nformats; f++) { pFormats[f].id = FakeClientID (0); pFormats[f].depth = formats[f].depth; format = formats[f].format; pFormats[f].format = format; pFormats[f].type = PictTypeDirect; switch (PICT_FORMAT_TYPE (format)) { case PICT_TYPE_ARGB: pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format)); if (pFormats[f].direct.alphaMask) pFormats[f].direct.alpha = (PICT_FORMAT_R (format) + PICT_FORMAT_G (format) + PICT_FORMAT_B (format)); pFormats[f].direct.redMask = Mask (PICT_FORMAT_R (format)); pFormats[f].direct.red = (PICT_FORMAT_G (format) + PICT_FORMAT_B (format)); pFormats[f].direct.greenMask = Mask (PICT_FORMAT_G (format)); pFormats[f].direct.green = PICT_FORMAT_B (format); pFormats[f].direct.blueMask = Mask (PICT_FORMAT_B (format)); pFormats[f].direct.blue = 0; break; case PICT_TYPE_A: pFormats[f].direct.alpha = 0; pFormats[f].direct.alphaMask = Mask (PICT_FORMAT_A (format)); break; case PICT_TYPE_COLOR: case PICT_TYPE_GRAY: break; } } if (!fbPictureInit (pScreen, pFormats, nformats)) return FALSE; PictureAddFilter (pScreen, FilterConvolution, miFilterValidateParams); return TRUE; } void xglPictureClipExtents (PicturePtr pPicture, BoxPtr extents) { if (pPicture->clientClipType != CT_NONE) { BoxPtr clip = REGION_EXTENTS (pPicture->pDrawable->pScreen, (RegionPtr) pPicture->clientClip); if (extents->x1 < pPicture->clipOrigin.x + clip->x1) extents->x1 = pPicture->clipOrigin.x + clip->x1; if (extents->y1 < pPicture->clipOrigin.y + clip->y1) extents->y1 = pPicture->clipOrigin.y + clip->y1; if (extents->x2 > pPicture->clipOrigin.x + clip->x2) extents->x2 = pPicture->clipOrigin.x + clip->x2; if (extents->y2 > pPicture->clipOrigin.y + clip->y2) extents->y2 = pPicture->clipOrigin.y + clip->y2; } else { if (extents->x1 < 0) extents->x1 = 0; if (extents->y1 < 0) extents->y1 = 0; if (extents->x2 > pPicture->pDrawable->width) extents->x2 = pPicture->pDrawable->width; if (extents->y2 > pPicture->pDrawable->height) extents->y2 = pPicture->pDrawable->height; } } #endif