summaryrefslogtreecommitdiff
path: root/src/ffb_cplane.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ffb_cplane.c')
-rw-r--r--src/ffb_cplane.c393
1 files changed, 393 insertions, 0 deletions
diff --git a/src/ffb_cplane.c b/src/ffb_cplane.c
new file mode 100644
index 0000000..a94b373
--- /dev/null
+++ b/src/ffb_cplane.c
@@ -0,0 +1,393 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Plane copies.
+ *
+ * Copyright (C) 1998,1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_cplane.c,v 1.2 2000/05/23 04:47:44 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "cfbmskbits.h"
+#include "mi.h"
+
+/* Blatantly stolen from mach64 driver. */
+#define mfbmaskbits(x, w, startmask, endmask, nlw) \
+ startmask = starttab[(x)&0x1f]; \
+ endmask = endtab[((x)+(w)) & 0x1f]; \
+ if (startmask) \
+ nlw = (((w) - (32 - ((x)&0x1f))) >> 5); \
+ else \
+ nlw = (w) >> 5;
+
+#define mfbmaskpartialbits(x, w, mask) \
+ mask = partmasks[(x)&0x1f][(w)&0x1f];
+
+#define LeftMost 0
+#define StepBit(bit, inc) ((bit) += (inc))
+
+
+#define GetBits(psrc, nBits, curBit, bitPos, bits) {\
+ bits = 0; \
+ while (nBits--) { \
+ bits |= ((*psrc++ >> bitPos) & 1) << curBit; \
+ StepBit (curBit, 1); \
+ } \
+}
+
+static void
+CreatorCopyPlane32to1 (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int rop, RegionPtr prgnDst,
+ DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane)
+{
+ int srcx, srcy, dstx, dsty, width, height;
+ unsigned long *psrcBase;
+ unsigned long *pdstBase;
+ int widthSrc, widthDst;
+ unsigned int *psrcLine;
+ unsigned int *pdstLine;
+ register unsigned int *psrc;
+ register int i;
+ register int curBit;
+ register int bitPos;
+ register unsigned int bits;
+ register unsigned int *pdst;
+ unsigned int startmask, endmask;
+ int niStart = 0, niEnd = 0;
+ int bitStart = 0, bitEnd = 0;
+ int nl, nlMiddle;
+ int nbox;
+ BoxPtr pbox;
+ int result;
+
+ extern int starttab[32], endtab[32];
+ extern unsigned int partmasks[32][32];
+
+ if (!(planemask & 1))
+ return;
+
+ /* must explicitly ask for "int" widths, as code below expects it */
+ /* on some machines (Sparc64), "long" and "int" are not the same size */
+ cfbGetTypedWidthAndPointer (pSrcDrawable, widthSrc, psrcBase, int, unsigned long)
+ cfbGetTypedWidthAndPointer (pDstDrawable, widthDst, pdstBase, int, unsigned long)
+
+ bitPos = ffs (bitPlane) - 1;
+
+ nbox = REGION_NUM_RECTS(prgnDst);
+ pbox = REGION_RECTS(prgnDst);
+ while (nbox--) {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+ srcx = pptSrc->x;
+ srcy = pptSrc->y;
+ width = pbox->x2 - pbox->x1;
+ height = pbox->y2 - pbox->y1;
+ pbox++;
+ pptSrc++;
+ psrcLine = (unsigned int *)psrcBase + srcy * widthSrc + srcx;
+ pdstLine = (unsigned int *)pdstBase + dsty * widthDst + (dstx >> 5);
+ if (dstx + width <= 32) {
+ mfbmaskpartialbits(dstx, width, startmask);
+ nlMiddle = 0;
+ endmask = 0;
+ } else {
+ mfbmaskbits (dstx, width, startmask, endmask, nlMiddle);
+ }
+ if (startmask) {
+ niStart = 32 - (dstx & 0x1f);
+ bitStart = LeftMost;
+ StepBit (bitStart, (dstx & 0x1f));
+ }
+ if (endmask) {
+ niEnd = (dstx + width) & 0x1f;
+ bitEnd = LeftMost;
+ }
+ if (rop == GXcopy) {
+ while (height--) {
+ psrc = psrcLine;
+ pdst = pdstLine;
+ psrcLine += widthSrc;
+ pdstLine += widthDst;
+ if (startmask) {
+ i = niStart;
+ curBit = bitStart;
+ GetBits (psrc, i, curBit, bitPos, bits);
+
+ *pdst = (*pdst & ~startmask) | bits;
+ pdst++;
+ }
+ nl = nlMiddle;
+
+ while (nl--) {
+ i = 32;
+ curBit = LeftMost;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ *pdst++ = bits;
+ }
+ if (endmask) {
+ i = niEnd;
+ curBit = bitEnd;
+ GetBits (psrc, i, curBit, bitPos, bits);
+
+ *pdst = (*pdst & ~endmask) | bits;
+ }
+ }
+ } else {
+ while (height--) {
+ psrc = psrcLine;
+ pdst = pdstLine;
+ psrcLine += widthSrc;
+ pdstLine += widthDst;
+ if (startmask) {
+ i = niStart;
+ curBit = bitStart;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+
+ *pdst = (*pdst & ~startmask) | (result & startmask);
+ pdst++;
+ }
+ nl = nlMiddle;
+ while (nl--) {
+ i = 32;
+ curBit = LeftMost;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+ *pdst = result;
+ ++pdst;
+ }
+ if (endmask) {
+ i = niEnd;
+ curBit = bitEnd;
+ GetBits (psrc, i, curBit, bitPos, bits);
+ DoRop (result, rop, bits, *pdst);
+
+ *pdst = (*pdst & ~endmask) | (result & endmask);
+ }
+ }
+ }
+ }
+}
+
+static unsigned int copyPlaneFG, copyPlaneBG;
+
+static void
+CreatorCopyPlane1toFbBpp (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDstDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDstDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ int srcx, srcy, dstx, dsty, width, height;
+ int xoffSrc, widthSrc;
+ unsigned int *psrcBase, *psrc, *psrcStart;
+ unsigned int w, tmp, i;
+ int nbox;
+ BoxPtr pbox;
+
+ {
+ unsigned int ppc = (FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE |
+ FFB_PPC_CS_CONST);
+ unsigned int ppc_mask = (FFB_PPC_APE_MASK | FFB_PPC_TBE_MASK |
+ FFB_PPC_CS_MASK);
+ unsigned int rop = (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8);
+ unsigned int fbc = FFB_FBC_WIN(pWin);
+
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+
+ if((pFfb->ppc_cache & ppc_mask) != ppc ||
+ pFfb->fg_cache != copyPlaneFG ||
+ pFfb->fbc_cache != fbc ||
+ pFfb->rop_cache != rop ||
+ pFfb->pmask_cache != planemask ||
+ pFfb->bg_cache != copyPlaneBG) {
+ pFfb->ppc_cache &= ~ppc_mask;
+ pFfb->ppc_cache |= ppc;
+ pFfb->fg_cache = copyPlaneFG;
+ pFfb->fbc_cache = fbc;
+ pFfb->rop_cache = rop;
+ pFfb->pmask_cache = planemask;
+ pFfb->bg_cache = copyPlaneBG;
+ pFfb->rp_active = 1;
+ FFBFifo(pFfb, 6);
+ ffb->ppc = ppc;
+ ffb->fg = copyPlaneFG;
+ ffb->fbc = fbc;
+ ffb->rop = rop;
+ ffb->pmask = planemask;
+ ffb->bg = copyPlaneBG;
+ }
+ }
+
+ cfbGetTypedWidthAndPointer (pSrcDrawable, widthSrc, psrcBase, unsigned int, unsigned int)
+
+ nbox = REGION_NUM_RECTS(prgnDst);
+ pbox = REGION_RECTS(prgnDst);
+ while (nbox--) {
+ dstx = pbox->x1;
+ dsty = pbox->y1;
+ srcx = pptSrc->x;
+ srcy = pptSrc->y;
+ width = pbox->x2 - dstx;
+ height = pbox->y2 - dsty;
+ pbox++;
+ pptSrc++;
+ if (!width)
+ continue;
+ psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
+ for (xoffSrc = srcx & 0x1f; height--; psrc = psrcStart + widthSrc) {
+ w = width;
+ psrcStart = psrc;
+ FFBFifo(pFfb, (1 + (xoffSrc != 0)));
+ ffb->fontxy = ((dsty++ << 16) | (dstx & 0xffff));
+ if (xoffSrc) {
+ tmp = 32 - xoffSrc;
+ if (tmp > w)
+ tmp = w;
+ FFB_WRITE_FONTW(pFfb, ffb, tmp);
+ FFB_WRITE_FONTINC(pFfb, ffb, tmp);
+ ffb->font = *psrc++ << xoffSrc;
+ w -= tmp;
+ }
+ if (!w)
+ continue;
+ FFB_WRITE_FONTW(pFfb, ffb, 32);
+ FFB_WRITE_FONTINC(pFfb, ffb, 32);
+ while (w >= 256) {
+ FFBFifo(pFfb, 8);
+ for (i = 0; i < 8; i++)
+ ffb->font = *psrc++;
+ w -= 256;
+ }
+ while (w >= 32) {
+ FFBFifo(pFfb, 1);
+ ffb->font = *psrc++;
+ w -= 32;
+ }
+ if (w) {
+ FFB_WRITE_FONTW(pFfb, ffb, w);
+ FFBFifo(pFfb, 1);
+ ffb->font = *psrc++;
+ }
+ }
+ }
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+}
+
+RegionPtr CreatorCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN (pSrcDrawable->pScreen);
+ WindowPtr pWin = (WindowPtr) pDstDrawable;
+ ffb_fbcPtr ffb = pFfb->regs;
+ RegionPtr ret;
+
+ FFBLOG(("CreatorCopyPlane: sbpp(%d) dbpp(%d) src[%08x:%08x] dst[%08x:%08x] bplane(%08x)\n",
+ pSrcDrawable->bitsPerPixel, pDstDrawable->bitsPerPixel,
+ srcx, srcy, dstx, dsty, bitPlane));
+ if (pSrcDrawable->bitsPerPixel == 1 &&
+ (pDstDrawable->bitsPerPixel == 32 || pDstDrawable->bitsPerPixel == 8)) {
+ if (bitPlane == 1) {
+ copyPlaneFG = pGC->fgPixel;
+ copyPlaneBG = pGC->bgPixel;
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height,
+ dstx, dsty, CreatorCopyPlane1toFbBpp, bitPlane);
+ } else
+ ret = miHandleExposures (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+ } else if ((pSrcDrawable->bitsPerPixel == 32 || pSrcDrawable->bitsPerPixel == 8)
+ && pDstDrawable->bitsPerPixel == 1) {
+ extern int InverseAlu[16];
+ int oldalu;
+
+ oldalu = pGC->alu;
+ if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
+ pGC->alu = InverseAlu[pGC->alu];
+ else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
+ pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pSrcDrawable->bitsPerPixel == 32) {
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty,
+ CreatorCopyPlane32to1, bitPlane);
+ } else {
+ ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty,
+ cfbCopyPlane8to1, bitPlane);
+ }
+ pGC->alu = oldalu;
+ } else {
+ PixmapPtr pBitmap;
+ ScreenPtr pScreen = pSrcDrawable->pScreen;
+ GCPtr pGC1;
+
+ pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
+ if (!pBitmap)
+ return NULL;
+ pGC1 = GetScratchGC (1, pScreen);
+ if (!pGC1) {
+ (*pScreen->DestroyPixmap) (pBitmap);
+ return NULL;
+ }
+ /*
+ * don't need to set pGC->fgPixel,bgPixel as copyPlane{8,32}to1
+ * ignores pixel values, expecting the rop to "do the
+ * right thing", which GXcopy will.
+ */
+ ValidateGC ((DrawablePtr) pBitmap, pGC1);
+ /* no exposures here, scratch GC's don't get graphics expose */
+ FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, pWin);
+ FFBWait(pFfb, ffb);
+ if (pSrcDrawable->bitsPerPixel == 32) {
+ cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap,
+ pGC1, srcx, srcy, width, height, 0, 0,
+ CreatorCopyPlane32to1, bitPlane);
+ } else {
+ cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap,
+ pGC1, srcx, srcy, width, height, 0, 0,
+ cfbCopyPlane8to1, bitPlane);
+ }
+ copyPlaneFG = pGC->fgPixel;
+ copyPlaneBG = pGC->bgPixel;
+ cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC,
+ 0, 0, width, height, dstx, dsty, CreatorCopyPlane1toFbBpp, 1);
+ FreeScratchGC (pGC1);
+ (*pScreen->DestroyPixmap) (pBitmap);
+ /* compute resultant exposures */
+ ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, bitPlane);
+ }
+ return ret;
+}