#include "sis_context.h"
#include "sis_state.h"
#include "sis_lock.h"
#include "swrast/swrast.h"
#include "mmath.h"
static GLbitfield sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
GLint x, GLint y, GLint width,
GLint height );
static void sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x,
GLint y, GLint width, GLint height );
static void sis_clear_z_stencil_buffer( GLcontext * ctx,
GLbitfield mask, GLint x,
GLint y, GLint width,
GLint height );
static void
set_color_pattern( sisContextPtr smesa, GLubyte red, GLubyte green,
GLubyte blue, GLubyte alpha )
{
switch (smesa->colorFormat)
{
case DST_FORMAT_ARGB_8888:
smesa->clearColorPattern = (alpha << 24) +
(red << 16) + (green << 8) + (blue);
break;
case DST_FORMAT_RGB_565:
smesa->clearColorPattern = ((red >> 3) << 11) +
((green >> 2) << 5) + (blue >> 3);
smesa->clearColorPattern |= smesa->clearColorPattern << 16;
break;
default:
assert(0);
}
}
void
sisUpdateZStencilPattern( sisContextPtr smesa, GLclampd z, GLint stencil )
{
GLuint zPattern;
switch (smesa->zFormat)
{
case SiS_ZFORMAT_Z16:
zPattern = FLOAT_TO_USHORT(z);
zPattern |= zPattern << 16;
break;
case SiS_ZFORMAT_S8Z24:
zPattern = FLOAT_TO_UINT(z) >> 8;
zPattern |= stencil << 24;
break;
case SiS_ZFORMAT_Z32:
zPattern = FLOAT_TO_UINT(z);
break;
default:
assert(0);
}
smesa->clearZStencilPattern = zPattern;
}
void
sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean all,
GLint x, GLint y, GLint width, GLint height )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
GLint x1, y1, width1, height1;
if (all) {
GLframebuffer *buffer = ctx->DrawBuffer;
x1 = 0;
y1 = 0;
width1 = buffer->Width;
height1 = buffer->Height;
} else {
x1 = x;
y1 = Y_FLIP(y+height-1);
width1 = width;
height1 = height;
}
LOCK_HARDWARE();
if (ctx->Visual.depthBits == 0 || !ctx->Depth.Mask)
mask &= ~DD_DEPTH_BIT;
if (ctx->Visual.stencilBits == 0)
mask &= ~DD_STENCIL_BIT;
if ((smesa->current.hwDstMask != 0xffffffff &&
(mask & (DD_BACK_LEFT_BIT | DD_FRONT_LEFT_BIT)) != 0) ||
(ctx->Stencil.WriteMask[0] < 0xff && (mask & DD_STENCIL_BIT) != 0) )
{
mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 );
}
if ( mask & DD_FRONT_LEFT_BIT || mask & DD_BACK_LEFT_BIT) {
sis_clear_color_buffer( ctx, mask, x1, y1, width1, height1 );
mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
}
if (mask & (DD_DEPTH_BIT | DD_STENCIL_BIT)) {
if (smesa->depthbuffer != NULL)
sis_clear_z_stencil_buffer( ctx, mask, x1, y1, width1, height1 );
mask &= ~(DD_DEPTH_BIT | DD_STENCIL_BIT);
}
UNLOCK_HARDWARE();
if (mask != 0)
_swrast_Clear( ctx, mask, all, x1, y1, width, height );
}
void
sisDDClearColor( GLcontext * ctx, const GLfloat color[4] )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
GLubyte c[4];
CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
set_color_pattern( smesa, c[0], c[1], c[2], c[3] );
}
void
sisDDClearDepth( GLcontext * ctx, GLclampd d )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
sisUpdateZStencilPattern( smesa, d, ctx->Stencil.Clear );
}
void
sisDDClearStencil( GLcontext * ctx, GLint s )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
sisUpdateZStencilPattern( smesa, ctx->Depth.Clear, s );
}
static GLbitfield
sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
GLint x, GLint y, GLint width, GLint height )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
__GLSiSHardware *current = &smesa->current;
float left, top, right, bottom, zClearVal;
GLboolean bClrColor, bClrDepth, bClrStencil;
GLint dwPrimitiveSet;
GLint dwEnable1 = 0, dwEnable2 = MASK_ColorMaskWriteEnable;
GLint dwDepthMask = 0, dwSten1 = 0, dwSten2 = 0;
GLint dirtyflags = GFLAG_ENABLESETTING | GFLAG_ENABLESETTING2 |
GFLAG_CLIPPING | GFLAG_DESTSETTING;
int count;
XF86DRIClipRectPtr pExtents;
bClrColor = (mask & (DD_BACK_LEFT_BIT | DD_FRONT_LEFT_BIT)) != 0;
bClrDepth = (mask & DD_DEPTH_BIT) != 0;
bClrStencil = (mask & DD_STENCIL_BIT) != 0;
if (smesa->GlobalFlag & GFLAG_RENDER_STATES)
sis_update_render_state( smesa );
if (bClrStencil) {
dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS |
(ctx->Stencil.Clear << 8) | 0xff;
dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE |
SiS_SPASS_ZPASS_REPLACE;
dwEnable1 = MASK_ZWriteEnable | MASK_StencilTestEnable;
dwEnable2 |= MASK_ZMaskWriteEnable;
dwDepthMask |= ctx->Stencil.WriteMask[0] << 24;
} else if (bClrDepth) {
dwEnable1 = MASK_ZWriteEnable;
dwEnable2 |= MASK_ZMaskWriteEnable;
}
if (bClrDepth) {
zClearVal = ctx->Depth.Clear;
if (ctx->Visual.depthBits != 32)
dwDepthMask |= 0x00ffffff;
else
dwDepthMask = 0xffffffff;
} else
zClearVal = 0.0;
mWait3DCmdQueue(9);
MMIO(REG_3D_TEnable, dwEnable1);
MMIO(REG_3D_TEnable2, dwEnable2);
if (bClrDepth || bClrStencil) {
MMIO(REG_3D_ZSet, (current->hwZ & ~MASK_ZTestMode) | SiS_Z_COMP_ALWAYS);
dirtyflags |= GFLAG_ZSETTING;
}
if (bClrColor) {
MMIO(REG_3D_DstSet, (current->hwDstSet & ~MASK_ROP2) | LOP_COPY);
} else {
MMIO(REG_3D_DstAlphaWriteMask, 0L);
}
if (bClrStencil) {
MMIO(REG_3D_StencilSet, dwSten1);
MMIO(REG_3D_StencilSet2, dwSten2);
dirtyflags |= GFLAG_STENCILSETTING;
}
if (mask & DD_FRONT_LEFT_BIT) {
pExtents = smesa->driDrawable->pClipRects;
count = smesa->driDrawable->numClipRects;
} else {
pExtents = NULL;
count = 1;
}
while(count--) {
left = x;
right = x + width;
top = y;
bottom = y + height;
if (pExtents != NULL) {
GLuint x1, y1, x2, y2;
x1 = pExtents->x1 - smesa->driDrawable->x;
y1 = pExtents->y1 - smesa->driDrawable->y;
x2 = pExtents->x2 - smesa->driDrawable->x - 1;
y2 = pExtents->y2 - smesa->driDrawable->y - 1;
left = (left > x1) ? left : x1;
right = (right > x2) ? x2 : right;
top = (top > y1) ? top : y1;
bottom = (bottom > y2) ? y2 : bottom;
pExtents++;
if (left > right || top > bottom)
continue;
}
mWait3DCmdQueue(20);
MMIO(REG_3D_ClipTopBottom, ((GLint)top << 13) | (GLint)bottom);
MMIO(REG_3D_ClipLeftRight, ((GLint)left << 13) | (GLint)right);
dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBc |
SHADE_FLAT_VertexC;
MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
MMIO(REG_3D_TSZa, *(GLint *) &zClearVal);
MMIO(REG_3D_TSXa, *(GLint *) &right);
MMIO(REG_3D_TSYa, *(GLint *) &top);
MMIO(REG_3D_TSARGBa, smesa->clearColorPattern);
MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
MMIO(REG_3D_TSXb, *(GLint *) &left);
MMIO(REG_3D_TSYb, *(GLint *) &top);
MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
MMIO(REG_3D_TSZc, *(GLint *) &zClearVal);
MMIO(REG_3D_TSXc, *(GLint *) &left);
MMIO(REG_3D_TSYc, *(GLint *) &bottom);
MMIO(REG_3D_TSARGBc, smesa->clearColorPattern);
dwPrimitiveSet = OP_3D_TRIANGLE_DRAW | OP_3D_FIRE_TSARGBb |
SHADE_FLAT_VertexB;
MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
MMIO(REG_3D_TSZb, *(GLint *) &zClearVal);
MMIO(REG_3D_TSXb, *(GLint *) &right);
MMIO(REG_3D_TSYb, *(GLint *) &bottom);
MMIO(REG_3D_TSARGBb, smesa->clearColorPattern);
}
mEndPrimitive();
if ((mask & DD_FRONT_LEFT_BIT) != 0 && (mask & DD_BACK_LEFT_BIT) != 0)
sis_3D_Clear( ctx, DD_BACK_LEFT_BIT, x, y, width, height );
smesa->GlobalFlag |= dirtyflags;
return mask & ~(DD_DEPTH_BIT | DD_STENCIL_BIT | DD_BACK_LEFT_BIT |
DD_FRONT_LEFT_BIT);
}
static void
sis_bitblt_clear_cmd( sisContextPtr smesa, ENGPACKET * pkt )
{
GLint *lpdwDest, *lpdwSrc;
int i;
lpdwSrc = (GLint *) pkt + 1;
lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR) + 1;
mWait3DCmdQueue (10);
*lpdwDest++ = *lpdwSrc++;
lpdwSrc++;
lpdwDest++;
for (i = 3; i < 8; i++) {
*lpdwDest++ = *lpdwSrc++;
}
MMIO(REG_CMD0, *(GLint *) & pkt->stdwCmd);
MMIO(REG_CommandQueue, -1);
}
static void
sis_clear_color_buffer( GLcontext *ctx, GLenum mask, GLint x, GLint y,
GLint width, GLint height )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
int count;
GLuint depth = smesa->bytesPerPixel;
XF86DRIClipRectPtr pExtents = NULL;
GLint xx, yy;
GLint x0, y0, width0, height0;
ENGPACKET stEngPacket;
if (mask & DD_BACK_LEFT_BIT) {
smesa->cbClearPacket.stdwDestPos.wY = y;
smesa->cbClearPacket.stdwDestPos.wX = x;
smesa->cbClearPacket.stdwDim.wWidth = (GLshort) width;
smesa->cbClearPacket.stdwDim.wHeight = (GLshort) height;
smesa->cbClearPacket.dwFgRopColor = smesa->clearColorPattern;
sis_bitblt_clear_cmd( smesa, &smesa->cbClearPacket );
}
if ((mask & DD_FRONT_LEFT_BIT) == 0)
return;
x0 = x;
y0 = y;
width0 = width;
height0 = height;
pExtents = smesa->driDrawable->pClipRects;
count = smesa->driDrawable->numClipRects;
memset( &stEngPacket, 0, sizeof (ENGPACKET) );
stEngPacket.dwSrcPitch = (depth == 2) ? 0x80000000 : 0xc0000000;
stEngPacket.dwDestBaseAddr = smesa->frontOffset;
stEngPacket.wDestPitch = smesa->frontPitch;
stEngPacket.wDestHeight = smesa->virtualY;
stEngPacket.stdwCmd.cRop = 0xf0;
stEngPacket.dwFgRopColor = smesa->clearColorPattern;
if (smesa->blockWrite)
stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
else
stEngPacket.stdwCmd.cCmd0 = 0;
stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
while (count--) {
GLint x2 = pExtents->x1 - smesa->driDrawable->x;
GLint y2 = pExtents->y1 - smesa->driDrawable->y;
GLint xx2 = pExtents->x2 - smesa->driDrawable->x;
GLint yy2 = pExtents->y2 - smesa->driDrawable->y;
x = (x0 > x2) ? x0 : x2;
y = (y0 > y2) ? y0 : y2;
xx = ((x0 + width0) > (xx2)) ? xx2 : x0 + width0;
yy = ((y0 + height0) > (yy2)) ? yy2 : y0 + height0;
width = xx - x;
height = yy - y;
pExtents++;
if (width <= 0 || height <= 0)
continue;
stEngPacket.stdwDestPos.wY = y;
stEngPacket.stdwDestPos.wX = x;
stEngPacket.stdwDim.wWidth = (GLshort)width;
stEngPacket.stdwDim.wHeight = (GLshort)height;
sis_bitblt_clear_cmd( smesa, &stEngPacket );
}
}
static void
sis_clear_z_stencil_buffer( GLcontext * ctx, GLbitfield mask,
GLint x, GLint y, GLint width, GLint height )
{
sisContextPtr smesa = SIS_CONTEXT(ctx);
smesa->zClearPacket.stdwDestPos.wY = y;
smesa->zClearPacket.stdwDestPos.wX = x;
smesa->zClearPacket.stdwDim.wWidth = (GLshort) width;
smesa->zClearPacket.stdwDim.wHeight = (GLshort) height;
smesa->zClearPacket.dwFgRopColor = smesa->clearZStencilPattern;
sis_bitblt_clear_cmd( smesa, &smesa->zClearPacket );
}