/* * Id: tridentdraw.c,v 1.1 1999/11/02 03:54:47 keithp Exp $ * * Copyright © 1999 Keith Packard * * 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 Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD 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. */ /* $RCSId: xc/programs/Xserver/hw/kdrive/trident/tridentdraw.c,v 1.10 2001/06/03 18:48:19 keithp Exp $ */ #ifdef HAVE_CONFIG_H #include #endif #include "trident.h" #include "tridentdraw.h" #include "Xmd.h" #include "gcstruct.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "regionstr.h" #include "mistruct.h" #include "fontstruct.h" #include "dixfontstr.h" #include "fb.h" #include "migc.h" #include "miline.h" #include "picturestr.h" CARD8 tridentRop[16] = { /* GXclear */ 0x00, /* 0 */ /* GXand */ 0x88, /* src AND dst */ /* GXandReverse */ 0x44, /* src AND NOT dst */ /* GXcopy */ 0xcc, /* src */ /* GXandInverted*/ 0x22, /* NOT src AND dst */ /* GXnoop */ 0xaa, /* dst */ /* GXxor */ 0x66, /* src XOR dst */ /* GXor */ 0xee, /* src OR dst */ /* GXnor */ 0x11, /* NOT src AND NOT dst */ /* GXequiv */ 0x99, /* NOT src XOR dst */ /* GXinvert */ 0x55, /* NOT dst */ /* GXorReverse */ 0xdd, /* src OR NOT dst */ /* GXcopyInverted*/ 0x33, /* NOT src */ /* GXorInverted */ 0xbb, /* NOT src OR dst */ /* GXnand */ 0x77, /* NOT src OR NOT dst */ /* GXset */ 0xff, /* 1 */ }; #define tridentFillPix(bpp,pixel) {\ if (bpp == 8) \ { \ pixel = pixel & 0xff; \ pixel = pixel | pixel << 8; \ } \ if (bpp <= 16) \ { \ pixel = pixel & 0xffff; \ pixel = pixel | pixel << 16; \ } \ } static Cop *cop; static CARD32 cmd; Bool tridentPrepareSolid (DrawablePtr pDrawable, int alu, Pixel pm, Pixel fg) { FbBits depthMask = FbFullMask(pDrawable->depth); if ((pm & depthMask) != depthMask) return FALSE; else { KdScreenPriv(pDrawable->pScreen); tridentCardInfo(pScreenPriv); cop = tridentc->cop; tridentFillPix(pDrawable->bitsPerPixel,fg); _tridentInit(cop,tridentc); _tridentSetSolidRect(cop,fg,alu,cmd); return TRUE; } } void tridentSolid (int x1, int y1, int x2, int y2) { _tridentRect (cop, x1, y1, x2 - 1, y2 - 1, cmd); } void tridentDoneSolid (void) { } Bool tridentPrepareCopy (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int dx, int dy, int alu, Pixel pm) { FbBits depthMask = FbFullMask(pDstDrawable->depth); if ((pm & depthMask) == depthMask) { KdScreenPriv(pDstDrawable->pScreen); tridentCardInfo(pScreenPriv); cop = tridentc->cop; _tridentInit(cop,tridentc); cop->multi = COP_MULTI_PATTERN; cop->multi = COP_MULTI_ROP | tridentRop[alu]; cmd = COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_ROP | COP_OP_FB; if (dx < 0 || dy < 0) cmd |= COP_X_REVERSE; return TRUE; } else return FALSE; } void tridentCopy (int srcX, int srcY, int dstX, int dstY, int w, int h) { if (cmd & COP_X_REVERSE) { cop->src_start_xy = TRI_XY (srcX + w - 1, srcY + h - 1); cop->src_end_xy = TRI_XY (srcX, srcY); cop->dst_start_xy = TRI_XY (dstX + w - 1, dstY + h - 1); cop->dst_end_xy = TRI_XY (dstX, dstY); } else { cop->src_start_xy = TRI_XY (srcX, srcY); cop->src_end_xy = TRI_XY (srcX + w - 1, srcY + h - 1); cop->dst_start_xy = TRI_XY (dstX, dstY); cop->dst_end_xy = TRI_XY (dstX + w - 1, dstY + h - 1); } _tridentWaitDone (cop); cop->command = cmd; } void tridentDoneCopy (void) { } void tridentComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { SetupTrident (pDst->pDrawable->pScreen); tridentScreenInfo(pScreenPriv); RegionRec region; int n; BoxPtr pbox; CARD32 rgb; CARD8 *msk, *mskLine; FbBits *mskBits; FbStride mskStride; int mskBpp; int mskXoff, mskYoff; CARD32 *src, *srcLine; CARD32 *off, *offLine; FbBits *srcBits; FbStride srcStride; int srcXoff, srcYoff; FbStride offStride; int srcBpp; int x_msk, y_msk, x_src, y_src, x_dst, y_dst; int x2; int w, h, w_this, h_this, w_remain; CARD32 *off_screen; int off_size = tridents->off_screen_size >> 2; int off_width, off_height; int stride = pScreenPriv->screen->fb[0].pixelStride; int mskExtra; CARD32 off_screen_offset = tridents->off_screen - tridents->screen; int mode; #define MODE_NONE 0 #define MODE_IMAGE 1 #define MODE_MASK 2 rgb = *((CARD32 *) ((PixmapPtr) (pSrc->pDrawable))->devPrivate.ptr); if (pMask && !pMask->repeat && pMask->format == PICT_a8 && op == PictOpOver && pSrc->repeat && pSrc->pDrawable->width == 1 && pSrc->pDrawable->height == 1 && PICT_FORMAT_BPP(pSrc->format) == 32 && (PICT_FORMAT_A(pSrc->format) == 0 || (rgb & 0xff000000) == 0xff000000) && pDst->pDrawable->bitsPerPixel == 32 && pDst->pDrawable->type == DRAWABLE_WINDOW) { mode = MODE_MASK; } else if (!pMask && op == PictOpOver && !pSrc->repeat && PICT_FORMAT_A(pSrc->format) == 8 && PICT_FORMAT_BPP(pSrc->format) == 32 && pDst->pDrawable->bitsPerPixel == 32 && pDst->pDrawable->type == DRAWABLE_WINDOW) { mode = MODE_IMAGE; } else mode = MODE_NONE; if (mode != MODE_NONE) { xDst += pDst->pDrawable->x; yDst += pDst->pDrawable->y; xSrc += pSrc->pDrawable->x; ySrc += pSrc->pDrawable->y; fbGetDrawable (pSrc->pDrawable, srcBits, srcStride, srcBpp, srcXoff, srcYoff); if (pMask) { xMask += pMask->pDrawable->x; yMask += pMask->pDrawable->y; fbGetDrawable (pMask->pDrawable, mskBits, mskStride, mskBpp, mskXoff, mskYoff); mskStride = mskStride * sizeof (FbBits) / sizeof (CARD8); } if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; _tridentInit(cop,tridentc); cop->multi = COP_MULTI_PATTERN; cop->src_offset = off_screen_offset; if (mode == MODE_IMAGE) { cop->multi = (COP_MULTI_ALPHA | COP_ALPHA_BLEND_ENABLE | COP_ALPHA_WRITE_ENABLE | 0x7 << 16 | COP_ALPHA_DST_BLEND_1_SRC_A | COP_ALPHA_SRC_BLEND_1); } else { rgb &= 0xffffff; cop->multi = (COP_MULTI_ALPHA | COP_ALPHA_BLEND_ENABLE | COP_ALPHA_WRITE_ENABLE | 0x7 << 16 | COP_ALPHA_DST_BLEND_1_SRC_A | COP_ALPHA_SRC_BLEND_SRC_A); } n = REGION_NUM_RECTS (®ion); pbox = REGION_RECTS (®ion); while (n--) { h = pbox->y2 - pbox->y1; w = pbox->x2 - pbox->x1; offStride = (w + 7) & ~7; off_height = off_size / offStride; if (off_height > h) off_height = h; cop->multi = COP_MULTI_STRIDE | (stride << 16) | offStride; y_dst = pbox->y1; y_src = y_dst - yDst + ySrc; y_msk = y_dst - yDst + yMask; x_dst = pbox->x1; x_src = x_dst - xDst + xSrc; x_msk = x_dst - xDst + xMask; if (mode == MODE_IMAGE) srcLine = (CARD32 *) srcBits + (y_src - srcYoff) * srcStride + (x_src - srcXoff); else mskLine = (CARD8 *) mskBits + (y_msk - mskYoff) * mskStride + (x_msk - mskXoff); while (h) { h_this = h; if (h_this > off_height) h_this = off_height; h -= h_this; offLine = (CARD32 *) tridents->off_screen; _tridentWaitDone(cop); cop->dst_start_xy = TRI_XY(x_dst, y_dst); cop->dst_end_xy = TRI_XY(x_dst + w - 1, y_dst + h_this - 1); cop->src_start_xy = TRI_XY(0,0); cop->src_end_xy = TRI_XY(w - 1, h_this - 1); if (mode == MODE_IMAGE) { while (h_this--) { w_remain = w; src = srcLine; srcLine += srcStride; off = offLine; offLine += offStride; while (w_remain--) *off++ = *src++; } } else { while (h_this--) { w_remain = w; msk = mskLine; mskLine += mskStride; off = offLine; offLine += offStride; while (w_remain--) *off++ = rgb | (*msk++ << 24); } } cop->command = (COP_OP_BLT | COP_SCL_OPAQUE | COP_OP_FB); } pbox++; } cop->src_offset = 0; KdMarkSync (pDst->pDrawable->pScreen); } else { KdCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); } } KaaScreenPrivRec tridentKaa = { tridentPrepareSolid, tridentSolid, tridentDoneSolid, tridentPrepareCopy, tridentCopy, tridentDoneCopy, }; Bool tridentDrawInit (ScreenPtr pScreen) { SetupTrident(pScreen); tridentScreenInfo(pScreenPriv); PictureScreenPtr ps = GetPictureScreen(pScreen); if (!kaaDrawInit (pScreen, &tridentKaa)) return FALSE; if (ps && tridents->off_screen) ps->Composite = tridentComposite; return TRUE; } void tridentDrawEnable (ScreenPtr pScreen) { SetupTrident(pScreen); CARD32 cmd; CARD32 base; CARD16 stride; CARD32 format; CARD32 alpha; int tries; int nwrite; stride = pScreenPriv->screen->fb[0].pixelStride; switch (pScreenPriv->screen->fb[0].bitsPerPixel) { case 8: format = COP_DEPTH_8; break; case 16: format = COP_DEPTH_16; break; case 24: format = COP_DEPTH_24_32; break; case 32: format = COP_DEPTH_24_32; break; } /* * compute a few things which will be set every time the * accelerator is used; this avoids problems with APM */ tridentc->cop_depth = COP_MULTI_DEPTH | format; tridentc->cop_stride = COP_MULTI_STRIDE | (stride << 16) | (stride); #define NUM_TRIES 100000 for (tries = 0; tries < NUM_TRIES; tries++) if (!(cop->status & COP_STATUS_BUSY)) break; if (cop->status & COP_STATUS_BUSY) FatalError ("Can't initialize graphics coprocessor"); cop->multi = COP_MULTI_CLIP_TOP_LEFT; cop->multi = COP_MULTI_MASK | 0; cop->src_offset = 0; cop->dst_offset = 0; cop->z_offset = 0; cop->clip_bottom_right = 0x0fff0fff; _tridentInit(cop,tridentc); _tridentSetSolidRect(cop, pScreen->blackPixel, GXcopy, cmd); _tridentRect (cop, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height, cmd); KdMarkSync (pScreen); } void tridentDrawDisable (ScreenPtr pScreen) { } void tridentDrawFini (ScreenPtr pScreen) { } void tridentDrawSync (ScreenPtr pScreen) { SetupTrident(pScreen); _tridentWaitIdleEmpty(cop); }