windows-nt/Source/XPSP1/NT/multimedia/opengl/server/generic/genclear.c
2020-09-26 16:20:57 +08:00

2420 lines
75 KiB
C

/******************************Module*Header*******************************\
* Module Name: genclear.c
*
* Clear functions.
*
* Created: 01-Dec-1993 16:11:17
* Author: Gilman Wong [gilmanw]
*
* Copyright (c) 1992 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#include "genci.h"
#include "genrgb.h"
#include "devlock.h"
/******************************Public*Routine******************************\
* __glim_Clear
*
* Generic proc table entry point for glClear. It allocates ancillary buffers
* the first time they are used
*
* History:
* 14-Dec-1993 -by- Eddie Robinson [v-eddier]
* Wrote it.
\**************************************************************************/
void APIPRIVATE __glim_Clear(GLbitfield mask)
{
__GL_SETUP();
GLuint beginMode;
beginMode = gc->beginMode;
if ( beginMode != __GL_NOT_IN_BEGIN )
{
if ( beginMode == __GL_NEED_VALIDATE )
{
(*gc->procs.validate)(gc);
gc->beginMode = __GL_NOT_IN_BEGIN;
__glim_Clear(mask);
return;
}
else
{
__glSetError(GL_INVALID_OPERATION);
return;
}
}
if ( mask & ~(GL_COLOR_BUFFER_BIT | GL_ACCUM_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) )
{
__glSetError(GL_INVALID_VALUE);
return;
}
if ( gc->renderMode == GL_RENDER )
{
BOOL bResetViewportAdj = FALSE;
#ifdef _MCD_
// Let MCD have first chance at clearing any of the MCD managed buffers.
if ( ((__GLGENcontext *) (gc))->pMcdState &&
(mask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT)) )
{
// Don't attempt to clear depth/stencil buffer if it does not exist.
if ( !gc->modes.depthBits )
mask &= ~GL_DEPTH_BUFFER_BIT;
if ( !gc->modes.stencilBits )
mask &= ~GL_STENCIL_BUFFER_BIT;
// GenMcdClear will clear the mask bits of the buffers it
// successfully cleared.
GenMcdClear((__GLGENcontext *) gc, &mask);
// If simulations are needed for any of the MCD buffers, now is
// the time to grab the device lock.
if (mask & (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT))
{
// Abandon the clear if we cannot acquire the lock.
if (!glsrvLazyGrabSurfaces((__GLGENcontext *) gc,
COLOR_LOCK_FLAGS |
DEPTH_LOCK_FLAGS))
return;
// We may need to temporarily reset the viewport adjust values
// before calling simulations. If GenMcdResetViewportAdj returns
// TRUE, the viewport is changed and we need restore later with
// VP_NOBIAS.
bResetViewportAdj = GenMcdResetViewportAdj(gc, VP_FIXBIAS);
}
}
#endif
if ( mask & GL_COLOR_BUFFER_BIT )
{
// Clear the software alpha buffer here too, as approppriate
switch ( gc->state.raster.drawBuffer )
{
case GL_NONE:
break;
case GL_FRONT:
(*gc->front->clear)(gc->front);
if( ALPHA_BUFFER_WRITE( gc->front ) )
(*gc->front->alphaBuf.clear)(&gc->front->alphaBuf);
break;
case GL_FRONT_AND_BACK:
(*gc->front->clear)(gc->front);
if( ALPHA_BUFFER_WRITE( gc->front ) )
(*gc->front->alphaBuf.clear)(&gc->front->alphaBuf);
// fall through...
case GL_BACK:
if ( gc->modes.doubleBufferMode ) {
(*gc->back->clear)(gc->back);
if( ALPHA_BUFFER_WRITE( gc->back ) )
(*gc->back->alphaBuf.clear)(&gc->back->alphaBuf);
}
break;
#if __GL_NUMBER_OF_AUX_BUFFERS > 0
case GL_AUX0:
case GL_AUX1:
case GL_AUX2:
case GL_AUX3:
i = gc->state.raster.drawBuffer - GL_AUX0;
if ( i < gc->modes.maxAuxBuffers )
(*gc->auxBuffer[i].clear)(&gc->auxBuffer[i]);
break;
#endif
}
}
if ( (mask & GL_DEPTH_BUFFER_BIT) && gc->modes.depthBits )
{
if ( !gc->modes.haveDepthBuffer )
LazyAllocateDepth(gc);
//XXX Any reason we have to check base???
//XXX That doesn't really fit with 3d DDI model! So check haveDepthBuffer
//XXX instead...
if ( gc->modes.haveDepthBuffer )
(*gc->depthBuffer.clear)(&gc->depthBuffer);
}
if ( (mask & GL_ACCUM_BUFFER_BIT) && gc->modes.accumBits )
{
if ( !gc->modes.haveAccumBuffer )
LazyAllocateAccum(gc);
if ( gc->accumBuffer.buf.base )
(*gc->accumBuffer.clear)(&gc->accumBuffer);
}
if ( (mask & GL_STENCIL_BUFFER_BIT) && gc->modes.stencilBits )
{
if ( !gc->modes.haveStencilBuffer )
LazyAllocateStencil(gc);
if ( gc->stencilBuffer.buf.base )
(*gc->stencilBuffer.clear)(&gc->stencilBuffer);
}
// Restore viewport values if needed.
if (bResetViewportAdj)
{
GenMcdResetViewportAdj(gc, VP_NOBIAS);
}
}
}
/******************************Public*Routine******************************\
* InitClearRectangle
*
* If the wndobj is complex, need to start the enumeration
*
* History:
* 23-Jun-1994 Gilman Wong [gilmanw]
* Use cache of clip rectangles.
*
* 24-Jan-1994 -by- Scott Carr [v-scottc]
* Wrote it.
\**************************************************************************/
void FASTCALL InitClearRectangle(GLGENwindow *pwnd, GLint *pEnumState)
{
__GLGENbuffers *buffers = pwnd->buffers;
ASSERTOPENGL(pwnd->clipComplexity == CLC_COMPLEX,
"InitClearRectangle(): not CLC_COMPLEX\n");
#ifndef _CLIENTSIDE_
// Check the uniqueness signature. Note that if the clip cache is
// uninitialized, the clip cache uniqueness is -1 (which is invalid).
if (buffers->clip.WndUniq != buffers->WndUniq)
{
if (buffers->clip.prcl)
(*private->free)(buffers->clip.prcl);
// How many clip rectangles?
buffers->clip.crcl = wglGetClipRects(pwnd, NULL);
// Allocate a new clip cache.
buffers->clip.prcl =
(RECTL *) (*private->malloc)(buffers->clip.crcl * sizeof(RECTL));
if (!buffers->clip.prcl)
{
buffers->clip.crcl = 0;
return;
}
// Get the clip rectangles.
buffers->clip.crcl = wglGetClipRects(pwnd, buffers->clip.prcl);
buffers->clip.WndUniq = buffers->WndUniq;
}
#else
{
// In the client-side case, we don't need to cache rectangles. We already
// have the rectangles cached for direct screen access.
// Just grab a copy of the pointer and count from the
// cached RGNDATA structure in the GLGENwindow.
buffers->clip.crcl = pwnd->prgndat->rdh.nCount;
buffers->clip.prcl = (RECTL *) pwnd->prgndat->Buffer;
buffers->clip.WndUniq = buffers->WndUniq;
}
#endif
*pEnumState = 0;
}
/******************************Public*Routine******************************\
* GetClearSubRectangle
*
* Enumerate the rectangles (inclusive-exclusive) in screen coordinates that
* need to be cleared. If the clipping region is complex, InitClearRectangle
* must be called prior to calling GetClearSubRectangle.
*
* Returns:
* TRUE if there are more clip rectangles, FALSE if no more.
*
* History:
* 23-Jun-1994 Gilman Wong [gilmanw]
* Use cache of clip rectangles.
*
* 03-Dec-1993 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
GLboolean
GetClearSubRectangle(
__GLcolorBuffer *cfb,
RECTL *prcl,
GLGENwindow *pwnd,
GLint *pEnumState)
{
__GLcontext *gc = cfb->buf.gc;
GLint x, y, x1, y1;
GLboolean retval;
RECTL *prcl2;
// Get the OpenGL clipping rectangle and convert to screen coordinates.
//!!!XXX -- We want to return the clear rectangle as inclusive-exclusive.
//!!!XXX Does the gc->tranform.clip* coordinates represent
//!!!XXX inclusive-exclusive or inclusive-inclusive?
x = gc->transform.clipX0;
y = gc->transform.clipY0;
x1 = gc->transform.clipX1;
y1 = gc->transform.clipY1;
if ((x1 - x == 0) || (y1 - y == 0)) {
prcl->left = prcl->right = 0;
prcl->top = prcl->bottom = 0;
return GL_FALSE;
}
prcl->left = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin;
prcl->right = __GL_UNBIAS_X(gc, x1) + cfb->buf.xOrigin;
prcl->bottom = __GL_UNBIAS_Y(gc, y1) + cfb->buf.yOrigin;
prcl->top = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin;
// Now get the windowing system clipping. There are three cases: CLC_TRIVIAL,
// CLC_COMPLEX, and CLC_RECTANGLE.
// CLC_TRIVIAL case -- no clipping, use rclClient.
if (pwnd->clipComplexity == CLC_TRIVIAL)
{
prcl2 = &pwnd->rclClient;
if ((pwnd->rclClient.left == 0) && (pwnd->rclClient.right == 0))
{
prcl->left = prcl->right = 0;
return GL_FALSE;
}
retval = GL_FALSE;
}
// CLC_COMPLEX case -- rectangles have already been enumerated and put into
// the clip cache. The pEnumState parameter tracks current rectangle to be
// enumerated.
else if (pwnd->clipComplexity == CLC_COMPLEX)
{
__GLGENbuffers *buffers = ((__GLGENcontext *)gc)->pwndLocked->buffers;
ASSERTOPENGL(buffers->WndUniq == buffers->clip.WndUniq,
"GetClearSubRectangle(): clip cache is dirty\n");
if (*pEnumState < buffers->clip.crcl)
{
prcl2 = &buffers->clip.prcl[*pEnumState];
*pEnumState += 1;
retval = (*pEnumState < buffers->clip.crcl);
}
else
{
RIP("GetClearSubRectangle(): no more rectangles!\n");
prcl->left = prcl->right = 0;
return GL_FALSE;
}
}
// CLC_RECT case -- only one rectangle, use rclBounds.
else
{
ASSERTOPENGL(pwnd->clipComplexity == CLC_RECT,
"Unexpected clipComplexity\n");
prcl2 = &pwnd->rclBounds;
if ((pwnd->rclBounds.left == 0) && (pwnd->rclBounds.right == 0))
{
prcl->left = prcl->right = 0;
return GL_FALSE;
}
retval = GL_FALSE;
}
// Sanity check the rectangle.
ASSERTOPENGL(
(prcl2->right - prcl2->left) <= __GL_MAX_WINDOW_WIDTH
&& (prcl2->bottom - prcl2->top) <= __GL_MAX_WINDOW_HEIGHT,
"GetClearSubRectangle(): bad visible rect size\n"
);
// Need to take intersection of prcl & prcl2.
if (prcl2->left > prcl->left)
prcl->left = prcl2->left;
if (prcl2->right < prcl->right)
prcl->right = prcl2->right;
if (prcl2->top > prcl->top)
prcl->top = prcl2->top;
if (prcl2->bottom < prcl->bottom)
prcl->bottom = prcl2->bottom;
if ((prcl->left >= prcl->right) || (prcl->top >= prcl->bottom))
prcl->left = prcl->right = 0; // empty inclusive-exclusive rect
return retval;
}
/******************************Public*Routine******************************\
* ScrnRGBCIReadSpan
*
* Reads a span of RGB, and converts to ColorIndex
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
ScrnRGBCIReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, GLuint *pResults,
GLint w, GLboolean bDIB)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc;
GLubyte *puj;
GLint i;
GLuint iColor;
gengc = (__GLGENcontext *)gc;
if (bDIB) {
puj = (GLubyte *)((ULONG_PTR)cfb->buf.base +
(y*cfb->buf.outerWidth) + (x * 3));
}
else {
(*gengc->pfnCopyPixels)(gengc, cfb, x, y, w, FALSE);
puj = gengc->ColorsBits;
}
for (i = 0; i < w; i++, puj += 3)
{
iColor = *( (GLuint *) puj) & 0xffffff;
*pResults++ = ColorToIndex( gengc, iColor );
}
}
/******************************Public*Routine******************************\
* ScrnBitfield16CIReadSpan
*
* Reads a span of Bitfield16, and converts to ColorIndex
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
ScrnBitfield16CIReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y,
GLuint *pResults, GLint w, GLboolean bDIB)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc;
GLushort *pus;
GLint i;
GLuint iColor;
gengc = (__GLGENcontext *)gc;
if (bDIB) {
pus = (GLushort *)((ULONG_PTR)cfb->buf.base +
(y*cfb->buf.outerWidth) + (x << 1));
}
else {
(*gengc->pfnCopyPixels)(gengc, cfb, x, y, w, FALSE);
pus = gengc->ColorsBits;
}
for (i = 0; i < w; i++)
{
iColor = *pus++;
*pResults++ = ColorToIndex( gengc, iColor );
}
}
/******************************Public*Routine******************************\
* ScrnBitfield32CIReadSpan
*
* Reads a span of Bitfield32, and converts to ColorIndex
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
ScrnBitfield32CIReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y,
GLuint *pResults, GLint w, GLboolean bDIB)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc;
GLuint *pul;
GLint i;
GLuint iColor;
gengc = (__GLGENcontext *)gc;
if (bDIB) {
pul = (GLuint *)((ULONG_PTR)cfb->buf.base +
(y*cfb->buf.outerWidth) + (x << 2));
}
else {
(*gengc->pfnCopyPixels)(gengc, cfb, x, y, w, FALSE);
pul = gengc->ColorsBits;
}
for (i = 0; i < w; i++)
{
iColor = *pul++;
*pResults++ = ColorToIndex( gengc, iColor );
}
}
/******************************Public*Routine******************************\
* CalcDitherMatrix
*
* Calculate the 16 element dither matrix, or return FALSE if dithering
* would have no effect.
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
GLboolean
CalcDitherMatrix( __GLcolorBuffer *cfb, GLboolean bRGBA, GLboolean bMasking,
GLboolean bBitfield16, GLubyte *mDither )
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
UINT i, j; // indices into the dither array
GLushort result; // dithered color value (in 332 RGB)
__GLcolor *clear;
GLfloat inc = DITHER_INC(15); // largest dither increment
GLushort *msDither = (GLushort *) mDither;
GLuint *pTrans = (GLuint *) (gengc->pajTranslateVector + 1);
// see if we can ignore dithering altogether
if( bRGBA ) {
clear = &gc->state.raster.clear;
if( ((BYTE)(clear->r*gc->frontBuffer.redScale) ==
(BYTE)(clear->r*gc->frontBuffer.redScale + inc)) &&
((BYTE)(clear->g*gc->frontBuffer.greenScale) ==
(BYTE)(clear->g*gc->frontBuffer.greenScale + inc)) &&
((BYTE)(clear->b*gc->frontBuffer.blueScale) ==
(BYTE)(clear->b*gc->frontBuffer.blueScale + inc)) ) {
return GL_FALSE;
}
}
else { // Color Index (cast to short so works for up to 16-bit)
if( (GLushort) (gc->state.raster.clearIndex) ==
(GLushort) (gc->state.raster.clearIndex + inc)) {
return GL_FALSE;
}
}
//XXX -- could cache this in the gengc
for (j = 0; j < 4; j++)
{
for (i = 0; i < 4; i++)
{
inc = fDitherIncTable[__GL_DITHER_INDEX(i, j)];
if( bRGBA ) {
result =
((BYTE)(clear->r*gc->frontBuffer.redScale + inc) <<
cfb->redShift) |
((BYTE)(clear->g*gc->frontBuffer.greenScale + inc) <<
cfb->greenShift) |
((BYTE)(clear->b*gc->frontBuffer.blueScale + inc) <<
cfb->blueShift);
}
else {
result = (BYTE) (gc->state.raster.clearIndex + inc);
result &= cfb->redMax;
}
if( bBitfield16 ) {
if( !bMasking ) {
if( bRGBA )
*msDither++ = result;
else
*msDither++ = (GLushort)pTrans[result];
}
else
*msDither++ = (GLushort)(result & cfb->sourceMask);
}
else {
if( !bMasking )
*mDither++ = gengc->pajTranslateVector[(GLubyte)result];
else
*mDither++ = (GLubyte)(result & cfb->sourceMask);
}
}
}
return TRUE;
}
/******************************Public*Routine******************************\
* Index4DitherClear
*
* Clear function for Display 4-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
Index4DitherClear(__GLcolorBuffer *cfb, RECTL *rcl, GLubyte *mDither,
GLboolean bDIB )
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
UINT cjSpan; // length of span in bytes
GLubyte *pDither; // dithered color, relative to window origin
UINT i, j; // indices into the dither array
GLubyte *puj, *pujStart; // pointer into span buffer
GLint ySpan; // index to window row to clear
GLushort pattern, *pus; // replicatable 4-nibble dither pattern
GLuint lRightByte, // right edge of span that is byte aligned
lLeftByte; // left edge of span that is byte aligned
GLuint cSpanWidth; // span width in pixels
GLuint dithX, dithY; // x,y offsets into dither matrix
GLubyte dithQuad[4]; // dither repetion quad along a span
lLeftByte = (rcl->left + 1) / 2;
lRightByte = rcl->right / 2;
cjSpan = lRightByte - lLeftByte;
cSpanWidth = rcl->right - rcl->left;
if( bDIB )
pujStart = (GLubyte *)
((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + lLeftByte);
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
for (j = 0; (j < 4) && ((rcl->top + j) < (UINT)rcl->bottom); j++)
{
// Arrange the 4-pixel dither repetition pattern in x. This
// pattern is relative to rcl->left.
pDither = mDither + ((dithY+j)&3)*4;
for( i = 0; i < 4; i ++ ) {
dithQuad[i] = pDither[(dithX+i)&3];
}
// Copy the clear pattern into the span buffer.
puj = gengc->ColorsBits;
pus = (GLushort *) puj;
// For every line, we can replicate a 2-byte(4-nibble) pattern
// into the span buffer. This will allow us to quickly output
// the byte aligned portion of the dithered span.
//
// If we are writing to a DIB and the first pixel does not fall
// on a byte boundary, then the buffer will replicate (using
// the dithQuad pattern) the dither pattern:
//
// <dith 1> <dith 2> <dith 3> <dith 0>
//
// (The non-aligned first dither pixel will have to be handled
// separately).
//
// Otherwise (if we are writing to a display managed surface or
// the first pixel does fall on a byte boundary), then the buffer
// will replicate the dither pattern:
//
// <dith 0> <dith 1> <dith 2> <dith 3>
//
// Note -- for a VGA, the layout of the pixels in a ushort is:
//
// | -------------- ushort --------------- |
// | ---- byte 1 ----- | ---- byte 0 ----- |
// <pixel 2> <pixel 3> <pixel 0> <pixel 1>
if( bDIB && (rcl->left & 1) ) { // not on byte boundary
// dither: 1230 pattern: 3012
pattern = (dithQuad[3] << 12) | (dithQuad[0] << 8) |
(dithQuad[1] << 4 ) | (dithQuad[2]);
}
else { // all other cases
// dither: 0123 pattern: 2301
pattern = (dithQuad[2] << 12) | (dithQuad[3] << 8) |
(dithQuad[0] << 4 ) | (dithQuad[1]);
}
// Replicate pattern into ColorsBits (round up to next short)
for( i = (rcl->right - rcl->left + 3)/4; i; i-- ) {
*pus++ = pattern;
}
// Copy the span to the display for every 4th row of the window.
if( bDIB ) {
for (ySpan = rcl->top + j, puj = pujStart;
ySpan < rcl->bottom;
ySpan+=4,
puj = (GLubyte *)((ULONG_PTR)puj + 4*cfb->buf.outerWidth) ) {
RtlCopyMemory_UnalignedDst( puj, gengc->ColorsBits, cjSpan );
}
// Take care of non-byte aligned left edge.
if( rcl->left & 1 ) {
for (ySpan = rcl->top + j, puj = (pujStart-1);
ySpan < rcl->bottom;
ySpan+=4,
puj = (GLubyte *)((ULONG_PTR)puj + 4*cfb->buf.outerWidth) )
*puj = (*puj & 0xf0) | (dithQuad[0] & 0x0f);
}
// Take care of non-byte aligned right edge.
if( rcl->right & 1 ) {
GLuint dindex = ((rcl->right - 1) - cfb->buf.xOrigin)&3;
for (ySpan = rcl->top + j, puj = (pujStart + cjSpan);
ySpan < rcl->bottom;
ySpan+=4,
puj = (GLubyte *)((ULONG_PTR)puj + 4*cfb->buf.outerWidth) )
*puj = (*puj & 0x0f) | (dithQuad[dindex] << 4);
}
pujStart += cfb->buf.outerWidth;
}
else {
for (ySpan = rcl->top + j; ySpan < rcl->bottom; ySpan+=4)
{
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
}
}
}
}
/******************************Public*Routine******************************\
* Index4MaskedClear
*
* Clear function for Index4 Masked clears
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
Index4MaskedClear(__GLcolorBuffer *cfb, RECTL *rcl, GLubyte index,
GLubyte *mDither)
{
GLint cSpanWidth, ySpan, w;
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
GLboolean bDIB;
GLubyte *puj, *puj2;
GLubyte result, pixel, src;
GLubyte *pTrans, *pInvTrans, *clearDither;
GLuint i,j;
GLuint dithX, dithY; // x,y offsets into dither matrix
cSpanWidth = rcl->right - rcl->left;
bDIB = cfb->buf.flags & DIB_FORMAT ? TRUE : FALSE;
pTrans = (GLubyte *) gengc->pajTranslateVector;
pInvTrans = (GLubyte *) gengc->pajInvTranslateVector;
puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + (rcl->left>>1))
: gengc->ColorsBits;
if( mDither ) {
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
}
for (ySpan = rcl->top, j=0; ySpan < rcl->bottom; ySpan++, j++) {
i = 0;
if( !bDIB ) {
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, FALSE);
}
if( mDither )
clearDither = mDither + ((dithY + j)&3)*4;
src = (GLubyte)(index & cfb->sourceMask);
w = cSpanWidth;
puj2 = puj;
if ( rcl->left & 1 ) {
result = (GLubyte)(pInvTrans[*puj2 & 0xf] & cfb->destMask);
if( mDither ) {
src = clearDither[dithX];
i++;
}
result = pTrans[src | result];
*puj2++ = (*puj2 & 0xf0) | result;
w--;
}
while( w > 1 ) {
pixel = (GLubyte)(pInvTrans[*puj2 >> 4] & cfb->destMask);
pixel = pTrans[src | pixel];
result = pixel << 4;
pixel = (GLubyte)(pInvTrans[*puj2 & 0x0f] & cfb->destMask);
if( mDither )
src = clearDither[(dithX + i)&3];
pixel = pTrans[src | pixel];
*puj2++ = result | pixel;
w -= 2;
i++;
}
if( w ) {
result = (GLubyte)(pInvTrans[*puj2 >> 4] & cfb->destMask);
if( mDither )
src = clearDither[(dithX + i)&3];
result = pTrans[src | result];
*puj2++ = (*puj2 & 0x0f) | (result << 4);
}
if( !bDIB )
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
if( bDIB ) {
puj += cfb->buf.outerWidth;
}
}
}
/******************************Public*Routine******************************\
* DIBIndex4Clear
*
* Clear function for DIB 4-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL DIBIndex4Clear(__GLcolorBuffer *cfb, RECTL *rcl, BYTE clearColor)
{
UINT cjSpan; // length of span in bytes
LONG lRightByte, // right edge of span that is byte aligned
lLeftByte; // left edge of span that is byte aligned
GLubyte *puj, *pujEnd; // pointers into DIB
lLeftByte = (rcl->left + 1) / 2;
lRightByte = rcl->right / 2;
cjSpan = lRightByte - lLeftByte;
// Copy the clear color into the DIB.
puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + lLeftByte);
pujEnd = (GLubyte *)((ULONG_PTR)puj + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
// Note: exit condition is (pul != pulEnd) rather than (pul < pulEnd)
// because the DIB may be upside down which means that pul is moving
// "backward" in memory rather than "forward".
for ( ; puj != pujEnd; puj = (GLubyte *)((ULONG_PTR)puj + cfb->buf.outerWidth) )
{
RtlFillMemory((PVOID) puj, cjSpan, clearColor);
}
// Take care of possible 1 nibble overhang on the left.
if ( rcl->left & 1 )
{
// Inclusive-exclusive, so on the left we want to turn on the pixel that
// that is the "right" pixel in the byte.
puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + (rcl->left/2));
pujEnd = (GLubyte *)((ULONG_PTR)puj + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
for ( ; puj != pujEnd; puj = (GLubyte *)((ULONG_PTR)puj + cfb->buf.outerWidth) )
*puj = (*puj & 0xf0) | (clearColor & 0x0f);
}
// Take care of possible 1 nibble overhang on the right.
if ( rcl->right & 1 )
{
// Inclusive-exclusive, so on the right we want to turn on the pixel that
// that is the "left" pixel in the byte.
puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + (rcl->right/2));
pujEnd = (GLubyte *)((ULONG_PTR)puj + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
for ( ; puj != pujEnd; puj = (GLubyte *)((ULONG_PTR)puj + cfb->buf.outerWidth) )
*puj = (*puj & 0x0f) | (clearColor & 0xf0);
}
}
/******************************Public*Routine******************************\
* Index4Clear
*
* Clear function for all 4-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL Index4Clear(__GLcolorBuffer *cfb)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
PIXELFORMATDESCRIPTOR *pfmt;
GLubyte clearColor; // clear color in 32BPP format
RECTL rcl; // clear rectangle in screen coord.
GLGENwindow *pwnd;
GLboolean bMoreRects = GL_TRUE;
GLboolean bDither = GL_FALSE;
GLboolean bMasking = (cfb->buf.flags & COLORMASK_ON) != 0;
GLboolean bDIB = (cfb->buf.flags & DIB_FORMAT) != 0;
GLboolean bUseMcdSpans = gengc->pMcdState && !bDIB;
GLboolean bRGBA;
GLubyte ditherMatrix[4][4];
GLint ClipEnumState;
DBGENTRY("Index4Clear\n");
pfmt = &gengc->gsurf.pfd;
bRGBA = (pfmt->iPixelType == PFD_TYPE_RGBA);
/* if dithering enabled, see if we can ignore it, and if not,
precompute a dither matrix
*/
if( gc->state.enables.general & __GL_DITHER_ENABLE ) {
bDither = CalcDitherMatrix( cfb, bRGBA, bMasking, GL_FALSE,
(GLubyte *)ditherMatrix );
}
// Convert the clear color to 4BPP format.
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
clearColor =
((BYTE)(gc->state.raster.clear.r*gc->frontBuffer.redScale +
__glHalf) << cfb->redShift) |
((BYTE)(gc->state.raster.clear.g*gc->frontBuffer.greenScale +
__glHalf) << cfb->greenShift) |
((BYTE)(gc->state.raster.clear.b*gc->frontBuffer.blueScale +
__glHalf) << cfb->blueShift);
}
else {
clearColor = (BYTE) (gc->state.raster.clearIndex + 0.5F);
clearColor &= cfb->redMax;
}
clearColor = gengc->pajTranslateVector[clearColor];
clearColor = (clearColor << 4) | clearColor;
// Get clear rectangle in screen coordinates.
pwnd = cfb->bitmap->pwnd;
if (pwnd->clipComplexity == CLC_COMPLEX) {
InitClearRectangle(pwnd, &ClipEnumState);
#ifdef LATER
} else if ( !bMasking
&& !bDither
&& bDIB
&& gengc->fDirtyRegionEnabled
&& !RECTLISTIsMax(&gengc->rlClear)
&& ((GLuint)clearColor == gengc->clearColor)
) {
//
// use dirty region rects
//
if (!RECTLISTIsEmpty(&gengc->rlClear)) {
PYLIST pylist = gengc->rlClear.pylist;
while (pylist != NULL) {
PXLIST pxlist = pylist->pxlist;
rcl.top = pylist->s;
rcl.bottom = pylist->e;
while (pxlist != NULL) {
rcl.left = pxlist->s;
rcl.right = pxlist->e;
DIBIndex4Clear( cfb, &rcl, clearColor );
pxlist = pxlist->pnext;
}
pylist = pylist->pnext;
}
//
// Union the blt region with the Clear region
// and set the clear region to empty
//
RECTLISTOrAndClear(&gengc->rlBlt, &gengc->rlClear);
}
return;
}
if (gengc->fDirtyRegionEnabled) {
//
// if we come through this path then for some reason we
// are clearing the entire window
//
RECTLISTSetEmpty(&gengc->rlClear);
RECTLISTSetMax(&gengc->rlBlt);
//
// remember the clear color
//
gengc->clearColor = (GLuint)clearColor;
#endif
}
while (bMoreRects)
{
// Must use MCD spans if buffer not accessible as DIB. In such a
// case, window offset has been removed (see GenMcdUpdateBufferInfo),
// so a window relative rectangle is required for the clear. Also,
// because the driver handles clipping, we do not need to enumerate
// rects.
if (bUseMcdSpans) {
rcl.left = __GL_UNBIAS_X(gc, gc->transform.clipX0);
rcl.right = __GL_UNBIAS_X(gc, gc->transform.clipX1);
rcl.bottom = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
rcl.top = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
bMoreRects = FALSE;
} else
bMoreRects = GetClearSubRectangle(cfb, &rcl, pwnd, &ClipEnumState);
if (rcl.right == rcl.left)
continue;
// Case: no dithering, no masking
if( !bMasking && !bDither ) {
if (bDIB)
DIBIndex4Clear( cfb, &rcl, clearColor );
else if (bUseMcdSpans)
Index4MaskedClear( cfb, &rcl, clearColor, NULL );
else
wglFillRect(gengc, pwnd, &rcl,
(ULONG) clearColor & 0x0000000F);
}
// Case: any masking
else if( bMasking ) {
Index4MaskedClear( cfb, &rcl, clearColor,
bDither ? (GLubyte *)ditherMatrix : NULL );
}
// Case: just dithering
else {
Index4DitherClear(cfb, &rcl, (GLubyte *)ditherMatrix, bDIB );
}
}
}
/******************************Public*Routine******************************\
* Index8DitherClear
*
* Clear device managed surface to the dithered clear color indicated
* in the __GLcolorBuffer.
*
* History:
* 06-Dec-1993 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void
Index8DitherClear(__GLcolorBuffer *cfb, RECTL *rcl, GLubyte *mDither,
GLboolean bDIB)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
UINT cjSpan; // length of span in bytes
GLubyte *pDither; // dithered color, relative to window origin
UINT i, j; // indices into the dither array
GLubyte *puj, *pujStart; // pointer into span buffer
GLint ySpan; // index to window row to clear
GLuint dithX, dithY; // x,y offsets into dither matrix
GLubyte dithQuad[4]; // dither repetion quad along a span
cjSpan = rcl->right - rcl->left;
if( bDIB )
pujStart = (GLubyte *)
((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + rcl->left);
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
for (j = 0; (j < 4) && ((rcl->top + j) < (UINT)rcl->bottom); j++)
{
// arrange the 4-pixel dither repetition pattern in x
pDither = mDither + ((dithY+j)&3)*4;
for( i = 0; i < 4; i ++ ) {
dithQuad[i] = pDither[(dithX+i)&3];
}
// Copy the clear color into the span buffer.
puj = gengc->ColorsBits;
for (i = cjSpan / 4; i; i--)
{
*puj++ = dithQuad[0];
*puj++ = dithQuad[1];
*puj++ = dithQuad[2];
*puj++ = dithQuad[3];
}
for (i = 0; i < (cjSpan & 3); i++)
{
*puj++ = dithQuad[i];
}
// Copy the span to the display for every 4th row of the window.
//!!!XXX -- It may be worth writing a (*gengc->pfnCopyPixelsN) routine which
//!!!XXX will do the loop in one call. This will save not only call
//!!!XXX overhead but also other engine locking overhead. Something
//!!!XXX like: (*gengc->pfnCopyPixelsN)(hdc, hbm, x, y, w, n, yDelta)
if( bDIB ) {
for (ySpan = rcl->top + j, puj = pujStart;
ySpan < rcl->bottom;
ySpan+=4,
puj = (GLubyte *)((ULONG_PTR)puj + 4*cfb->buf.outerWidth) ) {
RtlCopyMemory_UnalignedDst( puj, gengc->ColorsBits, cjSpan );
}
pujStart += cfb->buf.outerWidth;
}
else {
for (ySpan = rcl->top + j; ySpan < rcl->bottom; ySpan+=4)
{
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cjSpan, TRUE);
}
}
}
}
/******************************Public*Routine******************************\
* Index8MaskedClear
*
* Clear function for Index8 Masked clears
* (Also handles dithering when masking on)
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
Index8MaskedClear(__GLcolorBuffer *cfb, RECTL *rcl, GLubyte index,
GLubyte *mDither)
{
GLint cSpanWidth, ySpan;
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
GLboolean bDIB;
GLubyte *puj, *puj2, *pujEnd;
GLubyte result, src;
GLubyte *pTrans, *pInvTrans, *clearDither;
GLuint i,j;
GLuint dithX, dithY; // x,y offsets into dither matrix
cSpanWidth = rcl->right - rcl->left;
bDIB = cfb->buf.flags & DIB_FORMAT ? TRUE : FALSE;
pTrans = (GLubyte *) gengc->pajTranslateVector;
pInvTrans = (GLubyte *) gengc->pajInvTranslateVector;
puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + rcl->left)
: gengc->ColorsBits;
pujEnd = puj + cSpanWidth;
src = (GLubyte)(index & cfb->sourceMask);
if( mDither ) {
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
}
for (ySpan = rcl->top, j = 0; ySpan < rcl->bottom; ySpan++, j++) {
if( !bDIB ) {
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, FALSE);
}
if( mDither ) {
clearDither = mDither + ((dithY + j)&3)*4;
for( puj2 = puj, i = 0; puj2 < pujEnd; puj2++, i++ ) {
result = (GLubyte)(pInvTrans[*puj2] & cfb->destMask);
src = clearDither[(dithX + i)&3];
*puj2 = pTrans[result | src];
}
} else {
for( puj2 = puj, i = 0; puj2 < pujEnd; puj2++, i++ ) {
result = (GLubyte)(pInvTrans[*puj2] & cfb->destMask);
*puj2 = pTrans[result | src];
}
}
if( !bDIB )
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
if( bDIB ) {
puj += cfb->buf.outerWidth;
pujEnd = puj + cSpanWidth;
}
}
}
/******************************Public*Routine******************************\
* DIBIndex8Clear
*
* Clear function for DIB 8-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL DIBIndex8Clear(__GLcolorBuffer *cfb, RECTL *rcl, BYTE index)
{
int width = rcl->right - rcl->left;
int height = (rcl->bottom - rcl->top);
GLubyte *puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + rcl->left);
GLubyte *pujEnd;
if (cfb->buf.outerWidth > 0) {
if (width == cfb->buf.outerWidth) {
RtlFillMemory((PVOID) puj, width * height, index);
return;
}
} else {
if (width == -cfb->buf.outerWidth) {
RtlFillMemory(
(PVOID)((ULONG_PTR)puj - width * (height - 1)),
width * height,
index);
return;
}
}
pujEnd = (GLubyte *)((ULONG_PTR)puj + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
// Note: exit condition is (pul != pulEnd) rather than (pul < pulEnd)
// because the DIB may be upside down which means that pul is moving
// "backward" in memory rather than "forward".
for ( ; puj != pujEnd; puj = (GLubyte *)((ULONG_PTR)puj + cfb->buf.outerWidth) ) {
RtlFillMemory((PVOID) puj, width, index);
}
}
/******************************Public*Routine******************************\
* Index8Clear
*
* Clear function for all 8-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
* Oct-03-1995 -by- Marc Fortier [marcfo]
* Don't translate color if masking enabled
\**************************************************************************/
void FASTCALL Index8Clear(__GLcolorBuffer *cfb)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
PIXELFORMATDESCRIPTOR *pfmt;
BYTE clearColor;
RECTL rcl;
GLGENwindow *pwnd;
GLboolean bMoreRects = GL_TRUE;
GLboolean bDither = GL_FALSE;
GLboolean bMasking = (cfb->buf.flags & COLORMASK_ON) != 0;
GLboolean bDIB = (cfb->buf.flags & DIB_FORMAT) != 0;
GLboolean bUseMcdSpans = gengc->pMcdState && !bDIB;
GLboolean bRGBA;
GLubyte ditherMatrix[4][4];
GLint ClipEnumState;
DBGENTRY("Index8Clear\n");
pfmt = &gengc->gsurf.pfd;
bRGBA = (pfmt->iPixelType == PFD_TYPE_RGBA);
/* if dithering enabled, see if we can ignore it, and if not,
precompute a dither matrix
*/
if( gc->state.enables.general & __GL_DITHER_ENABLE ) {
bDither = CalcDitherMatrix( cfb, bRGBA, bMasking, GL_FALSE,
(GLubyte *)ditherMatrix );
}
// Convert clear value to index
if( bRGBA ) {
clearColor =
((BYTE)(gc->state.raster.clear.r*gc->frontBuffer.redScale + __glHalf) <<
cfb->redShift) |
((BYTE)(gc->state.raster.clear.g*gc->frontBuffer.greenScale + __glHalf) <<
cfb->greenShift) |
((BYTE)(gc->state.raster.clear.b*gc->frontBuffer.blueScale + __glHalf) <<
cfb->blueShift);
}
else {
clearColor = (BYTE) (gc->state.raster.clearIndex + __glHalf);
clearColor &= cfb->redMax;
}
// translate color to index
if( !bMasking )
clearColor = gengc->pajTranslateVector[clearColor];
// Get clear rectangle in screen coordinates.
pwnd = cfb->bitmap->pwnd;
if (pwnd->clipComplexity == CLC_COMPLEX) {
InitClearRectangle(pwnd, &ClipEnumState);
#ifdef LATER
} else if ( !bMasking
&& !bDither
&& bDIB
&& gengc->fDirtyRegionEnabled
&& !RECTLISTIsMax(&gengc->rlClear)
&& ((GLuint)clearColor == gengc->clearColor)
) {
//
// use dirty region rects
//
if (!RECTLISTIsEmpty(&gengc->rlClear)) {
PYLIST pylist = gengc->rlClear.pylist;
while (pylist != NULL) {
PXLIST pxlist = pylist->pxlist;
rcl.top = pylist->s;
rcl.bottom = pylist->e;
while (pxlist != NULL) {
rcl.left = pxlist->s;
rcl.right = pxlist->e;
DIBIndex8Clear( cfb, &rcl, clearColor );
pxlist = pxlist->pnext;
}
pylist = pylist->pnext;
}
//
// Union the blt region with the Clear region
// and set the clear region to empty
//
RECTLISTOrAndClear(&gengc->rlBlt, &gengc->rlClear);
}
return;
}
if (gengc->fDirtyRegionEnabled) {
//
// if we come through this path then for some reason we
// are clearing the entire window
//
RECTLISTSetEmpty(&gengc->rlClear);
RECTLISTSetMax(&gengc->rlBlt);
//
// remember the clear color
//
gengc->clearColor = (GLuint)clearColor;
#endif
}
while (bMoreRects)
{
// Must use MCD spans if buffer not accessible as DIB. In such a
// case, window offset has been removed (see GenMcdUpdateBufferInfo),
// so a window relative rectangle is required for the clear. Also,
// because the driver handles clipping, we do not need to enumerate
// rects.
if (bUseMcdSpans) {
rcl.left = __GL_UNBIAS_X(gc, gc->transform.clipX0);
rcl.right = __GL_UNBIAS_X(gc, gc->transform.clipX1);
rcl.bottom = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
rcl.top = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
bMoreRects = FALSE;
} else
bMoreRects = GetClearSubRectangle(cfb, &rcl, pwnd, &ClipEnumState);
if (rcl.right == rcl.left)
continue;
// Case: no dithering, no masking
if( !bMasking && !bDither ) {
if( bDIB )
DIBIndex8Clear( cfb, &rcl, clearColor );
else if (bUseMcdSpans)
Index8MaskedClear( cfb, &rcl, clearColor, NULL );
else
wglFillRect(gengc, pwnd, &rcl,
(ULONG) clearColor & 0x000000FF);
}
// Case: masking, maybe dithering
else if( bMasking ) {
Index8MaskedClear( cfb, &rcl, clearColor,
bDither ? (GLubyte *)ditherMatrix : NULL );
}
// Case: just dithering
else {
Index8DitherClear(cfb, &rcl, (GLubyte *)ditherMatrix, bDIB );
}
}
}
/******************************Public*Routine******************************\
* RGBMaskedClear
*
* Clear function for 24-bit (RGB/BGR) Masked clears
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
RGBMaskedClear(__GLcolorBuffer *cfb, RECTL *rcl, GLuint color, GLuint index)
{
GLint cSpanWidth, ySpan;
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
__GLcontext *gc = (__GLcontext *) gengc;
PIXELFORMATDESCRIPTOR *pfmt;
GLboolean bDIB;
GLuint *destColors, *cp;
GLubyte *puj, *puj2, *pujEnd;
GLuint result, src;
GLuint *pTrans;
pfmt = &gengc->gsurf.pfd;
cSpanWidth = rcl->right - rcl->left;
bDIB = cfb->buf.flags & DIB_FORMAT ? TRUE : FALSE;
if( pfmt->iPixelType != PFD_TYPE_RGBA ) {
destColors = (GLuint *) gcTempAlloc(gc, cSpanWidth*sizeof(GLuint));
if( NULL == destColors )
return;
pTrans = (GLuint *) gengc->pajTranslateVector + 1;
}
puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + (rcl->left*3))
: gengc->ColorsBits;
pujEnd = puj + 3*cSpanWidth;
for (ySpan = rcl->top; ySpan < rcl->bottom; ySpan++) {
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
// fetch based on bDIB
if( !bDIB ) {
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, FALSE);
}
src = color & cfb->sourceMask;
for( puj2 = puj; puj2 < pujEnd; puj2+=3 ) {
Copy3Bytes( &result, puj2 ); // get dst pixel
result = src | (result & cfb->destMask);
Copy3Bytes( puj2, &result );
}
}
else { // Color Index
ScrnRGBCIReadSpan( cfb, rcl->left, ySpan, destColors, cSpanWidth,
bDIB );
cp = destColors;
src = index & cfb->sourceMask;
for( puj2 = puj; puj2 < pujEnd; puj2+=3, cp++ ) {
result = src | (*cp & cfb->destMask);
result = pTrans[result];
Copy3Bytes( puj2, &result );
}
}
if( !bDIB )
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
if( bDIB ) {
puj += cfb->buf.outerWidth;
pujEnd = puj + 3*cSpanWidth;
}
}
if( pfmt->iPixelType != PFD_TYPE_RGBA )
gcTempFree(gc, destColors);
}
/******************************Public*Routine******************************\
* DIBRGBClear
*
* Clear function for 24-bit (RGB/BGR) DIB pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL DIBRGBClear(__GLcolorBuffer *cfb, RECTL *rcl, GLubyte *color)
{
__GLcontext *gc = cfb->buf.gc;
GLint width = (rcl->right - rcl->left) * 3;
GLuint *pul = (GLuint *) (((ULONG_PTR)cfb->buf.base +
rcl->top*cfb->buf.outerWidth) + (rcl->left*3));
GLuint *pulEnd;
GLubyte clear0, clear1, clear2;
BYTE *ScanLineBuf;
ScanLineBuf = (BYTE *) gcTempAlloc (gc, width);
if (ScanLineBuf) {
// Alloc succeeds
clear0 = color[0]; clear1 = color[1]; clear2 = color[2];
RtlFillMemory24((PVOID)ScanLineBuf, width, clear0, clear1, clear2);
pulEnd = (GLuint *)((ULONG_PTR)pul +
((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
// Note: exit condition is (pul != pulEnd) rather than (pul < pulEnd)
// because the DIB may be upside down which means that pul is moving
// "backward" in memory rather than "forward".
for ( ; pul != pulEnd;
pul = (GLuint *)((ULONG_PTR)pul + cfb->buf.outerWidth))
memcpy((PVOID) pul, ScanLineBuf, width);
gcTempFree(gc, ScanLineBuf);
}
}
/******************************Public*Routine******************************\
* RGBClear
*
* Clear function for all 24-bit (RGB/BGR) pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL RGBClear(__GLcolorBuffer *cfb)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
PIXELFORMATDESCRIPTOR *pfmt;
RECTL rcl;
GLuint clearColor;
GLGENwindow *pwnd;
GLboolean bMoreRects = GL_TRUE;
DWORD index;
GLint ClipEnumState;
GLboolean bMasking = (cfb->buf.flags & COLORMASK_ON) != 0;
GLboolean bDIB = (cfb->buf.flags & DIB_FORMAT) != 0;
GLboolean bUseMcdSpans = gengc->pMcdState && !bDIB;
DBGENTRY("RGBClear\n");
// Convert the clear color to individual RGB components.
pfmt = &gengc->gsurf.pfd;
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
GLubyte clearR, clearG, clearB;
GLubyte *pClearColor;
clearR = (GLubyte)(gc->state.raster.clear.r*gc->frontBuffer.redScale);
clearG = (GLubyte)(gc->state.raster.clear.g*gc->frontBuffer.greenScale);
clearB = (GLubyte)(gc->state.raster.clear.b*gc->frontBuffer.blueScale);
pClearColor = (GLubyte *) &clearColor;
if( cfb->redShift == 16 ) {
// BGR mode
*pClearColor++ = clearB;
*pClearColor++ = clearG;
*pClearColor = clearR;
}
else {
// RGB mode
*pClearColor++ = clearR;
*pClearColor++ = clearG;
*pClearColor = clearB;
}
}
else {
GLuint *pTrans;
index = (DWORD) (gc->state.raster.clearIndex + 0.5F);
index &= cfb->redMax;
pTrans = (GLuint *) gengc->pajTranslateVector;
clearColor = pTrans[index+1];
}
// Get clear rectangle in screen coordinates.
pwnd = cfb->bitmap->pwnd;
if (pwnd->clipComplexity == CLC_COMPLEX) {
InitClearRectangle(pwnd, &ClipEnumState);
#ifdef LATER
} else if ( !bMasking
&& bDIB
&& gengc->fDirtyRegionEnabled
&& !RECTLISTIsMax(&gengc->rlClear)
&& ((GLuint)clearColor == gengc->clearColor)
) {
//
// use dirty region rects
//
if (!RECTLISTIsEmpty(&gengc->rlClear)) {
PYLIST pylist = gengc->rlClear.pylist;
while (pylist != NULL) {
PXLIST pxlist = pylist->pxlist;
rcl.top = pylist->s;
rcl.bottom = pylist->e;
while (pxlist != NULL) {
rcl.left = pxlist->s;
rcl.right = pxlist->e;
DIBRGBClear( cfb, &rcl, (GLubyte *) &clearColor);
pxlist = pxlist->pnext;
}
pylist = pylist->pnext;
}
//
// Union the blt region with the Clear region
// and set the clear region to empty
//
RECTLISTOrAndClear(&gengc->rlBlt, &gengc->rlClear);
}
return;
}
if (gengc->fDirtyRegionEnabled) {
//
// if we come through this path then for some reason we
// are clearing the entire window
//
RECTLISTSetEmpty(&gengc->rlClear);
RECTLISTSetMax(&gengc->rlBlt);
//
// remember the clear color
//
gengc->clearColor = (GLuint)clearColor;
#endif
}
while (bMoreRects)
{
// Must use MCD spans if buffer not accessible as DIB. In such a
// case, window offset has been removed (see GenMcdUpdateBufferInfo),
// so a window relative rectangle is required for the clear. Also,
// because the driver handles clipping, we do not need to enumerate
// rects.
if (bUseMcdSpans) {
rcl.left = __GL_UNBIAS_X(gc, gc->transform.clipX0);
rcl.right = __GL_UNBIAS_X(gc, gc->transform.clipX1);
rcl.bottom = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
rcl.top = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
bMoreRects = FALSE;
} else
bMoreRects = GetClearSubRectangle(cfb, &rcl, pwnd, &ClipEnumState);
if (rcl.right == rcl.left)
continue;
// Call aproppriate clear function
if (bMasking || bUseMcdSpans) { // or INDEXMASK_ON
RGBMaskedClear( cfb, &rcl, clearColor, index );
}
else {
if (bDIB)
DIBRGBClear( cfb, &rcl, (GLubyte *) &clearColor);
else
wglFillRect(gengc, pwnd, &rcl,
(ULONG) clearColor & 0x00FFFFFF);
}
}
}
/******************************Public*Routine******************************\
* Bitfield16DitherClear
*
* Clear device managed surface to the dithered clear color indicated
* in the __GLcolorBuffer.
*
* History:
* 06-Dec-1993 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void
Bitfield16DitherClear(__GLcolorBuffer *cfb, RECTL *rcl, GLushort *mDither,
GLboolean bDIB)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
GLushort *pDither; // dithered color, relative to window origin
UINT i, j;
GLushort *pus, *pusStart; // pointer into span buffer
GLint ySpan; // index to window row to clear
GLuint cSpanWidth, cSpanWidth2;
GLint outerWidth4;
GLuint dithX, dithY; // x,y offsets into dither matrix
GLushort dithQuad[4]; // dither repetion quad along a span
cSpanWidth = rcl->right - rcl->left;
if( bDIB )
{
pusStart = (GLushort *)
((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + (rcl->left << 1));
/*
* Dither patterns repeat themselves every four rows
*/
outerWidth4 = cfb->buf.outerWidth << 2;
/*
* cSpanWidth is in pixels, convert it to bytes
*/
cSpanWidth2 = cSpanWidth << 1;
}
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
for (j = 0; (j < 4) && ((rcl->top + j) < (UINT)rcl->bottom); j++)
{
// arrange the 4-pixel dither repetition pattern in x
pDither = mDither + ((dithY+j)&3)*4;
for( i = 0; i < 4; i ++ ) {
dithQuad[i] = pDither[(dithX+i)&3];
}
// Copy the clear color into the span buffer.
pus = gengc->ColorsBits;
for (i = cSpanWidth / 4; i; i--)
{
*pus++ = dithQuad[0];
*pus++ = dithQuad[1];
*pus++ = dithQuad[2];
*pus++ = dithQuad[3];
}
for (i = 0; i < (cSpanWidth & 3); i++)
{
*pus++ = dithQuad[i];
}
// Copy the span to the display for every 4th row of the window.
if( bDIB ) {
for (ySpan = rcl->top + j, pus = pusStart;
ySpan < rcl->bottom;
ySpan+=4,
pus = (GLushort *)((ULONG_PTR)pus + outerWidth4) ) {
RtlCopyMemory_UnalignedDst( pus, gengc->ColorsBits, cSpanWidth2 );
}
pusStart = (GLushort *)((ULONG_PTR)pusStart + cfb->buf.outerWidth);
}
else {
for (ySpan = rcl->top + j; ySpan < rcl->bottom; ySpan+=4)
{
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
}
}
}
}
/******************************Public*Routine******************************\
* Bitfield16MaskedClear
*
* Clear function for Bitfield16 Masked clears
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
Bitfield16MaskedClear(__GLcolorBuffer *cfb, RECTL *rcl, GLushort color,
GLuint index, GLushort *mDither)
{
GLint cSpanWidth, ySpan;
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
__GLcontext *gc = (__GLcontext *) gengc;
PIXELFORMATDESCRIPTOR *pfmt;
GLboolean bDIB;
GLuint *destColors, *cp;
GLushort *pus, *pus2, *pusEnd, *clearDither;
GLushort result, src;
GLuint *pTrans, i, j;
GLuint dithX, dithY; // x,y offsets into dither matrix
pfmt = &gengc->gsurf.pfd;
cSpanWidth = rcl->right - rcl->left;
bDIB = cfb->buf.flags & DIB_FORMAT ? TRUE : FALSE;
if( pfmt->iPixelType != PFD_TYPE_RGBA ) {
destColors = (GLuint *) gcTempAlloc(gc, cSpanWidth*sizeof(GLuint));
if( NULL == destColors )
return;
pTrans = (GLuint *) gengc->pajTranslateVector + 1;
}
pus = bDIB ? (GLushort *)((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + (rcl->left<<1))
: gengc->ColorsBits;
pusEnd = pus + cSpanWidth;
if( mDither ) {
// calc dither offset in x,y
dithX = (rcl->left - cfb->buf.xOrigin) & 3;
dithY = (rcl->top - cfb->buf.yOrigin) & 3;
}
for (ySpan = rcl->top, j = 0; ySpan < rcl->bottom; ySpan++, j++) {
if( mDither )
clearDither = mDither + ((dithY + j)&3)*4;
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
// fetch based on bDIB
if( !bDIB ) {
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, FALSE);
}
src = (GLushort)(color & cfb->sourceMask);
for( pus2 = pus, i = 0; pus2 < pusEnd; pus2++, i++ ) {
if( mDither )
src = clearDither[(dithX + i)&3];
*pus2 = (GLushort)(src | (*pus2 & cfb->destMask));
}
}
else { // Color Index
ScrnBitfield16CIReadSpan( cfb, rcl->left, ySpan, destColors,
cSpanWidth, bDIB );
cp = destColors;
src = (GLushort)(index & cfb->sourceMask);
for( pus2 = pus, i = 0; pus2 < pusEnd; pus2++, cp++, i++ ) {
if( mDither )
src = clearDither[(dithX + i)&3];
result = (GLushort)(src | (*cp & cfb->destMask));
result = (GLushort)pTrans[result];
*pus2 = result;
}
}
if( !bDIB )
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
if( bDIB ) {
pus = (GLushort *)((ULONG_PTR)pus + cfb->buf.outerWidth);
pusEnd = pus + cSpanWidth;
}
}
if( pfmt->iPixelType != PFD_TYPE_RGBA )
gcTempFree(gc, destColors);
}
/******************************Public*Routine******************************\
* DIBBitfield16Clear
*
* Clear function for 16-bit DIB pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL DIBBitfield16Clear(__GLcolorBuffer *cfb, RECTL *rcl, GLushort clearColor)
{
GLint cSpanWidth; // span width to clear
GLushort *pus, *pusEnd; // pointers into DIB
cSpanWidth = rcl->right - rcl->left;
pus = (GLushort *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + (rcl->left<<1));
pusEnd = (GLushort *)((ULONG_PTR)pus + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
// Note: exit condition is (pul != pulEnd) rather than (pul < pulEnd)
// because the DIB may be upside down which means that pul is moving
// "backward" in memory rather than "forward".
for ( ; pus != pusEnd; pus = (GLushort *)((ULONG_PTR)pus + cfb->buf.outerWidth) )
{
RtlFillMemoryUshort(pus, cSpanWidth * sizeof(GLushort), clearColor);
}
}
//!!!XXX -- don't need yet, but let's keep it around just in case
#if 0
/******************************Public*Routine******************************\
* DisplayBitfield16Clear
*
* Clear device managed surface to the clear color indicated
* in the __GLcolorBuffer.
*
* History:
* 16-Feb-1995 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
void
DisplayBitfield16Clear(__GLcolorBuffer *cfb, RECTL *rcl,
GLushort clearColor)
{
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
GLushort *pus, *pusEnd;
GLint cSpanWidth; // in pixels
GLint ySpan;
cSpanWidth = rcl->right - rcl->left;
pus = (GLushort *) gengc->ColorsBits;
pusEnd = pus + cSpanWidth;
// Initialize a span buffer to clear color.
LocalRtlFillMemoryUshort(pus, cSpanWidth*sizeof(GLushort), clearColor);
for ( ySpan = rcl->top; ySpan < rcl->bottom; ySpan++ )
{
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
}
}
#endif
/******************************Public*Routine******************************\
* Bitfield16Clear
*
* Clear function for all 16-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL Bitfield16Clear(__GLcolorBuffer *cfb)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
PIXELFORMATDESCRIPTOR *pfmt;
GLushort clearColor;
RECTL rcl;
GLGENwindow *pwnd;
GLboolean bMoreRects = GL_TRUE;
GLboolean bDither = GL_FALSE;
GLboolean bMasking = (cfb->buf.flags & COLORMASK_ON) != 0;
GLboolean bDIB = (cfb->buf.flags & DIB_FORMAT) != 0;
GLboolean bUseMcdSpans = gengc->pMcdState && !bDIB;
GLboolean bRGBA;
GLushort ditherMatrix[4][4];
DWORD index;
GLint ClipEnumState;
DBGENTRY("Bitfield16Clear\n");
pfmt = &gengc->gsurf.pfd;
bRGBA = (pfmt->iPixelType == PFD_TYPE_RGBA);
/* if dithering enabled, see if we can ignore it, and if not,
precompute a dither matrix
*/
if( gc->state.enables.general & __GL_DITHER_ENABLE ) {
bDither = CalcDitherMatrix( cfb, bRGBA, bMasking, GL_TRUE,
(GLubyte *)ditherMatrix );
}
// Convert clear value
if( bRGBA ) {
clearColor =
((BYTE)(gc->state.raster.clear.r*gc->frontBuffer.redScale + __glHalf) <<
cfb->redShift) |
((BYTE)(gc->state.raster.clear.g*gc->frontBuffer.greenScale + __glHalf) <<
cfb->greenShift) |
((BYTE)(gc->state.raster.clear.b*gc->frontBuffer.blueScale + __glHalf) <<
cfb->blueShift);
if( ALPHA_IN_PIXEL( cfb ) )
clearColor |=
((BYTE)(gc->state.raster.clear.a*gc->frontBuffer.alphaScale + __glHalf) <<
cfb->alphaShift);
}
else {
GLuint *pTrans;
index = (DWORD) (gc->state.raster.clearIndex + 0.5F);
index &= cfb->redMax;
pTrans = (GLuint *) gengc->pajTranslateVector;
clearColor = (GLushort) pTrans[index+1];
}
// Get clear rectangle in screen coordinates.
pwnd = cfb->bitmap->pwnd;
if (pwnd->clipComplexity == CLC_COMPLEX) {
InitClearRectangle(pwnd, &ClipEnumState);
#ifdef LATER
} else if ( !bMasking
&& !bDither
&& bDIB
&& gengc->fDirtyRegionEnabled
&& !RECTLISTIsMax(&gengc->rlClear)
&& ((GLuint)clearColor == gengc->clearColor)
) {
//
// use dirty region rects
//
if (!RECTLISTIsEmpty(&gengc->rlClear)) {
PYLIST pylist = gengc->rlClear.pylist;
while (pylist != NULL) {
PXLIST pxlist = pylist->pxlist;
rcl.top = pylist->s;
rcl.bottom = pylist->e;
while (pxlist != NULL) {
rcl.left = pxlist->s;
rcl.right = pxlist->e;
DIBBitfield16Clear( cfb, &rcl, clearColor );
pxlist = pxlist->pnext;
}
pylist = pylist->pnext;
}
//
// Union the blt region with the Clear region
// and set the clear region to empty
//
RECTLISTOrAndClear(&gengc->rlBlt, &gengc->rlClear);
}
return;
}
if (gengc->fDirtyRegionEnabled) {
//
// if we come through this path then for some reason we
// are clearing the entire window
//
RECTLISTSetEmpty(&gengc->rlClear);
RECTLISTSetMax(&gengc->rlBlt);
//
// remember the clear color
//
gengc->clearColor = (GLuint)clearColor;
#endif
}
while (bMoreRects)
{
// Must use MCD spans if buffer not accessible as DIB. In such a
// case, window offset has been removed (see GenMcdUpdateBufferInfo),
// so a window relative rectangle is required for the clear. Also,
// because the driver handles clipping, we do not need to enumerate
// rects.
if (bUseMcdSpans) {
rcl.left = __GL_UNBIAS_X(gc, gc->transform.clipX0);
rcl.right = __GL_UNBIAS_X(gc, gc->transform.clipX1);
rcl.bottom = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
rcl.top = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
bMoreRects = FALSE;
} else
bMoreRects = GetClearSubRectangle(cfb, &rcl, pwnd, &ClipEnumState);
if (rcl.right == rcl.left)
continue;
// Case: no dithering, no masking
if( !bMasking && !bDither) {
if (bDIB)
DIBBitfield16Clear( cfb, &rcl, clearColor );
else if (bUseMcdSpans)
Bitfield16MaskedClear( cfb, &rcl, clearColor, index, NULL );
else
wglFillRect(gengc, pwnd, &rcl,
(ULONG) clearColor & 0x0000FFFF);
}
// Case: masking, maybe dithering
else if( bMasking ) {
Bitfield16MaskedClear( cfb, &rcl, clearColor, index,
bDither ? (GLushort *)ditherMatrix : NULL );
}
// Case: just dithering
else {
Bitfield16DitherClear(cfb, &rcl, (GLushort *)ditherMatrix, bDIB );
}
}
}
/******************************Public*Routine******************************\
* Bitfield32MaskedClear
*
* Clear function for Bitfield16 Masked clears
*
* History:
* Feb-09-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void
Bitfield32MaskedClear(__GLcolorBuffer *cfb, RECTL *rcl, GLuint color, GLuint index)
{
GLint cSpanWidth, ySpan;
__GLGENcontext *gengc = (__GLGENcontext *) cfb->buf.gc;
__GLcontext *gc = (__GLcontext *) gengc;
PIXELFORMATDESCRIPTOR *pfmt;
GLboolean bDIB;
GLuint *destColors, *cp;
GLuint *pul, *pul2, *pulEnd;
GLuint result, src;
GLuint *pTrans;
pfmt = &gengc->gsurf.pfd;
cSpanWidth = rcl->right - rcl->left;
bDIB = cfb->buf.flags & DIB_FORMAT ? TRUE : FALSE;
if( pfmt->iPixelType != PFD_TYPE_RGBA ) {
destColors = (GLuint *) gcTempAlloc(gc, cSpanWidth*sizeof(GLuint));
if( NULL == destColors )
return;
pTrans = (GLuint *) gengc->pajTranslateVector + 1;
}
pul = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base +
(rcl->top*cfb->buf.outerWidth) + (rcl->left<<2))
: gengc->ColorsBits;
pulEnd = pul + cSpanWidth;
for (ySpan = rcl->top; ySpan < rcl->bottom; ySpan++) {
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
// fetch based on bDIB
if( !bDIB ) {
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, FALSE);
}
src = color & cfb->sourceMask;
for( pul2 = pul; pul2 < pulEnd; pul2++) {
*pul2 = src | (*pul2 & cfb->destMask);
}
}
else { // Color Index
ScrnBitfield32CIReadSpan( cfb, rcl->left, ySpan, destColors,
cSpanWidth, bDIB );
cp = destColors;
src = index & cfb->sourceMask;
for( pul2 = pul; pul2 < pulEnd; pul2++, cp++ ) {
result = src | (*cp & cfb->destMask);
result = pTrans[result];
*pul2 = result;
}
}
if( !bDIB )
(*gengc->pfnCopyPixels)(gengc, cfb, rcl->left,
ySpan, cSpanWidth, TRUE);
if( bDIB ) {
pul = (GLuint *)((ULONG_PTR)pul + cfb->buf.outerWidth);
pulEnd = pul + cSpanWidth;
}
}
if( pfmt->iPixelType != PFD_TYPE_RGBA )
gcTempFree(gc, destColors);
}
/******************************Public*Routine******************************\
* DIBBitfield32Clear
*
* Clear function for 32-bit DIB pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL DIBBitfield32Clear(__GLcolorBuffer *cfb, RECTL *rcl, GLuint clearColor)
{
GLint width = (rcl->right - rcl->left) * sizeof(ULONG);
GLint height = (rcl->bottom - rcl->top);
GLuint *pul = (GLuint *)((ULONG_PTR)cfb->buf.base + (rcl->top*cfb->buf.outerWidth) + (rcl->left<<2));
GLuint *pulEnd;
if (cfb->buf.outerWidth > 0) {
if (width == cfb->buf.outerWidth) {
RtlFillMemoryUlong((PVOID) pul, width * height, clearColor);
return;
}
} else {
if (width == -cfb->buf.outerWidth) {
RtlFillMemoryUlong(
(PVOID)((ULONG_PTR)pul - width * (height - 1)),
width * height,
clearColor);
return;
}
}
pulEnd = (GLuint *)((ULONG_PTR)pul + ((rcl->bottom-rcl->top)*cfb->buf.outerWidth));
// Note: exit condition is (pul != pulEnd) rather than (pul < pulEnd)
// because the DIB may be upside down which means that pul is moving
// "backward" in memory rather than "forward".
for ( ; pul != pulEnd; pul = (GLuint *)((ULONG_PTR)pul + cfb->buf.outerWidth))
{
RtlFillMemoryUlong((PVOID) pul, width, clearColor);
}
}
/******************************Public*Routine******************************\
* Bitfield32Clear
*
* Clear function for all 32-bit pixel formats
*
* History:
* Feb-03-1994 -by- Marc Fortier [v-marcf]
* Wrote it.
\**************************************************************************/
void FASTCALL Bitfield32Clear(__GLcolorBuffer *cfb)
{
__GLcontext *gc = cfb->buf.gc;
__GLGENcontext *gengc = (__GLGENcontext *)gc;
PIXELFORMATDESCRIPTOR *pfmt;
GLuint clearColor;
RECTL rcl;
DWORD index;
GLGENwindow *pwnd;
GLboolean bMoreRects = GL_TRUE;
GLint ClipEnumState;
GLboolean bMasking = (cfb->buf.flags & COLORMASK_ON) != 0;
GLboolean bDIB = (cfb->buf.flags & DIB_FORMAT) != 0;
GLboolean bUseMcdSpans = gengc->pMcdState && !bDIB;
DBGENTRY("Bitfield32Clear\n");
// Convert clear value
pfmt = &gengc->gsurf.pfd;
if( pfmt->iPixelType == PFD_TYPE_RGBA ) {
clearColor =
((BYTE)(gc->state.raster.clear.r*gc->frontBuffer.redScale + __glHalf) <<
cfb->redShift) |
((BYTE)(gc->state.raster.clear.g*gc->frontBuffer.greenScale + __glHalf) <<
cfb->greenShift) |
((BYTE)(gc->state.raster.clear.b*gc->frontBuffer.blueScale + __glHalf) <<
cfb->blueShift);
if( ALPHA_IN_PIXEL( cfb ) )
clearColor |=
((BYTE)(gc->state.raster.clear.a*gc->frontBuffer.alphaScale + __glHalf) <<
cfb->alphaShift);
}
else {
GLuint *pTrans;
index = (DWORD) (gc->state.raster.clearIndex + 0.5F);
index &= cfb->redMax;
pTrans = (GLuint *) gengc->pajTranslateVector;
clearColor = pTrans[index+1];
}
// Get clear rectangle in screen coordinates.
pwnd = cfb->bitmap->pwnd;
if (pwnd->clipComplexity == CLC_COMPLEX) {
InitClearRectangle(pwnd, &ClipEnumState);
#ifdef LATER
} else if ( !bMasking
&& bDIB
&& gengc->fDirtyRegionEnabled
&& !RECTLISTIsMax(&gengc->rlClear)
&& ((GLuint)clearColor == gengc->clearColor)
) {
//
// use dirty region rects
//
if (!RECTLISTIsEmpty(&gengc->rlClear)) {
PYLIST pylist = gengc->rlClear.pylist;
while (pylist != NULL) {
PXLIST pxlist = pylist->pxlist;
rcl.top = pylist->s;
rcl.bottom = pylist->e;
while (pxlist != NULL) {
rcl.left = pxlist->s;
rcl.right = pxlist->e;
DIBBitfield32Clear( cfb, &rcl, clearColor );
pxlist = pxlist->pnext;
}
pylist = pylist->pnext;
}
//
// Union the blt region with the Clear region
// and set the clear region to empty
//
RECTLISTOrAndClear(&gengc->rlBlt, &gengc->rlClear);
}
return;
}
if (gengc->fDirtyRegionEnabled) {
//
// if we come through this path then for some reason we
// are clearing the entire window
//
RECTLISTSetEmpty(&gengc->rlClear);
RECTLISTSetMax(&gengc->rlBlt);
//
// remember the clear color
//
gengc->clearColor = (GLuint)clearColor;
#endif
}
while (bMoreRects)
{
// Must use MCD spans if buffer not accessible as DIB. In such a
// case, window offset has been removed (see GenMcdUpdateBufferInfo),
// so a window relative rectangle is required for the clear. Also,
// because the driver handles clipping, we do not need to enumerate
// rects.
if (bUseMcdSpans) {
rcl.left = __GL_UNBIAS_X(gc, gc->transform.clipX0);
rcl.right = __GL_UNBIAS_X(gc, gc->transform.clipX1);
rcl.bottom = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
rcl.top = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
bMoreRects = FALSE;
} else
bMoreRects = GetClearSubRectangle(cfb, &rcl, pwnd, &ClipEnumState);
if (rcl.right == rcl.left)
continue;
// Call aproppriate clear function
if (bMasking || bUseMcdSpans) { // or INDEXMASK_ON
Bitfield32MaskedClear( cfb, &rcl, clearColor, index );
}
else {
if (bDIB)
DIBBitfield32Clear( cfb, &rcl, clearColor );
else
wglFillRect(gengc, pwnd, &rcl, (ULONG) clearColor);
}
}
}