|
|
/******************************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); } }
}
|