/* * Copyright © 2000 SuSE, Inc. * * 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 SuSE not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. SuSE makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE * 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: Keith Packard, SuSE, Inc. */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif #include <string.h> #include "fb.h" /* X apps don't like 24bpp images, this code exposes 32bpp images */ /* * These two functions do a full CopyArea while reformatting * the data between 24 and 32bpp. They try to go a bit faster * by reading/writing aligned CARD32s where it's easy */ #define Get8(a) ((CARD32) READ(a)) #if BITMAP_BIT_ORDER == MSBFirst #define Get24(a) ((Get8(a) << 16) | (Get8((a)+1) << 8) | Get8((a)+2)) #define Put24(a,p) ((WRITE((a+0), (CARD8) ((p) >> 16))), \ (WRITE((a+1), (CARD8) ((p) >> 8))), \ (WRITE((a+2), (CARD8) (p)))) #else #define Get24(a) (Get8(a) | (Get8((a)+1) << 8) | (Get8((a)+2)<<16)) #define Put24(a,p) ((WRITE((a+0), (CARD8) (p))), \ (WRITE((a+1), (CARD8) ((p) >> 8))), \ (WRITE((a+2), (CARD8) ((p) >> 16)))) #endif typedef void (*fb24_32BltFunc) (CARD8 *srcLine, FbStride srcStride, int srcX, CARD8 *dstLine, FbStride dstStride, int dstX, int width, int height, int alu, FbBits pm); static void fb24_32BltDown (CARD8 *srcLine, FbStride srcStride, int srcX, CARD8 *dstLine, FbStride dstStride, int dstX, int width, int height, int alu, FbBits pm) { CARD32 *src; CARD8 *dst; int w; Bool destInvarient; CARD32 pixel, dpixel; FbDeclareMergeRop (); srcLine += srcX * 4; dstLine += dstX * 3; FbInitializeMergeRop(alu, (pm | ~(FbBits) 0xffffff)); destInvarient = FbDestInvarientMergeRop(); while (height--) { src = (CARD32 *) srcLine; dst = dstLine; srcLine += srcStride; dstLine += dstStride; w = width; if (destInvarient) { while (((long) dst & 3) && w) { w--; pixel = READ(src++); pixel = FbDoDestInvarientMergeRop(pixel); Put24 (dst, pixel); dst += 3; } /* Do four aligned pixels at a time */ while (w >= 4) { CARD32 s0, s1; s0 = READ(src++); s0 = FbDoDestInvarientMergeRop(s0); s1 = READ(src++); s1 = FbDoDestInvarientMergeRop(s1); #if BITMAP_BIT_ORDER == LSBFirst WRITE((CARD32 *)dst, (s0 & 0xffffff) | (s1 << 24)); #else WRITE((CARD32 *)dst, (s0 << 8) | ((s1 & 0xffffff) >> 16)); #endif s0 = READ(src++); s0 = FbDoDestInvarientMergeRop(s0); #if BITMAP_BIT_ORDER == LSBFirst WRITE((CARD32 *)(dst+4), ((s1 & 0xffffff) >> 8) | (s0 << 16)); #else WRITE((CARD32 *)(dst+4), (s1 << 16) | ((s0 & 0xffffff) >> 8)); #endif s1 = READ(src++); s1 = FbDoDestInvarientMergeRop(s1); #if BITMAP_BIT_ORDER == LSBFirst WRITE((CARD32 *)(dst+8), ((s0 & 0xffffff) >> 16) | (s1 << 8)); #else WRITE((CARD32 *)(dst+8), (s0 << 24) | (s1 & 0xffffff)); #endif dst += 12; w -= 4; } while (w--) { pixel = READ(src++); pixel = FbDoDestInvarientMergeRop(pixel); Put24 (dst, pixel); dst += 3; } } else { while (w--) { pixel = READ(src++); dpixel = Get24 (dst); pixel = FbDoMergeRop(pixel, dpixel); Put24 (dst, pixel); dst += 3; } } } } static void fb24_32BltUp (CARD8 *srcLine, FbStride srcStride, int srcX, CARD8 *dstLine, FbStride dstStride, int dstX, int width, int height, int alu, FbBits pm) { CARD8 *src; CARD32 *dst; int w; Bool destInvarient; CARD32 pixel; FbDeclareMergeRop (); FbInitializeMergeRop(alu, (pm | (~(FbBits) 0xffffff))); destInvarient = FbDestInvarientMergeRop(); srcLine += srcX * 3; dstLine += dstX * 4; while (height--) { w = width; src = srcLine; dst = (CARD32 *) dstLine; srcLine += srcStride; dstLine += dstStride; if (destInvarient) { while (((long) src & 3) && w) { w--; pixel = Get24(src); src += 3; WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); } /* Do four aligned pixels at a time */ while (w >= 4) { CARD32 s0, s1; s0 = READ((CARD32 *)src); #if BITMAP_BIT_ORDER == LSBFirst pixel = s0 & 0xffffff; #else pixel = s0 >> 8; #endif WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); s1 = READ((CARD32 *)(src+4)); #if BITMAP_BIT_ORDER == LSBFirst pixel = (s0 >> 24) | ((s1 << 8) & 0xffffff); #else pixel = ((s0 << 16) & 0xffffff) | (s1 >> 16); #endif WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); s0 = READ((CARD32 *)(src+8)); #if BITMAP_BIT_ORDER == LSBFirst pixel = (s1 >> 16) | ((s0 << 16) & 0xffffff); #else pixel = ((s1 << 8) & 0xffffff) | (s0 >> 24); #endif WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); #if BITMAP_BIT_ORDER == LSBFirst pixel = s0 >> 8; #else pixel = s0 & 0xffffff; #endif WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); src += 12; w -= 4; } while (w) { w--; pixel = Get24(src); src += 3; WRITE(dst++, FbDoDestInvarientMergeRop(pixel)); } } else { while (w--) { pixel = Get24(src); src += 3; WRITE(dst, FbDoMergeRop(pixel, READ(dst))); dst++; } } } } /* * Spans functions; probably unused. */ void fb24_32GetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, int nspans, char *pchardstStart) { FbBits *srcBits; CARD8 *src; FbStride srcStride; int srcBpp; int srcXoff, srcYoff; CARD8 *dst; fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); src = (CARD8 *) srcBits; srcStride *= sizeof (FbBits); while (nspans--) { dst = (CARD8 *) pchardstStart; fb24_32BltUp (src + (ppt->y + srcYoff) * srcStride, srcStride, ppt->x + srcXoff, dst, 1, 0, *pwidth, 1, GXcopy, FB_ALLONES); pchardstStart += PixmapBytePad(*pwidth, pDrawable->depth); ppt++; pwidth++; } fbFinishAccess (pDrawable); } void fb24_32SetSpans (DrawablePtr pDrawable, GCPtr pGC, char *src, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) { FbGCPrivPtr pPriv = fbGetGCPrivate (pGC); RegionPtr pClip = fbGetCompositeClip(pGC); FbBits *dstBits; CARD8 *dst, *d, *s; FbStride dstStride; int dstBpp; int dstXoff, dstYoff; BoxPtr pbox; int n; int x1, x2; fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); dst = (CARD8 *) dstBits; dstStride *= sizeof (FbBits); while (nspans--) { d = dst + (ppt->y + dstYoff) * dstStride; s = (CARD8 *) src; n = REGION_NUM_RECTS(pClip); pbox = REGION_RECTS (pClip); while (n--) { if (pbox->y1 > ppt->y) break; if (pbox->y2 > ppt->y) { x1 = ppt->x; x2 = x1 + *pwidth; if (pbox->x1 > x1) x1 = pbox->x1; if (pbox->x2 < x2) x2 = pbox->x2; if (x1 < x2) fb24_32BltDown (s, 0, (x1 - ppt->x), d, dstStride, x1 + dstXoff, (x2 - x1), 1, pGC->alu, pPriv->pm); } } src += PixmapBytePad (*pwidth, pDrawable->depth); ppt++; pwidth++; } fbFinishAccess (pDrawable); } /* * Clip and put 32bpp Z-format images to a 24bpp drawable */ void fb24_32PutZImage (DrawablePtr pDrawable, RegionPtr pClip, int alu, FbBits pm, int x, int y, int width, int height, CARD8 *src, FbStride srcStride) { FbBits *dstBits; CARD8 *dst; FbStride dstStride; int dstBpp; int dstXoff, dstYoff; int nbox; BoxPtr pbox; int x1, y1, x2, y2; fbGetDrawable (pDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); dstStride *= sizeof(FbBits); dst = (CARD8 *) dstBits; for (nbox = REGION_NUM_RECTS (pClip), pbox = REGION_RECTS(pClip); nbox--; pbox++) { x1 = x; y1 = y; x2 = x + width; y2 = y + height; if (x1 < pbox->x1) x1 = pbox->x1; if (y1 < pbox->y1) y1 = pbox->y1; if (x2 > pbox->x2) x2 = pbox->x2; if (y2 > pbox->y2) y2 = pbox->y2; if (x1 >= x2 || y1 >= y2) continue; fb24_32BltDown (src + (y1 - y) * srcStride, srcStride, (x1 - x), dst + (y1 + dstYoff) * dstStride, dstStride, x1 + dstXoff, (x2 - x1), (y2 - y1), alu, pm); } fbFinishAccess (pDrawable); } void fb24_32GetImage (DrawablePtr pDrawable, int x, int y, int w, int h, unsigned int format, unsigned long planeMask, char *d) { FbBits *srcBits; CARD8 *src; FbStride srcStride; int srcBpp; int srcXoff, srcYoff; FbStride dstStride; FbBits pm; fbGetDrawable (pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); src = (CARD8 *) srcBits; srcStride *= sizeof (FbBits); x += pDrawable->x; y += pDrawable->y; pm = fbReplicatePixel (planeMask, 32); dstStride = PixmapBytePad(w, pDrawable->depth); if (pm != FB_ALLONES) memset (d, 0, dstStride * h); fb24_32BltUp (src + (y + srcYoff) * srcStride, srcStride, x + srcXoff, (CARD8 *) d, dstStride, 0, w, h, GXcopy, pm); fbFinishAccess (pDrawable); } void fb24_32CopyMtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); FbBits *srcBits; CARD8 *src; FbStride srcStride; int srcBpp; FbBits *dstBits; CARD8 *dst; FbStride dstStride; int dstBpp; fb24_32BltFunc blt; int srcXoff, srcYoff; int dstXoff, dstYoff; fbGetDrawable (pSrcDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); src = (CARD8 *) srcBits; srcStride *= sizeof (FbBits); fbGetDrawable (pDstDrawable, dstBits, dstStride, dstBpp, dstXoff, dstYoff); dst = (CARD8 *) dstBits; dstStride *= sizeof (FbBits); if (srcBpp == 24) blt = fb24_32BltUp; else blt = fb24_32BltDown; while (nbox--) { (*blt) (src + (pbox->y1 + dy + srcYoff) * srcStride, srcStride, (pbox->x1 + dx + srcXoff), dst + (pbox->y1 + dstYoff) * dstStride, dstStride, (pbox->x1 + dstXoff), (pbox->x2 - pbox->x1), (pbox->y2 - pbox->y1), pGC->alu, pPriv->pm); pbox++; } fbFinishAccess (pSrcDrawable); fbFinishAccess (pDstDrawable); } PixmapPtr fb24_32ReformatTile(PixmapPtr pOldTile, int bitsPerPixel) { ScreenPtr pScreen = pOldTile->drawable.pScreen; PixmapPtr pNewTile; FbBits *old, *new; FbStride oldStride, newStride; int oldBpp, newBpp; fb24_32BltFunc blt; int oldXoff, oldYoff; int newXoff, newYoff; pNewTile = pScreen->CreatePixmap(pScreen, pOldTile->drawable.width, pOldTile->drawable.height, pOldTile->drawable.depth, pOldTile->usage_hint); if (!pNewTile) return 0; fbGetDrawable (&pOldTile->drawable, old, oldStride, oldBpp, oldXoff, oldYoff); fbGetDrawable (&pNewTile->drawable, new, newStride, newBpp, newXoff, newYoff); if (oldBpp == 24) blt = fb24_32BltUp; else blt = fb24_32BltDown; (*blt) ((CARD8 *) old, oldStride * sizeof (FbBits), 0, (CARD8 *) new, newStride * sizeof (FbBits), 0, pOldTile->drawable.width, pOldTile->drawable.height, GXcopy, FB_ALLONES); fbFinishAccess (&pOldTile->drawable); fbFinishAccess (&pNewTile->drawable); return pNewTile; } typedef struct { pointer pbits; int width; } miScreenInitParmsRec, *miScreenInitParmsPtr; Bool fb24_32CreateScreenResources(ScreenPtr pScreen) { miScreenInitParmsPtr pScrInitParms; int pitch; Bool retval; /* get the pitch before mi destroys it */ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate; pitch = BitmapBytePad(pScrInitParms->width * 24); if((retval = miCreateScreenResources(pScreen))) { /* fix the screen pixmap */ PixmapPtr pPix = (PixmapPtr)pScreen->devPrivate; pPix->drawable.bitsPerPixel = 24; pPix->devKind = pitch; } return retval; } Bool fb24_32ModifyPixmapHeader (PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData) { int bpp, w; if (!pPixmap) return FALSE; bpp = bitsPerPixel; if (bpp <= 0) bpp = pPixmap->drawable.bitsPerPixel; if (bpp == 24) { if (devKind < 0) { w = width; if (w <= 0) w = pPixmap->drawable.width; devKind = BitmapBytePad(w * 24); } } return miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); }