/* * Id: sisdraw.c,v 1.1 1999/11/02 08:17:24 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. */ /* $XFree86: xc/programs/Xserver/hw/kdrive/sis530/sisdraw.c,v 1.2 1999/12/30 03:03:14 robin Exp $ */ #include "sis.h" #include "sisdraw.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" CARD8 sisPatRop[16] = { /* GXclear */ 0x00, /* 0 */ /* GXand */ 0xa0, /* src AND dst */ /* GXandReverse */ 0x50, /* src AND NOT dst */ /* GXcopy */ 0xf0, /* src */ /* GXandInverted*/ 0x0a, /* NOT src AND dst */ /* GXnoop */ 0xaa, /* dst */ /* GXxor */ 0x5a, /* src XOR dst */ /* GXor */ 0xfa, /* src OR dst */ /* GXnor */ 0x05, /* NOT src AND NOT dst */ /* GXequiv */ 0xa5, /* NOT src XOR dst */ /* GXinvert */ 0x55, /* NOT dst */ /* GXorReverse */ 0xf5, /* src OR NOT dst */ /* GXcopyInverted*/ 0x0f, /* NOT src */ /* GXorInverted */ 0xaf, /* NOT src OR dst */ /* GXnand */ 0x5f, /* NOT src OR NOT dst */ /* GXset */ 0xff, /* 1 */ }; CARD8 sisBltRop[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 */ }; /* Align blts to this boundary or risk trashing an in-progress expand */ #define SIS_MIN_PATTERN 8 /* Do plane bits in this increment to balance CPU and graphics engine */ #define SIS_PATTERN_INC 1024 typedef struct _SisExpand { SisCardInfo *sisc; SisScreenInfo *siss; CARD32 off; int last; } SisExpand; static void sisExpandInit (ScreenPtr pScreen, SisExpand *e) { KdScreenPriv(pScreen); sisCardInfo(pScreenPriv); sisScreenInfo(pScreenPriv); e->sisc = sisc; e->siss = siss; e->off = siss->expand_off; e->last = 0; } static CARD32 * sisExpandAlloc (SisExpand *e, int nb) { SisCardInfo *sisc = e->sisc; SisScreenInfo *siss = e->siss; SisPtr sis = sisc->sis; CARD32 off; /* round up to alignment boundary */ nb = (nb + SIS_MIN_PATTERN-1) & ~(SIS_MIN_PATTERN-1); off = e->off + e->last; if (off + nb > siss->expand_off + siss->expand_len) { _sisWaitIdleEmpty (sis); off = siss->expand_off; } e->off = off; e->last = nb; return (CARD32 *) (sisc->frameBuffer + off); } void sisGlyphBltClipped (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppciInit, Bool imageBlt) { SetupSis(pDrawable->pScreen); FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); int height; int width; int xBack, yBack; int hBack, wBack; int nb, bwidth, nl; FontPtr pfont = pGC->font; CharInfoPtr pci; CARD8 *bits8, b; CARD16 *bits16; CARD32 *bits32; BoxPtr extents; BoxRec bbox; unsigned char alu; CARD32 cmd; SisExpand expand; CARD32 *dst, d; int nbytes; int shift; int x1, y1, x2, y2; RegionPtr pClip = fbGetCompositeClip(pGC); BoxPtr pBox; int nbox; int rect_in; int widthBlt; CharInfoPtr *ppci; x += pDrawable->x; y += pDrawable->y; if (imageBlt) { xBack = x; yBack = y - FONTASCENT(pGC->font); wBack = 0; hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); if (hBack) { height = nglyph; ppci = ppciInit; while (height--) wBack += (*ppci++)->metrics.characterWidth; } if (wBack < 0) { xBack = xBack + wBack; wBack = -wBack; } if (hBack < 0) { yBack = yBack + hBack; hBack = -hBack; } alu = GXcopy; } else { wBack = 0; alu = pGC->alu; } if (wBack) { _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd); for (nbox = REGION_NUM_RECTS (pClip), pBox = REGION_RECTS (pClip); nbox--; pBox++) { x1 = xBack; x2 = xBack + wBack; y1 = yBack; y2 = yBack + hBack; if (x1 < pBox->x1) x1 = pBox->x1; if (x2 > pBox->x2) x2 = pBox->x2; if (y1 < pBox->y1) y1 = pBox->y1; if (y2 > pBox->y2) y2 = pBox->y2; if (x1 < x2 && y1 < y2) { _sisRect (sis, x1, y1, x2 - x1, y2 - y1, cmd); } } } sisExpandInit (pDrawable->pScreen, &expand); sis->u.general.src_fg = pGC->fgPixel; sis->u.general.src_pitch = 0; sis->u.general.src_x = 0; sis->u.general.src_y = 0; cmd = (SIS_CMD_ENH_COLOR_EXPAND | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_FG | (sisBltRop[alu] << 8) | SIS_CMD_INC_X | SIS_CMD_INC_Y | SIS_CMD_RECT_CLIP_ENABLE | SIS_CMD_TRANSPARENT); ppci = ppciInit; while (nglyph--) { pci = *ppci++; height = pci->metrics.ascent + pci->metrics.descent; width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; widthBlt = (width + 31) & ~31; nb = (widthBlt >> 3) * height; if (nb) { x1 = x + pci->metrics.leftSideBearing; y1 = y - pci->metrics.ascent; bbox.x1 = x1; bbox.y1 = y1; bbox.x2 = x1 + width; bbox.y2 = y1 + height; rect_in = RECT_IN_REGION(pGC->pScreen, pClip, &bbox); if (rect_in != rgnOUT) { dst = sisExpandAlloc (&expand, nb); sis->u.general.src_base = expand.off; sis->u.general.dst_x = x1; sis->u.general.dst_y = y1; sis->u.general.rect_width = widthBlt; sis->u.general.rect_height = height; nb >>= 2; bits32 = (CARD32 *) pci->bits; while (nb--) { d = *bits32++; SisInvertBits32 (d); *dst++ = d; } if (rect_in == rgnPART) { for (nbox = REGION_NUM_RECTS (pClip), pBox = REGION_RECTS (pClip); nbox--; pBox++) { _sisClip (sis, pBox->x1, pBox->y1, pBox->x2, pBox->y2); sis->u.general.command = cmd; } } else { _sisClip (sis, 0, 0, x1+width, pScreenPriv->screen->height); sis->u.general.command = cmd; } } } x += pci->metrics.characterWidth; } _sisClip (sis, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height); KdMarkSync (pDrawable->pScreen); } Bool sisTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int xInit, int yInit, unsigned int nglyph, CharInfoPtr *ppci, Bool imageBlt) { SetupSis(pDrawable->pScreen); int x, y; int widthGlyphs, widthGlyph; int widthBlt; FbBits depthMask; int glyphsPer; FontPtr pfont = pGC->font; unsigned long *char1, *char2, *char3, *char4, *char5; CARD8 alu; CARD32 *dst, tmp; CARD8 *dst8, *bits8; int nb; int bwidth; CARD32 cmd; int h; BoxRec bbox; SisExpand expand; int lwTmp, lw; int extra, n; widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); if (!widthGlyph) return TRUE; h = FONTASCENT(pfont) + FONTDESCENT(pfont); if (!h) return TRUE; x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x; y = yInit - FONTASCENT(pfont) + pDrawable->y; bbox.x1 = x; bbox.x2 = x + (widthGlyph * nglyph); bbox.y1 = y; bbox.y2 = y + h; switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) { case rgnPART: if (x < 0 || y < 0) return FALSE; sisGlyphBltClipped (pDrawable, pGC, xInit, yInit, nglyph, ppci, imageBlt); case rgnOUT: return TRUE; } if (widthGlyph <= 6) glyphsPer = 5; else if (widthGlyph <= 8) glyphsPer = 4; else if (widthGlyph <= 10) glyphsPer = 3; else if (widthGlyph <= 16) glyphsPer = 2; else glyphsPer = 1; widthGlyphs = widthGlyph * glyphsPer; widthBlt = widthGlyphs; /* make sure scanlines are 32-bit aligned */ if (widthGlyphs <= 24) widthBlt = 25; cmd = (SIS_CMD_ENH_COLOR_EXPAND | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_FG | SIS_CMD_INC_X | SIS_CMD_INC_Y); if (imageBlt) { sis->u.general.clip_right = bbox.x2; cmd |= ((sisBltRop[GXcopy] << 8) | SIS_CMD_OPAQUE | SIS_CMD_RECT_CLIP_ENABLE); } else { cmd |= ((sisBltRop[pGC->alu] << 8) | SIS_CMD_TRANSPARENT | SIS_CMD_RECT_CLIP_DISABLE); } sisExpandInit (pDrawable->pScreen, &expand); sis->u.general.src_fg = pGC->fgPixel; sis->u.general.src_bg = pGC->bgPixel; bwidth = (widthBlt + 7) >> 3; nb = bwidth * h; #define LoopIt(count, loadup, fetch) \ while (nglyph >= count) \ { \ nglyph -= count; \ dst = sisExpandAlloc (&expand, nb); \ sis->u.general.src_base = expand.off; \ sis->u.general.src_pitch = 0; \ sis->u.general.src_x = 0; \ sis->u.general.src_y = 0; \ sis->u.general.dst_x = x; \ sis->u.general.dst_y = y; \ sis->u.general.rect_width = widthBlt; \ sis->u.general.rect_height = h; \ x += widthGlyphs; \ loadup \ lwTmp = h; \ while (lwTmp--) { \ tmp = fetch; \ SisInvertBits32(tmp); \ *dst++ = tmp; \ } \ sis->u.general.command = cmd; \ } switch (glyphsPer) { case 5: LoopIt(5, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits; char3 = (unsigned long *) (*ppci++)->bits; char4 = (unsigned long *) (*ppci++)->bits; char5 = (unsigned long *) (*ppci++)->bits;, (*char1++ | ((*char2++ | ((*char3++ | ((*char4++ | (*char5++ << widthGlyph)) << widthGlyph)) << widthGlyph)) << widthGlyph))); break; case 4: LoopIt(4, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits; char3 = (unsigned long *) (*ppci++)->bits; char4 = (unsigned long *) (*ppci++)->bits;, (*char1++ | ((*char2++ | ((*char3++ | (*char4++ << widthGlyph)) << widthGlyph)) << widthGlyph))); break; case 3: LoopIt(3, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits; char3 = (unsigned long *) (*ppci++)->bits;, (*char1++ | ((*char2++ | (*char3++ << widthGlyph)) << widthGlyph))); break; case 2: LoopIt(2, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits;, (*char1++ | (*char2++ << widthGlyph))); break; } widthBlt = (widthGlyph + 31) & ~31; bwidth = widthBlt >> 3; nb = bwidth * h; lw = (widthBlt >> 5) * h; while (nglyph--) { dst = (CARD32 *) sisExpandAlloc (&expand, nb); char1 = (CARD32 *) (*ppci++)->bits; sis->u.general.src_base = expand.off; sis->u.general.src_pitch = 0; sis->u.general.src_x = 0; sis->u.general.src_y = 0; sis->u.general.dst_x = x; sis->u.general.dst_y = y; sis->u.general.rect_width = widthBlt; sis->u.general.rect_height = h; lwTmp = lw; while (lwTmp--) { tmp = *char1++; SisInvertBits32 (tmp); *dst++ = tmp; } sis->u.general.command = cmd; x += widthGlyph; } if (imageBlt) sis->u.general.clip_right = pScreenPriv->screen->width; KdMarkSync (pDrawable->pScreen); return TRUE; } Bool sisGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppciInit, Bool imageBlt) { SetupSis(pDrawable->pScreen); int height; int width; int xBack, yBack; int hBack, wBack; int nb, bwidth, nl; FontPtr pfont = pGC->font; CharInfoPtr pci; CARD8 *bits8, b; CARD16 *bits16; CARD32 *bits32; BoxPtr extents; BoxRec bbox; CharInfoPtr *ppci; unsigned char alu; CARD32 cmd; SisExpand expand; CARD32 *dst, d; int nbytes; int shift; x += pDrawable->x; y += pDrawable->y; /* compute an approximate (but covering) bounding box */ ppci = ppciInit; width = 0; height = nglyph; while (height--) width += (*ppci++)->metrics.characterWidth; if (width < 0) { bbox.x1 = x + width; bbox.x2 = x; } else { bbox.x1 = x; bbox.x2 = x + width; } width = FONTMINBOUNDS(pfont,leftSideBearing); if (width < 0) bbox.x1 += width; width = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth); if (width > 0) bbox.x2 += width; bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent); bbox.y2 = y + FONTMAXBOUNDS(pfont,descent); switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox)) { case rgnPART: if (bbox.x1 < 0 || bbox.y1 < 0) return FALSE; sisGlyphBltClipped (pDrawable, pGC, x - pDrawable->x, y - pDrawable->y, nglyph, ppciInit, imageBlt); case rgnOUT: return TRUE; } if (imageBlt) { xBack = x; yBack = y - FONTASCENT(pGC->font); wBack = 0; hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); if (hBack) { height = nglyph; ppci = ppciInit; while (height--) wBack += (*ppci++)->metrics.characterWidth; } if (wBack < 0) { xBack = xBack + wBack; wBack = -wBack; } if (hBack < 0) { yBack = yBack + hBack; hBack = -hBack; } alu = GXcopy; } else { wBack = 0; alu = pGC->alu; } if (wBack) { _sisSetSolidRect (sis, pGC->bgPixel, GXcopy, cmd); _sisRect (sis, xBack, yBack, wBack, hBack, cmd); } sisExpandInit (pDrawable->pScreen, &expand); sis->u.general.src_fg = pGC->fgPixel; cmd = (SIS_CMD_ENH_COLOR_EXPAND | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_FG | (sisBltRop[alu] << 8) | SIS_CMD_INC_X | SIS_CMD_INC_Y | SIS_CMD_RECT_CLIP_DISABLE | SIS_CMD_TRANSPARENT); ppci = ppciInit; while (nglyph--) { pci = *ppci++; height = pci->metrics.ascent + pci->metrics.descent; width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; /* * For glyphs wider than 16 pixels, expand the blt to the nearest multiple * of 32; this allows the scanlines to be padded to a 32-bit boundary * instead of requiring byte packing */ if (width > 16) width = (width + 31) & ~31; bwidth = (width + 7) >> 3; nb = bwidth * height; if (nb) { dst = sisExpandAlloc (&expand, nb); sis->u.general.src_base = expand.off; sis->u.general.src_pitch = 0; sis->u.general.src_x = 0; sis->u.general.src_y = 0; sis->u.general.dst_x = x + pci->metrics.leftSideBearing; sis->u.general.dst_y = y - pci->metrics.ascent; sis->u.general.rect_width = width; sis->u.general.rect_height = height; switch (bwidth) { case 1: bits8 = (CARD8 *) pci->bits; while (height >= 4) { d = (bits8[0] | (bits8[4] << 8) | (bits8[8] << 16) | (bits8[12] << 24)); SisInvertBits32(d); *dst++ = d; bits8 += 16; height -= 4; } if (height) { switch (height) { case 3: d = bits8[0] | (bits8[4] << 8) | (bits8[8] << 16); break; case 2: d = bits8[0] | (bits8[4] << 8); break; case 1: d = bits8[0]; break; } SisInvertBits32(d); *dst++ = d; } break; case 2: bits16 = (CARD16 *) pci->bits; while (height >= 2) { d = bits16[0] | (bits16[2] << 16); SisInvertBits32(d); *dst++ = d; bits16 += 4; height -= 2; } if (height) { d = bits16[0]; SisInvertBits32(d); *dst++ = d; } break; default: nb >>= 2; bits32 = (CARD32 *) pci->bits; while (nb--) { d = *bits32++; SisInvertBits32 (d); *dst++ = d; } } sis->u.general.command = cmd; } x += pci->metrics.characterWidth; } KdMarkSync (pDrawable->pScreen); return TRUE; } /* * Blt glyphs using Sis image transfer register, this does both * poly glyph blt and image glyph blt (when pglyphBase == 1) */ void sisPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { FbBits depthMask; depthMask = FbFullMask (pDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pGC->fillStyle == FillSolid) { if (TERMINALFONT(pGC->font)) { if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE)) return; } else { if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE)) return; } } KdCheckPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); } void sisImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { FbBits depthMask; depthMask = FbFullMask (pDrawable->depth); if ((pGC->planemask & depthMask) == depthMask) { if (TERMINALFONT(pGC->font)) { if (sisTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE)) return; } else { if (sisGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE)) return; } } KdCheckImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); } #define sourceInvarient(alu) (((alu) & 3) == (((alu) >> 2) & 3)) #define sisPatternDimOk(d) ((d) <= 8 && (((d) & ((d) - 1)) == 0)) BOOL sisFillOk (GCPtr pGC) { FbBits depthMask; depthMask = FbFullMask(pGC->depth); if ((pGC->planemask & depthMask) != depthMask) return FALSE; switch (pGC->fillStyle) { case FillSolid: return TRUE; case FillTiled: return (sisPatternDimOk (pGC->tile.pixmap->drawable.width) && sisPatternDimOk (pGC->tile.pixmap->drawable.height)); case FillStippled: case FillOpaqueStippled: return (sisPatternDimOk (pGC->stipple->drawable.width) && sisPatternDimOk (pGC->stipple->drawable.height)); } } CARD32 sisStipplePrepare (DrawablePtr pDrawable, GCPtr pGC) { SetupSis(pGC->pScreen); PixmapPtr pStip = pGC->stipple; int stipHeight = pStip->drawable.height; int xRot, yRot; int rot, stipX, stipY; FbStip *stip, *stipEnd, bits; FbStride stipStride; int stipBpp; int y; CARD32 cmd; xRot = pGC->patOrg.x + pDrawable->x; yRot = pGC->patOrg.y + pDrawable->y; modulus (- yRot, stipHeight, stipY); modulus (- xRot, FB_UNIT, stipX); rot = stipX; fbGetStipDrawable (&pStip->drawable, stip, stipStride, stipBpp); for (y = 0; y < 8; y++) { bits = stip[stipY<<1]; FbRotLeft(bits, rot); SisInvertBits32(bits); sis->u.general.mask[y] = (CARD8) bits; stipY++; if (stipY == stipHeight) stipY = 0; } sis->u.general.pattern_fg = pGC->fgPixel; cmd = (SIS_CMD_BITBLT | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_MONO | (sisPatRop[pGC->alu] << 8) | SIS_CMD_INC_X | SIS_CMD_INC_Y | SIS_CMD_RECT_CLIP_DISABLE | SIS_CMD_RECT_CLIP_DONT_MERGE); if (pGC->fillStyle == FillOpaqueStippled) { sis->u.general.pattern_bg = pGC->bgPixel; cmd |= SIS_CMD_OPAQUE; } else cmd |= SIS_CMD_TRANSPARENT; return cmd; } CARD32 sisTilePrepare (PixmapPtr pTile, int xRot, int yRot, CARD8 alu) { SetupSis(pTile->drawable.pScreen); int tileHeight = pTile->drawable.height; int tileWidth = pTile->drawable.width; FbBits *tile; FbStride tileStride; int tileBpp; fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp); /* * Tile the pattern register */ fbTile ((FbBits *) sis->u.general.pattern, (8 * tileBpp) >> FB_SHIFT, 0, 8 * tileBpp, 8, tile, tileStride, tileWidth * tileBpp, tileHeight, GXcopy, FB_ALLONES, tileBpp, xRot * tileBpp, yRot); return (SIS_CMD_BITBLT | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_PATTERN | (sisPatRop[alu] << 8) | SIS_CMD_INC_X | SIS_CMD_INC_Y | SIS_CMD_RECT_CLIP_DISABLE | SIS_CMD_RECT_CLIP_DONT_MERGE); } void sisFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel, int alu) { SetupSis(pDrawable->pScreen); CARD32 cmd; _sisSetSolidRect(sis,pixel,alu,cmd); while (nBox--) { _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } void sisFillBoxStipple (DrawablePtr pDrawable, GCPtr pGC, int nBox, BoxPtr pBox) { SetupSis(pDrawable->pScreen); CARD32 cmd; cmd = sisStipplePrepare (pDrawable, pGC); while (nBox--) { _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } void sisFillBoxTiled (DrawablePtr pDrawable, int nBox, BoxPtr pBox, PixmapPtr pTile, int xRot, int yRot, CARD8 alu) { SetupSis (pDrawable->pScreen); CARD32 cmd; cmd = sisTilePrepare (pTile, xRot, yRot, alu); while (nBox--) { _sisRect(sis,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } /* sisDoBitBlt ============= Bit Blit for all window to window blits. */ void sisCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { SetupSis(pDstDrawable->pScreen); int srcX, srcY, dstX, dstY; int w, h; CARD32 flags; CARD32 cmd; CARD8 alu; if (pGC) { alu = pGC->alu; if (sourceInvarient (pGC->alu)) { sisFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu); return; } } else alu = GXcopy; _sisSetBlt(sis,alu,cmd); while (nbox--) { w = pbox->x2 - pbox->x1; h = pbox->y2 - pbox->y1; flags = 0; if (reverse) { dstX = pbox->x2 - 1; } else { dstX = pbox->x1; flags |= SIS_CMD_INC_X; } srcX = dstX + dx; if (upsidedown) { dstY = pbox->y2 - 1; } else { dstY = pbox->y1; flags |= SIS_CMD_INC_Y; } srcY = dstY + dy; _sisBlt (sis, srcX, srcY, dstX, dstY, w, h, cmd|flags); pbox++; } KdMarkSync (pDstDrawable->pScreen); } RegionPtr sisCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { KdScreenPriv(pDstDrawable->pScreen); FbBits depthMask; depthMask = FbFullMask (pDstDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pSrcDrawable->type == DRAWABLE_WINDOW && pDstDrawable->type == DRAWABLE_WINDOW) { return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, sisCopyNtoN, 0, 0); } return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); } typedef struct _sis1toNargs { unsigned long copyPlaneFG, copyPlaneBG; } sis1toNargs; void _sisStipple (ScreenPtr pScreen, FbStip *psrcBase, FbStride widthSrc, CARD8 alu, int srcx, int srcy, int dstx, int dsty, int width, int height) { SetupSis(pScreen); FbStip *psrcLine, *psrc; FbStride widthRest; FbStip bits, tmp, lastTmp; int leftShift, rightShift; int nl, nlMiddle; int r; SisExpand expand; CARD32 *dst; int hthis; int hper; int bwidth; CARD32 cmd; sisExpandInit (pScreen, &expand); /* Compute blt address and parameters */ psrc = psrcBase + srcy * widthSrc + (srcx >> 5); nlMiddle = (width + 31) >> 5; leftShift = srcx & 0x1f; rightShift = 32 - leftShift; widthRest = widthSrc - nlMiddle; cmd = (SIS_CMD_ENH_COLOR_EXPAND | SIS_CMD_SRC_SCREEN | SIS_CMD_PAT_FG | (sisBltRop[alu] << 8) | SIS_CMD_INC_X | SIS_CMD_INC_Y | SIS_CMD_OPAQUE | SIS_CMD_RECT_CLIP_ENABLE); if (leftShift != 0) widthRest--; sis->u.general.src_x = 0; sis->u.general.src_y = 0; sis->u.general.dst_x = dstx; sis->u.general.rect_width = (width + 31) & ~31; sis->u.general.clip_right = (dstx + width); bwidth = nlMiddle << 2; hper = SIS_PATTERN_INC / bwidth; if (hper == 0) hper = 1; while (height) { hthis = hper; if (hthis > height) hthis = height; dst = sisExpandAlloc (&expand, bwidth * hthis); sis->u.general.src_base = expand.off; sis->u.general.dst_y = dsty; sis->u.general.rect_height = hthis; dsty += hthis; height -= hthis; if (leftShift == 0) { while (hthis--) { nl = nlMiddle; while (nl--) { tmp = *psrc++; SisInvertBits32(tmp); *dst++ = tmp; } psrc += widthRest; } } else { while (hthis--) { bits = *psrc++; nl = nlMiddle; while (nl--) { tmp = FbStipLeft(bits, leftShift); bits = *psrc++; tmp |= FbStipRight(bits, rightShift); SisInvertBits32(tmp); *dst++ = tmp; } psrc += widthRest; } } sis->u.general.command = cmd; } sis->u.general.clip_right = pScreenPriv->screen->width; } void sisCopy1toN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { SetupSis(pDstDrawable->pScreen); sis1toNargs *args = closure; int dstx, dsty; FbStip *psrcBase; FbStride widthSrc; int srcBpp; if (sourceInvarient (pGC->alu)) { sisFillBoxSolid (pDstDrawable, nbox, pbox, pGC->bgPixel, pGC->alu); return; } fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp); sis->u.general.src_fg = args->copyPlaneFG; sis->u.general.src_bg = args->copyPlaneBG; while (nbox--) { dstx = pbox->x1; dsty = pbox->y1; _sisStipple (pDstDrawable->pScreen, psrcBase, widthSrc, pGC->alu, dstx + dx, dsty + dy, dstx, dsty, pbox->x2 - dstx, pbox->y2 - dsty); pbox++; } KdMarkSync (pDstDrawable->pScreen); } RegionPtr sisCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, unsigned long bitPlane) { KdScreenPriv (pDstDrawable->pScreen); RegionPtr ret; sis1toNargs args; FbBits depthMask; depthMask = FbFullMask (pDstDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pDstDrawable->type == DRAWABLE_WINDOW && pSrcDrawable->depth == 1) { args.copyPlaneFG = pGC->fgPixel; args.copyPlaneBG = pGC->bgPixel; return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, sisCopy1toN, bitPlane, &args); } return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } void sisFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { SetupSis(pDrawable->pScreen); DDXPointPtr pptFree; FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); int *pwidthFree;/* copies of the pointers to free */ CARD32 cmd; int nTmp; INT16 x, y; int width; if (!sisFillOk (pGC)) { KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC)); pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int)); pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec)); if(!pptFree || !pwidthFree) { if (pptFree) DEALLOCATE_LOCAL(pptFree); if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); return; } n = miClipSpans(fbGetCompositeClip(pGC), ppt, pwidth, n, pptFree, pwidthFree, fSorted); pwidth = pwidthFree; ppt = pptFree; switch (pGC->fillStyle) { case FillSolid: _sisSetSolidRect(sis,pGC->fgPixel,pGC->alu,cmd); break; case FillTiled: cmd = sisTilePrepare (pGC->tile.pixmap, pGC->patOrg.x + pDrawable->x, pGC->patOrg.y + pDrawable->y, pGC->alu); break; default: cmd = sisStipplePrepare (pDrawable, pGC); break; } while (n--) { x = ppt->x; y = ppt->y; ppt++; width = *pwidth++; if (width) { _sisRect(sis,x,y,width,1,cmd); } } KdMarkSync (pDrawable->pScreen); DEALLOCATE_LOCAL(pptFree); DEALLOCATE_LOCAL(pwidthFree); } #define NUM_STACK_RECTS 1024 void sisPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { SetupSis(pDrawable->pScreen); xRectangle *prect; RegionPtr prgnClip; register BoxPtr pbox; register BoxPtr pboxClipped; BoxPtr pboxClippedBase; BoxPtr pextent; BoxRec stackRects[NUM_STACK_RECTS]; FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC); int numRects; int n; int xorg, yorg; int x, y; if (!sisFillOk (pGC)) { KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit); return; } prgnClip = fbGetCompositeClip(pGC); xorg = pDrawable->x; yorg = pDrawable->y; if (xorg || yorg) { prect = prectInit; n = nrectFill; while(n--) { prect->x += xorg; prect->y += yorg; prect++; } } prect = prectInit; numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; if (numRects > NUM_STACK_RECTS) { pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec)); if (!pboxClippedBase) return; } else pboxClippedBase = stackRects; pboxClipped = pboxClippedBase; if (REGION_NUM_RECTS(prgnClip) == 1) { int x1, y1, x2, y2, bx2, by2; pextent = REGION_RECTS(prgnClip); x1 = pextent->x1; y1 = pextent->y1; x2 = pextent->x2; y2 = pextent->y2; while (nrectFill--) { if ((pboxClipped->x1 = prect->x) < x1) pboxClipped->x1 = x1; if ((pboxClipped->y1 = prect->y) < y1) pboxClipped->y1 = y1; bx2 = (int) prect->x + (int) prect->width; if (bx2 > x2) bx2 = x2; pboxClipped->x2 = bx2; by2 = (int) prect->y + (int) prect->height; if (by2 > y2) by2 = y2; pboxClipped->y2 = by2; prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; } } } else { int x1, y1, x2, y2, bx2, by2; pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); x1 = pextent->x1; y1 = pextent->y1; x2 = pextent->x2; y2 = pextent->y2; while (nrectFill--) { BoxRec box; if ((box.x1 = prect->x) < x1) box.x1 = x1; if ((box.y1 = prect->y) < y1) box.y1 = y1; bx2 = (int) prect->x + (int) prect->width; if (bx2 > x2) bx2 = x2; box.x2 = bx2; by2 = (int) prect->y + (int) prect->height; if (by2 > y2) by2 = y2; box.y2 = by2; prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = REGION_NUM_RECTS (prgnClip); pbox = REGION_RECTS(prgnClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while(n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if(pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; } } } } if (pboxClipped != pboxClippedBase) { switch (pGC->fillStyle) { case FillSolid: sisFillBoxSolid(pDrawable, pboxClipped-pboxClippedBase, pboxClippedBase, pGC->fgPixel, pGC->alu); break; case FillTiled: sisFillBoxTiled(pDrawable, pboxClipped-pboxClippedBase, pboxClippedBase, pGC->tile.pixmap, pGC->patOrg.x + pDrawable->x, pGC->patOrg.y + pDrawable->y, pGC->alu); break; case FillStippled: case FillOpaqueStippled: sisFillBoxStipple (pDrawable, pGC, pboxClipped-pboxClippedBase, pboxClippedBase); break; } } if (pboxClippedBase != stackRects) DEALLOCATE_LOCAL(pboxClippedBase); } static const GCOps sisOps = { sisFillSpans, KdCheckSetSpans, KdCheckPutImage, sisCopyArea, sisCopyPlane, KdCheckPolyPoint, KdCheckPolylines, KdCheckPolySegment, miPolyRectangle, KdCheckPolyArc, miFillPolygon, sisPolyFillRect, KdCheckPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, sisImageGlyphBlt, sisPolyGlyphBlt, KdCheckPushPixels, #ifdef NEED_LINEHELPER ,NULL #endif }; void sisValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) { FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); fbValidateGC (pGC, changes, pDrawable); if (pDrawable->type == DRAWABLE_WINDOW) pGC->ops = (GCOps *) &sisOps; else pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; } GCFuncs sisGCFuncs = { sisValidateGC, miChangeGC, miCopyGC, miDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; int sisCreateGC (GCPtr pGC) { if (!fbCreateGC (pGC)) return FALSE; if (pGC->depth != 1) pGC->funcs = &sisGCFuncs; pGC->ops = (GCOps *) &kdAsyncPixmapGCOps; return TRUE; } void sisCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; KdScreenPriv(pScreen); RegionRec rgnDst; int dx, dy; WindowPtr pwinRoot; pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, 0, &rgnDst, dx, dy, sisCopyNtoN, 0, 0); REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } void sisPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { KdScreenPriv(pWin->drawable.pScreen); PixmapPtr pTile; if (!REGION_NUM_RECTS(pRegion)) return; switch (what) { case PW_BACKGROUND: switch (pWin->backgroundState) { case None: return; case ParentRelative: do { pWin = pWin->parent; } while (pWin->backgroundState == ParentRelative); (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, what); return; case BackgroundPixmap: pTile = pWin->background.pixmap; if (sisPatternDimOk (pTile->drawable.width) && sisPatternDimOk (pTile->drawable.height)) { sisFillBoxTiled ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pTile, pWin->drawable.x, pWin->drawable.y, GXcopy); return; } break; case BackgroundPixel: sisFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel, GXcopy); return; } break; case PW_BORDER: if (pWin->borderIsPixel) { sisFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel, GXcopy); return; } else { pTile = pWin->border.pixmap; if (sisPatternDimOk (pTile->drawable.width) && sisPatternDimOk (pTile->drawable.height)) { sisFillBoxTiled ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pTile, pWin->drawable.x, pWin->drawable.y, GXcopy); return; } } break; } KdCheckPaintWindow (pWin, pRegion, what); } Bool sisDrawInit (ScreenPtr pScreen) { KdScreenPriv(pScreen); sisScreenInfo(pScreenPriv); /* * Hook up asynchronous drawing */ KdScreenInitAsync (pScreen); /* * Replace various fb screen functions */ pScreen->CreateGC = sisCreateGC; pScreen->CopyWindow = sisCopyWindow; pScreen->PaintWindowBackground = sisPaintWindow; pScreen->PaintWindowBorder = sisPaintWindow; return TRUE; } void sisDrawEnable (ScreenPtr pScreen) { SetupSis(pScreen); sisScreenInfo(pScreenPriv); CARD32 cmd; CARD32 base; CARD16 stride; base = pScreenPriv->screen->fb[0].frameBuffer - sisc->frameBuffer; stride = pScreenPriv->screen->fb[0].byteStride; sis->u.general.dst_base = base; sis->u.general.dst_pitch = stride; sis->u.general.dst_height = pScreenPriv->screen->height; _sisClip (sis, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height); _sisSetSolidRect(sis, pScreen->blackPixel, GXcopy, cmd); _sisRect (sis, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height, cmd); KdMarkSync (pScreen); } void sisDrawSync (ScreenPtr pScreen) { SetupSis(pScreen); _sisWaitIdleEmpty (sis); } void sisDrawDisable (ScreenPtr pScreen) { } void sisDrawFini (ScreenPtr pScreen) { }