#ifdef HAVE_XORG_CONFIG_H #include #endif #include "misc.h" #include "xf86.h" #include "xf86_OSproc.h" #include "servermd.h" #include #include "scrnintstr.h" #include "mi.h" #include "pixmapstr.h" #include "xf86str.h" #include "xaa.h" #include "xaalocal.h" void XAAMoveDWORDS_FixedBase(register CARD32 *dest, register CARD32 *src, register int dwords) { while (dwords & ~0x03) { *dest = *src; *dest = *(src + 1); *dest = *(src + 2); *dest = *(src + 3); dwords -= 4; src += 4; } if (!dwords) return; *dest = *src; if (dwords == 1) return; *dest = *(src + 1); if (dwords == 2) return; *dest = *(src + 2); } void XAAMoveDWORDS(register CARD32 *dest, register CARD32 *src, register int dwords) { while (dwords & ~0x03) { *dest = *src; *(dest + 1) = *(src + 1); *(dest + 2) = *(src + 2); *(dest + 3) = *(src + 3); src += 4; dest += 4; dwords -= 4; } if (!dwords) return; *dest = *src; if (dwords == 1) return; *(dest + 1) = *(src + 1); if (dwords == 2) return; *(dest + 2) = *(src + 2); } void XAAMoveDWORDS_FixedSrc(register CARD32 *dest, register CARD32 *src, register int dwords) { while (dwords & ~0x03) { *dest = *src; *(dest + 1) = *src; *(dest + 2) = *src; *(dest + 3) = *src; dest += 4; dwords -= 4; } if (!dwords) return; *dest = *src; if (dwords == 1) return; *(dest + 1) = *src; if (dwords == 2) return; *(dest + 2) = *src; } static void XAAWritePixmap32To24(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *srcInit, int srcwidth, /* bytes */ int rop, unsigned int planemask, int trans) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int count, dwords = bytes_to_int32(w * 3); CARD32 *src, *dst; Bool PlusOne = FALSE; if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01)) { PlusOne = TRUE; } (*infoRec->SetupForImageWrite) (pScrn, rop, planemask, trans, 24, 24); (*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, 0); if (dwords > infoRec->ImageWriteRange) { dst = (CARD32 *) infoRec->ImageWriteBase; while (h--) { src = (CARD32 *) srcInit; count = w; while (count >= 4) { *dst = (src[0] & 0x00ffffff) | (src[1] << 24); *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); *dst = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); src += 4; count -= 4; } switch (count) { case 0: break; case 1: *dst = src[0]; break; case 2: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); *dst = src[1] >> 8; break; default: *dst = (src[0] & 0x00ffffff) | (src[1] << 24); *dst = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); *dst = src[2] >> 16; break; } srcInit += srcwidth; } } else { while (h--) { dst = (CARD32 *) infoRec->ImageWriteBase; src = (CARD32 *) srcInit; count = w; while (count >= 4) { dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); dst[2] = ((src[2] >> 16) & 0x000000ff) | (src[3] << 8); dst += 3; src += 4; count -= 4; } switch (count) { case 0: break; case 1: dst[0] = src[0]; break; case 2: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); dst[1] = src[1] >> 8; break; default: dst[0] = (src[0] & 0x00ffffff) | (src[1] << 24); dst[1] = ((src[1] >> 8) & 0x0000ffff) | (src[2] << 16); dst[2] = src[2] >> 16; break; } srcInit += srcwidth; } } if (PlusOne) { CARD32 *base = (CARD32 *) infoRec->ImageWriteBase; *base = 0x00000000; } if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) (*infoRec->Sync) (pScrn); else SET_SYNC_FLAG(infoRec); } void XAAWritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *src, int srcwidth, /* bytes */ int rop, unsigned int planemask, int trans, int bpp, int depth) { XAAInfoRecPtr infoRec; int dwords, skipleft, Bpp; Bool beCareful, PlusOne; if ((bpp == 32) && (pScrn->bitsPerPixel == 24)) { XAAWritePixmap32To24(pScrn, x, y, w, h, src, srcwidth, rop, planemask, trans); return; } infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); beCareful = PlusOne = FALSE; Bpp = bpp >> 3; if ((skipleft = (long) src & 0x03L)) { if (!(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING)) { skipleft = 0; beCareful = TRUE; goto BAD_ALIGNMENT; } if (Bpp == 3) skipleft = 4 - skipleft; else skipleft /= Bpp; if ((x < skipleft) && !(infoRec->ImageWriteFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X)) { skipleft = 0; beCareful = TRUE; goto BAD_ALIGNMENT; } x -= skipleft; w += skipleft; if (Bpp == 3) src -= 3 * skipleft; else /* is this Alpha friendly ? */ src = (unsigned char *) ((long) src & ~0x03L); } BAD_ALIGNMENT: dwords = bytes_to_int32(w * Bpp); if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01)) { PlusOne = TRUE; } (*infoRec->SetupForImageWrite) (pScrn, rop, planemask, trans, bpp, depth); (*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, skipleft); if (beCareful) { /* in cases with bad alignment we have to be careful not to read beyond the end of the source */ if (((x * Bpp) + (dwords << 2)) > srcwidth) h--; else beCareful = FALSE; } if (dwords > infoRec->ImageWriteRange) { while (h--) { XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords); src += srcwidth; } if (beCareful) { int shift = ((long) src & 0x03L) << 3; if (--dwords) XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords); src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); *((CARD32 *) infoRec->ImageWriteBase) = *((CARD32 *) src) >> shift; } } else { if (srcwidth == (dwords << 2)) { int decrement = infoRec->ImageWriteRange / dwords; while (h > decrement) { XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords * decrement); src += (srcwidth * decrement); h -= decrement; } if (h) { XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords * h); if (beCareful) src += (srcwidth * h); } } else { while (h--) { XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords); src += srcwidth; } } if (beCareful) { int shift = ((long) src & 0x03L) << 3; if (--dwords) XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase, (CARD32 *) src, dwords); src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); ((CARD32 *) infoRec->ImageWriteBase)[dwords] = *((CARD32 *) src) >> shift; } } if (PlusOne) { CARD32 *base = (CARD32 *) infoRec->ImageWriteBase; *base = 0x00000000; } if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE) (*infoRec->Sync) (pScrn); else SET_SYNC_FLAG(infoRec); } void XAAWritePixmapScanline(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned char *src, int srcwidth, /* bytes */ int rop, unsigned int planemask, int trans, int bpp, int depth) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); int dwords, skipleft, bufferNo = 0, Bpp = bpp >> 3; Bool beCareful = FALSE; CARD32 *base; if ((skipleft = (long) src & 0x03L)) { if (!(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING)) { skipleft = 0; beCareful = TRUE; goto BAD_ALIGNMENT; } if (Bpp == 3) skipleft = 4 - skipleft; else skipleft /= Bpp; if ((x < skipleft) && !(infoRec->ScanlineImageWriteFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X)) { skipleft = 0; beCareful = TRUE; goto BAD_ALIGNMENT; } x -= skipleft; w += skipleft; if (Bpp == 3) src -= 3 * skipleft; else src = (unsigned char *) ((long) src & ~0x03L); } BAD_ALIGNMENT: dwords = bytes_to_int32(w * Bpp); (*infoRec->SetupForScanlineImageWrite) (pScrn, rop, planemask, trans, bpp, depth); (*infoRec->SubsequentScanlineImageWriteRect) (pScrn, x, y, w, h, skipleft); if (beCareful) { /* in cases with bad alignment we have to be careful not to read beyond the end of the source */ if (((x * Bpp) + (dwords << 2)) > srcwidth) h--; else beCareful = FALSE; } while (h--) { base = (CARD32 *) infoRec->ScanlineImageWriteBuffers[bufferNo]; XAAMoveDWORDS(base, (CARD32 *) src, dwords); (*infoRec->SubsequentImageWriteScanline) (pScrn, bufferNo++); src += srcwidth; if (bufferNo >= infoRec->NumScanlineImageWriteBuffers) bufferNo = 0; } if (beCareful) { int shift = ((long) src & 0x03L) << 3; base = (CARD32 *) infoRec->ScanlineImageWriteBuffers[bufferNo]; if (--dwords) XAAMoveDWORDS(base, (CARD32 *) src, dwords); src = (unsigned char *) ((long) (src + (dwords << 2)) & ~0x03L); base[dwords] = *((CARD32 *) src) >> shift; (*infoRec->SubsequentImageWriteScanline) (pScrn, bufferNo); } SET_SYNC_FLAG(infoRec); } void XAAPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pImage) { XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC); int bpp = BitsPerPixel(depth); Bool depthBug = FALSE; if (!w || !h) return; if (!RegionNumRects(pGC->pCompositeClip)) return; depthBug = XAA_DEPTH_BUG(pGC); if (((format == ZPixmap) && infoRec->WritePixmap && ((pDraw->bitsPerPixel == bpp) || ((pDraw->bitsPerPixel == 24) && (bpp == 32) && (infoRec->WritePixmapFlags & CONVERT_32BPP_TO_24BPP))) && CHECK_ROP(pGC, infoRec->WritePixmapFlags) && CHECK_ROPSRC(pGC, infoRec->WritePixmapFlags) && CHECK_PLANEMASK(pGC, infoRec->WritePixmapFlags) && CHECK_NO_GXCOPY(pGC, infoRec->WritePixmapFlags)) || ((format == XYBitmap) && !depthBug && infoRec->WriteBitmap && CHECK_ROP(pGC, infoRec->WriteBitmapFlags) && CHECK_ROPSRC(pGC, infoRec->WriteBitmapFlags) && CHECK_PLANEMASK(pGC, infoRec->WriteBitmapFlags) && CHECK_COLORS(pGC, infoRec->WriteBitmapFlags) && !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY)) || ((format == XYPixmap) && !depthBug && infoRec->WriteBitmap && CHECK_ROP(pGC, infoRec->WriteBitmapFlags) && CHECK_ROPSRC(pGC, infoRec->WriteBitmapFlags) && !(infoRec->WriteBitmapFlags & NO_PLANEMASK) && !(infoRec->WriteBitmapFlags & TRANSPARENCY_ONLY))) { int MaxBoxes = RegionNumRects(pGC->pCompositeClip); BoxPtr pbox, pClipBoxes; int nboxes, srcx, srcy, srcwidth; xRectangle TheRect; TheRect.x = pDraw->x + x; TheRect.y = pDraw->y + y; TheRect.width = w; TheRect.height = h; if (MaxBoxes > (infoRec->PreAllocSize / sizeof(BoxRec))) { pClipBoxes = malloc(MaxBoxes * sizeof(BoxRec)); if (!pClipBoxes) return; } else pClipBoxes = (BoxPtr) infoRec->PreAllocMem; nboxes = XAAGetRectClipBoxes(pGC, pClipBoxes, 1, &TheRect); pbox = pClipBoxes; if (format == XYBitmap) { srcwidth = BitmapBytePad(leftPad + w); while (nboxes--) { srcx = pbox->x1 - TheRect.x + leftPad; srcy = pbox->y1 - TheRect.y; (*infoRec->WriteBitmap) (infoRec->pScrn, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (unsigned char *) pImage + (srcwidth * srcy) + ((srcx >> 5) << 2), srcwidth, srcx & 31, pGC->fgPixel, pGC->bgPixel, pGC->alu, pGC->planemask); pbox++; } } else if (format == ZPixmap) { int Bpp = bpp >> 3; srcwidth = PixmapBytePad(leftPad + w, depth); while (nboxes--) { srcx = pbox->x1 - TheRect.x + leftPad; srcy = pbox->y1 - TheRect.y; (*infoRec->WritePixmap) (infoRec->pScrn, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, (unsigned char *) pImage + (srcwidth * srcy) + (srcx * Bpp), srcwidth, pGC->alu, pGC->planemask, -1, Bpp << 3, depth); pbox++; } } else { /* XYPixmap */ int depth = pGC->depth; int numBox, increment; unsigned long i, mask; BoxPtr pntBox; srcwidth = BitmapBytePad(w + leftPad); increment = h * srcwidth; i = 1 << (depth - 1); mask = ~0; if ((infoRec->pScrn->overlayFlags & OVERLAY_8_32_PLANAR) && (pGC->depth == 8)) { i = 0x80000000; mask = 0xff000000; } for (; i & mask; i >>= 1, pImage += increment) { if (i & pGC->planemask) { pntBox = pbox; numBox = nboxes; while (numBox--) { srcx = pntBox->x1 - TheRect.x + leftPad; srcy = pntBox->y1 - TheRect.y; (*infoRec->WriteBitmap) (infoRec->pScrn, pntBox->x1, pntBox->y1, pntBox->x2 - pntBox->x1, pntBox->y2 - pntBox->y1, (unsigned char *) pImage + (srcwidth * srcy) + ((srcx >> 5) << 2), srcwidth, srcx & 31, ~0, 0, pGC->alu, i); pntBox++; } } } } if (pClipBoxes != (BoxPtr) infoRec->PreAllocMem) free(pClipBoxes); } else XAAFallbackOps.PutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage); }