313 lines
7.1 KiB
C
313 lines
7.1 KiB
C
/*
|
|
* Copyright © 1998 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_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include "fb.h"
|
|
|
|
#ifndef FBNOPIXADDR
|
|
/*
|
|
* This is a slight abuse of the preprocessor to generate repetitive
|
|
* code, the idea is to generate code for each case of a copy-mode
|
|
* transparent stipple
|
|
*/
|
|
#define LaneCases1(c,a) case c: \
|
|
while (n--) { FbLaneCase(c,a); a++; } \
|
|
break
|
|
#define LaneCases2(c,a) LaneCases1(c,a); LaneCases1(c+1,a)
|
|
#define LaneCases4(c,a) LaneCases2(c,a); LaneCases2(c+2,a)
|
|
#define LaneCases8(c,a) LaneCases4(c,a); LaneCases4(c+4,a)
|
|
#define LaneCases16(c,a) LaneCases8(c,a); LaneCases8(c+8,a)
|
|
#define LaneCases32(c,a) LaneCases16(c,a); LaneCases16(c+16,a)
|
|
#define LaneCases64(c,a) LaneCases32(c,a); LaneCases32(c+32,a)
|
|
#define LaneCases128(c,a) LaneCases64(c,a); LaneCases64(c+64,a)
|
|
#define LaneCases256(c,a) LaneCases128(c,a); LaneCases128(c+128,a)
|
|
|
|
#if FB_SHIFT == 6
|
|
#define LaneCases(a) LaneCases256(0,a)
|
|
#endif
|
|
|
|
#if FB_SHIFT == 5
|
|
#define LaneCases(a) LaneCases16(0,a)
|
|
#endif
|
|
|
|
/*
|
|
* Repeat a transparent stipple across a scanline n times
|
|
*/
|
|
|
|
void
|
|
fbTransparentSpan (FbBits *dst,
|
|
FbBits stip,
|
|
FbBits fgxor,
|
|
int n)
|
|
{
|
|
FbStip s;
|
|
|
|
s = ((FbStip) (stip ) & 0x01);
|
|
s |= ((FbStip) (stip >> 8) & 0x02);
|
|
s |= ((FbStip) (stip >> 16) & 0x04);
|
|
s |= ((FbStip) (stip >> 24) & 0x08);
|
|
#if FB_SHIFT > 5
|
|
s |= ((FbStip) (stip >> 32) & 0x10);
|
|
s |= ((FbStip) (stip >> 40) & 0x20);
|
|
s |= ((FbStip) (stip >> 48) & 0x40);
|
|
s |= ((FbStip) (stip >> 56) & 0x80);
|
|
#endif
|
|
switch (s) {
|
|
LaneCases(dst);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
fbEvenStipple (FbBits *dst,
|
|
FbStride dstStride,
|
|
int dstX,
|
|
int dstBpp,
|
|
|
|
int width,
|
|
int height,
|
|
|
|
FbStip *stip,
|
|
FbStride stipStride,
|
|
int stipHeight,
|
|
|
|
FbBits fgand,
|
|
FbBits fgxor,
|
|
FbBits bgand,
|
|
FbBits bgxor,
|
|
|
|
int xRot,
|
|
int yRot)
|
|
{
|
|
FbBits startmask, endmask;
|
|
FbBits mask, and, xor;
|
|
int nmiddle, n;
|
|
FbStip *s, *stipEnd, bits;
|
|
int rot, stipX, stipY;
|
|
int pixelsPerDst;
|
|
const FbBits *fbBits;
|
|
Bool transparent;
|
|
int startbyte, endbyte;
|
|
|
|
/*
|
|
* Check for a transparent stipple (stencil)
|
|
*/
|
|
transparent = FALSE;
|
|
if (dstBpp >= 8 &&
|
|
fgand == 0 && bgand == FB_ALLONES && bgxor == 0)
|
|
transparent = TRUE;
|
|
|
|
pixelsPerDst = FB_UNIT / dstBpp;
|
|
/*
|
|
* Adjust dest pointers
|
|
*/
|
|
dst += dstX >> FB_SHIFT;
|
|
dstX &= FB_MASK;
|
|
FbMaskBitsBytes (dstX, width, fgand == 0 && bgand == 0,
|
|
startmask, startbyte, nmiddle, endmask, endbyte);
|
|
|
|
if (startmask)
|
|
dstStride--;
|
|
dstStride -= nmiddle;
|
|
|
|
xRot *= dstBpp;
|
|
/*
|
|
* Compute stip start scanline and rotation parameters
|
|
*/
|
|
stipEnd = stip + stipStride * stipHeight;
|
|
modulus (- yRot, stipHeight, stipY);
|
|
s = stip + stipStride * stipY;
|
|
modulus (- xRot, FB_UNIT, stipX);
|
|
rot = stipX;
|
|
|
|
/*
|
|
* Get pointer to stipple mask array for this depth
|
|
*/
|
|
/* fbStippleTable covers all valid bpp (4,8,16,32) */
|
|
fbBits = fbStippleTable[pixelsPerDst];
|
|
|
|
while (height--)
|
|
{
|
|
/*
|
|
* Extract stipple bits for this scanline;
|
|
*/
|
|
bits = READ(s);
|
|
s += stipStride;
|
|
if (s == stipEnd)
|
|
s = stip;
|
|
#if FB_UNIT > 32
|
|
if (pixelsPerDst == 16)
|
|
mask = FbStipple16Bits(FbLeftStipBits(bits,16));
|
|
else
|
|
#endif
|
|
mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
|
|
/*
|
|
* Rotate into position and compute reduced rop values
|
|
*/
|
|
mask = FbRotLeft(mask, rot);
|
|
and = (fgand & mask) | (bgand & ~mask);
|
|
xor = (fgxor & mask) | (bgxor & ~mask);
|
|
|
|
#ifndef FBNOPIXADDR
|
|
if (transparent)
|
|
{
|
|
if (startmask)
|
|
{
|
|
fbTransparentSpan(dst, mask&startmask, fgxor, 1);
|
|
dst++;
|
|
}
|
|
fbTransparentSpan (dst, mask, fgxor, nmiddle);
|
|
dst += nmiddle;
|
|
if (endmask)
|
|
fbTransparentSpan(dst, mask&endmask, fgxor, 1);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
/*
|
|
* Fill scanline
|
|
*/
|
|
if (startmask)
|
|
{
|
|
FbDoLeftMaskByteRRop (dst, startbyte, startmask, and, xor);
|
|
dst++;
|
|
}
|
|
n = nmiddle;
|
|
if (!and)
|
|
while (n--)
|
|
WRITE(dst++, xor);
|
|
else
|
|
{
|
|
while (n--)
|
|
{
|
|
WRITE(dst, FbDoRRop (READ(dst), and, xor));
|
|
dst++;
|
|
}
|
|
}
|
|
if (endmask)
|
|
FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
|
|
}
|
|
dst += dstStride;
|
|
}
|
|
}
|
|
|
|
void
|
|
fbOddStipple (FbBits *dst,
|
|
FbStride dstStride,
|
|
int dstX,
|
|
int dstBpp,
|
|
|
|
int width,
|
|
int height,
|
|
|
|
FbStip *stip,
|
|
FbStride stipStride,
|
|
int stipWidth,
|
|
int stipHeight,
|
|
|
|
FbBits fgand,
|
|
FbBits fgxor,
|
|
FbBits bgand,
|
|
FbBits bgxor,
|
|
|
|
int xRot,
|
|
int yRot)
|
|
{
|
|
int stipX, stipY, sx;
|
|
int widthTmp;
|
|
int h, w;
|
|
int x, y;
|
|
|
|
modulus (- yRot, stipHeight, stipY);
|
|
modulus (dstX / dstBpp - xRot, stipWidth, stipX);
|
|
y = 0;
|
|
while (height)
|
|
{
|
|
h = stipHeight - stipY;
|
|
if (h > height)
|
|
h = height;
|
|
height -= h;
|
|
widthTmp = width;
|
|
x = dstX;
|
|
sx = stipX;
|
|
while (widthTmp)
|
|
{
|
|
w = (stipWidth - sx) * dstBpp;
|
|
if (w > widthTmp)
|
|
w = widthTmp;
|
|
widthTmp -= w;
|
|
fbBltOne (stip + stipY * stipStride,
|
|
stipStride,
|
|
sx,
|
|
|
|
dst + y * dstStride,
|
|
dstStride,
|
|
x,
|
|
dstBpp,
|
|
|
|
w, h,
|
|
|
|
fgand, fgxor, bgand, bgxor);
|
|
x += w;
|
|
sx = 0;
|
|
}
|
|
y += h;
|
|
stipY = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
fbStipple (FbBits *dst,
|
|
FbStride dstStride,
|
|
int dstX,
|
|
int dstBpp,
|
|
|
|
int width,
|
|
int height,
|
|
|
|
FbStip *stip,
|
|
FbStride stipStride,
|
|
int stipWidth,
|
|
int stipHeight,
|
|
Bool even,
|
|
|
|
FbBits fgand,
|
|
FbBits fgxor,
|
|
FbBits bgand,
|
|
FbBits bgxor,
|
|
|
|
int xRot,
|
|
int yRot)
|
|
{
|
|
if (even)
|
|
fbEvenStipple (dst, dstStride, dstX, dstBpp, width, height,
|
|
stip, stipStride, stipHeight,
|
|
fgand, fgxor, bgand, bgxor, xRot, yRot);
|
|
else
|
|
fbOddStipple (dst, dstStride, dstX, dstBpp, width, height,
|
|
stip, stipStride, stipWidth, stipHeight,
|
|
fgand, fgxor, bgand, bgxor, xRot, yRot);
|
|
}
|