mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2419 lines
75 KiB
2419 lines
75 KiB
/******************************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);
|
|
}
|
|
}
|
|
|
|
|
|
}
|