xserver-multidpi/hw/kdrive/sis530/sisdraw.c
Eric Anholt e4d11e58ce Remove the PaintWindow optimization.
This was an attempt to avoid scratch gc creation and validation for paintwin
because that was expensive.  This is not the case in current servers, and the
danger of failure to implement it correctly (as seen in all previous
implementations) is high enough to justify removing it.  No performance
difference detected with x11perf -create -move -resize -circulate on Xvfb.
Leave the screen hooks for PaintWindow* in for now to avoid ABI change.
2007-09-13 00:08:53 +00:00

1650 lines
38 KiB
C

/*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#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 stipXoff, stipYoff; /* XXX assumed to be zero */
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, stipXoff, stipYoff);
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;
int tileXoff, tileYoff; /* XXX assumed to be zero */
fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp, tileXoff, tileYoff);
/*
* 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;
int srcXoff, srcYoff;
if (sourceInvarient (pGC->alu))
{
sisFillBoxSolid (pDstDrawable, nbox, pbox,
pGC->bgPixel, pGC->alu);
return;
}
fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff);
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 - srcXoff, dsty + dy - srcYoff,
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,
};
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);
}
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;
return TRUE;
}
void
sisDrawEnable (ScreenPtr pScreen)
{
SetupSis(pScreen);
sisScreenInfo(pScreenPriv);
CARD32 cmd;
CARD32 base;
CARD16 stride;
CARD16 op;
base = pScreenPriv->screen->fb[0].frameBuffer - sisc->frameBuffer;
stride = pScreenPriv->screen->fb[0].byteStride;
#if 0
sis->u.general.dst_base = base;
sis->u.general.dst_pitch = stride;
sis->u.general.src_pitch = stride;
sis->u.general._pad0 = 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);
#endif
base = (CARD32) (pScreenPriv->screen->fb[0].frameBuffer);
fprintf (stderr, "src 0x%x\n", sis->u.accel.src_addr);
sis->u.accel.src_addr = (base & 0x3fffff);
fprintf (stderr, "src 0x%x\n", sis->u.accel.src_addr);
sis->u.accel.dst_addr = (base & 0x3fffff);
sis->u.accel.pitch = (stride << 16) | stride;
sis->u.accel.dimension = ((pScreenPriv->screen->height-1) << 16 |
(pScreenPriv->screen->width - 1));
sis->u.accel.fg = (sisBltRop[GXcopy] << 24) | 0xf800;
sis->u.accel.bg = (sisBltRop[GXcopy] << 24) | 0x00;
#define sisLEFT2RIGHT 0x10
#define sisRIGHT2LEFT 0x00
#define sisTOP2BOTTOM 0x20
#define sisBOTTOM2TOP 0x00
#define sisSRCSYSTEM 0x03
#define sisSRCVIDEO 0x02
#define sisSRCFG 0x01
#define sisSRCBG 0x00
#define sisCMDBLT 0x0000
#define sisCMDBLTMSK 0x0100
#define sisCMDCOLEXP 0x0200
#define sisCMDLINE 0x0300
#define sisCMDENHCOLEXP 0x2000
#define sisXINCREASE 0x10
#define sisYINCREASE 0x20
#define sisCLIPENABL 0x40
#define sisCLIPINTRN 0x80
#define sisCLIPEXTRN 0x00
#define sisPATREG 0x08
#define sisPATFG 0x04
#define sisPATBG 0x00
#define sisLASTPIX 0x0800
#define sisXMAJOR 0x0400
op = sisCMDBLT | sisLEFT2RIGHT | sisTOP2BOTTOM | sisSRCFG | sisPATFG;
sis->u.accel.cmd = op;
KdMarkSync (pScreen);
}
void
sisDrawSync (ScreenPtr pScreen)
{
SetupSis(pScreen);
_sisWaitIdleEmpty (sis);
}
void
sisDrawDisable (ScreenPtr pScreen)
{
}
void
sisDrawFini (ScreenPtr pScreen)
{
}