/* ** Copyright 1991, 1992, 1993, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. */ #include "precomp.h" #pragma hdrstop #include "genrgb.h" #include "genclear.h" #define STATIC __GLfloat fDitherIncTable[16] = { DITHER_INC(0), DITHER_INC(8), DITHER_INC(2), DITHER_INC(10), DITHER_INC(12), DITHER_INC(4), DITHER_INC(14), DITHER_INC(6), DITHER_INC(3), DITHER_INC(11), DITHER_INC(1), DITHER_INC(9), DITHER_INC(15), DITHER_INC(7), DITHER_INC(13), DITHER_INC(5) }; /* No Dither, No blend, No Write, No Nothing */ STATIC void FASTCALL Store_NOT(__GLcolorBuffer *cfb, const __GLfragment *frag) { } STATIC GLboolean FASTCALL StoreSpanNone(__GLcontext *gc) { return GL_FALSE; } // // Special case normal alpha blending (source alpha*src + dst*(1-sa)) // This case is used in antialiasing and actually jumping through // the fetch and blend procs takes up a large amount of time. Moving // the code into the store proc removes this overhead // // The macro requires a standard store proc setup, with gc, cfb, frag, // blendColor and so on. It requires a dst_pix variable which // will hold a pixel in the destination format. // It also takes as an argument a statement which will set dst_pix. // The reason it doesn't take the pixel itself is because only the special case // actually needs the value. In all the flags cases the pixel // retrieval would be wasted. // extern void __glDoBlend_SA_MSA(__GLcontext *gc, const __GLcolor *source, const __GLcolor *dest, __GLcolor *result); #define SPECIAL_ALPHA_BLEND(dst_pix_gen) \ color = &blendColor; \ if( (gc->procs.blendColor == __glDoBlend_SA_MSA) && \ !( ALPHA_WRITE_ENABLED( cfb )) ) \ { \ __GLfloat a, msa; \ \ a = frag->color.a * gc->frontBuffer.oneOverAlphaScale; \ msa = __glOne - a; \ \ dst_pix_gen; \ blendColor.r = frag->color.r*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.redMask) >> cfb->redShift); \ blendColor.g = frag->color.g*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.greenMask) >> cfb->greenShift); \ blendColor.b = frag->color.b*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.blueMask) >> cfb->blueShift); \ } \ else \ { \ (*gc->procs.blend)( gc, cfb, frag, &blendColor ); \ } #define SPECIAL_ALPHA_BLEND_SPAN(dst_pix_gen) \ if( (gc->procs.blendColor == __glDoBlend_SA_MSA) && \ !( ALPHA_WRITE_ENABLED( cfb )) ) \ { \ __GLcolor *color = gc->polygon.shader.colors; \ \ for ( i = 0; i < w; i++, color++ ) \ { \ __GLfloat a, msa; \ \ a = color->a * gc->frontBuffer.oneOverAlphaScale; \ msa = __glOne - a; \ \ dst_pix_gen; \ color->r = color->r*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.redMask) >> cfb->redShift); \ color->g = color->g*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.greenMask) >> cfb->greenShift); \ color->b = color->b*a + msa*(__GLfloat) \ ((dst_pix & gc->modes.blueMask) >> cfb->blueShift); \ } \ } \ else \ { \ (*gc->procs.blendSpan)( gc ); \ } #define DitheredRGBColorToBuffer(col, incr, cfb, dest, type) \ ((dest) = (type)(( FTOL((col)->r+(incr)) << (cfb)->redShift) | \ ( FTOL((col)->g+(incr)) << (cfb)->greenShift) | \ ( FTOL((col)->b+(incr)) << (cfb)->blueShift))) #define UnditheredRGBColorToBuffer(col, cfb, dest, type) \ ((dest) = (type)(( FTOL((col)->r) << (cfb)->redShift) | \ ( FTOL((col)->g) << (cfb)->greenShift) | \ ( FTOL((col)->b) << (cfb)->blueShift))) #define DitheredRGBAColorToBuffer(col, incr, cfb, dest, type) \ ((dest) = (type)(( FTOL((col)->r+(incr)) << (cfb)->redShift) | \ ( FTOL((col)->g+(incr)) << (cfb)->greenShift) | \ ( FTOL((col)->b+(incr)) << (cfb)->blueShift) | \ ( FTOL((col)->a+(incr)) << (cfb)->alphaShift))) #define UnditheredRGBAColorToBuffer(col, cfb, dest, type) \ ((dest) = (type)(( FTOL((col)->r) << (cfb)->redShift) | \ ( FTOL((col)->g) << (cfb)->greenShift) | \ ( FTOL((col)->b) << (cfb)->blueShift) | \ ( FTOL((col)->a) << (cfb)->alphaShift))) #define DitheredColorToBuffer(col, incr, cfb, dest, type) \ if( ALPHA_PIXEL_WRITE( cfb ) ) \ DitheredRGBAColorToBuffer(col, incr, cfb, dest, type); \ else \ DitheredRGBColorToBuffer(col, incr, cfb, dest, type); #define UnditheredColorToBuffer(col, cfb, dest, type) \ if( ALPHA_PIXEL_WRITE( cfb ) ) \ UnditheredRGBAColorToBuffer(col, cfb, dest, type); \ else \ UnditheredRGBColorToBuffer(col, cfb, dest, type); #define StoreColorAsRGB(col, dst) \ (*(dst)++ = (BYTE) FTOL((col)->r), \ *(dst)++ = (BYTE) FTOL((col)->g), \ *(dst)++ = (BYTE) FTOL((col)->b) ) #define StoreColorAsBGR(col, dst) \ (*(dst)++ = (BYTE) FTOL((col)->b), \ *(dst)++ = (BYTE) FTOL((col)->g), \ *(dst)++ = (BYTE) FTOL((col)->r) ) // Macro to read RGBA bitfield span, where alpha component has 3 possibilities: // 1) No alpha buffer, so use constant alpha // 2) Alpha is part of the pixel // 3) Alpha is in the software alpha buffer // Note, currently this is only used for 16 and 32bpp. #define READ_RGBA_BITFIELD_SPAN(src_pix_gen) \ if( !gc->modes.alphaBits ) { \ for( ; w; w--, pResults++ ) \ { \ src_pix_gen; \ pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); \ pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); \ pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); \ pResults->a = cfb->alphaScale; \ } \ } \ else if( ALPHA_IN_PIXEL( cfb ) ) { \ for( ; w; w--, pResults++ ) \ { \ src_pix_gen; \ pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); \ pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); \ pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); \ pResults->a = (__GLfloat) ((pixel & gc->modes.alphaMask) >> cfb->alphaShift); \ } \ } else { \ (*cfb->alphaBuf.readSpan)(&cfb->alphaBuf, x, y, w, pResults); \ for( ; w; w--, pResults++ ) \ { \ src_pix_gen; \ pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); \ pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); \ pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); \ } \ } /* * write all */ STATIC void FASTCALL DIBIndex4Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte result, *puj; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLubyte dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x >> 1)); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND((dst_pix = gengc->pajInvTranslateVector [(x & 1) ? (*puj & 0xf) : (*puj >> 4)])); } else { color = &(frag->color); } DitheredRGBColorToBuffer(color, incr, cfb, result, GLubyte); if (cfb->buf.flags & NEED_FETCH) { if( x & 1 ) { dst_pix = (*puj & 0x0f); } else { dst_pix = (*puj & 0xf0) >> 4; } dst_pix = gengc->pajInvTranslateVector[dst_pix]; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLubyte) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLubyte) ((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } // now put it in result = gengc->pajTranslateVector[result]; if (x & 1) { *puj = (*puj & 0xf0) | result; } else { result <<= 4; *puj = (*puj & 0x0f) | result; } if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } STATIC void FASTCALL DIBIndex8Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte result, *puj; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLubyte dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + x); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND((dst_pix = gengc->pajInvTranslateVector[*puj])); } else { color = &(frag->color); } DitheredRGBColorToBuffer(color, incr, cfb, result, GLubyte); if (cfb->buf.flags & NEED_FETCH) { dst_pix = gengc->pajInvTranslateVector[*puj]; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLubyte) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLubyte) ((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *puj = gengc->pajTranslateVector[result]; if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } // BMF_24BPP in BGR format STATIC void FASTCALL DIBBGRStore(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte *puj; GLuint result; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND(Copy3Bytes(&dst_pix, puj)); } else { color = &(frag->color); } if (cfb->buf.flags & NEED_FETCH) { Copy3Bytes( &dst_pix, puj ); UnditheredRGBColorToBuffer(color, cfb, result, GLuint); if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (result & cfb->sourceMask) | (dst_pix & cfb->destMask); } Copy3Bytes( puj, &result ); } else { StoreColorAsBGR(color, puj); } if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } // BMF_24BPP in RGB format STATIC void FASTCALL DIBRGBAStore(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte *puj; GLuint result; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND(Copy3Bytes(&dst_pix, puj)); } else { color = &(frag->color); } if (cfb->buf.flags & NEED_FETCH) { Copy3Bytes( &dst_pix, puj ); UnditheredRGBColorToBuffer(color, cfb, result, GLuint); if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (result & cfb->sourceMask) | (dst_pix & cfb->destMask); } Copy3Bytes( puj, &result ); } else { StoreColorAsRGB(color, puj); } if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } // BMF_16BPP STATIC void FASTCALL DIBBitfield16Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLushort result, *pus; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLushort dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; pus = (GLushort *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x << 1)); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND((dst_pix = *pus)); } else { color = &(frag->color); } DitheredColorToBuffer(color, incr, cfb, result, GLushort); if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pus; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLushort) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLushort)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *pus = result; if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } // BMF_32BPP store // each component is 8 bits or less // XXX could special case if shifting by 8 or use the 24 bit RGB code STATIC void FASTCALL DIBBitfield32Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLuint result, *pul; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now if ( (cfb->buf.flags & NO_CLIP) || (*gengc->pfnPixelVisible)(x, y) ) { pul = (GLuint *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x << 2)); if( enables & __GL_BLEND_ENABLE ) { SPECIAL_ALPHA_BLEND((dst_pix = *pul)); } else { color = &(frag->color); } UnditheredColorToBuffer(color, cfb, result, GLuint); if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pul; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } } *pul = result; if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } } static GLubyte vubRGBtoVGA[8] = { 0x00, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }; STATIC void FASTCALL DisplayIndex4Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte result, *puj; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLubyte dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; puj = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } DitheredRGBColorToBuffer(color, incr, cfb, result, GLubyte); if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = *puj >> 4; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLubyte) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLubyte)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *puj = vubRGBtoVGA[result]; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } // Put fragment into created DIB and call copybits for one pixel STATIC void FASTCALL DisplayIndex8Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte result, *puj; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLubyte dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; puj = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } DitheredRGBColorToBuffer(color, incr, cfb, result, GLubyte); if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = gengc->pajInvTranslateVector[*puj]; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLubyte) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLubyte)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *puj = gengc->pajTranslateVector[result]; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } STATIC void FASTCALL DisplayBGRStore(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte *puj; GLuint result; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now puj = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = *(GLuint *)puj; UnditheredRGBColorToBuffer(color, cfb, result, GLuint); if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } Copy3Bytes( puj, &result ); } else { StoreColorAsBGR(color, puj); } (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } STATIC void FASTCALL DisplayRGBStore(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLubyte *puj; GLuint result; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now puj = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = *(GLuint *)puj; UnditheredRGBColorToBuffer(color, cfb, result, GLuint); if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } Copy3Bytes( puj, &result ); } else { StoreColorAsRGB(color, puj); } (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } STATIC void FASTCALL DisplayBitfield16Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLushort result, *pus; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; __GLfloat incr; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLushort dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now incr = (enables & __GL_DITHER_ENABLE) ? fDitherIncTable[__GL_DITHER_INDEX(frag->x, frag->y)] : __glHalf; pus = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } DitheredColorToBuffer(color, incr, cfb, result, GLushort); if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = *pus; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLushort) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLushort)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *pus = result; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } STATIC void FASTCALL DisplayBitfield32Store(__GLcolorBuffer *cfb, const __GLfragment *frag) { GLint x, y; GLuint result, *pul; __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint enables = gc->state.enables.general; __GLcolor blendColor; const __GLcolor *color; GLuint dst_pix; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, frag->x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, frag->y) + cfb->buf.yOrigin; // x & y are screen coords now pul = gengc->ColorsBits; if( enables & __GL_BLEND_ENABLE ) { color = &blendColor; (*gc->procs.blend)( gc, cfb, frag, &blendColor ); } else { color = &(frag->color); } UnditheredColorToBuffer(color, cfb, result, GLuint); if (cfb->buf.flags & NEED_FETCH) { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); dst_pix = *pul; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } } *pul = result; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, color); } STATIC void FASTCALL AlphaStore(__GLcolorBuffer *cfb, const __GLfragment *frag) { (*cfb->alphaBuf.store)(&cfb->alphaBuf, frag->x, frag->y, &(frag->color) ); } /******************************Public*Routine******************************\ * Index8StoreSpan * * Copies the current span in the renderer into a bitmap. If bDIB is TRUE, * then the bitmap is the display in DIB format (or a memory DC). If bDIB * is FALSE, then the bitmap is an offscreen scanline buffer and it will be * output to the buffer by (*gengc->pfnCopyPixels)(). * * This handles 8-bit CI mode. Blending and dithering are supported. * * Returns: * GL_FALSE always. Soft code ignores return value. * * History: * 15-Nov-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ //XXX The returnSpan routine follows this routine very closely. Any changes //XXX to this routine should also be reflected in the returnSpan routine STATIC GLboolean FASTCALL Index8StoreSpan( __GLcontext *gc ) { GLint xFrag, yFrag; // current fragment coordinates __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLint xScr, yScr; // current screen (pixel) coordinates GLubyte result, *puj; // current pixel color, current pixel ptr GLubyte *pujEnd; // end of scan line __GLfloat incr; // current dither adj. GLint w; // span width ULONG ulSpanVisibility; // span visibility mode GLint cWalls; GLint *Walls; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLboolean bDIB; GLubyte dst_pix; ASSERT_CHOP_ROUND(); // Get span position and length. w = gc->polygon.shader.length; xFrag = gc->polygon.shader.frag.x; yFrag = gc->polygon.shader.frag.y; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, xFrag) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, yFrag) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; bDIB = flags & DIB_FORMAT; if( !bDIB || (flags & NO_CLIP) ) { // Device managed or unclipped surface ulSpanVisibility = WGL_SPAN_ALL; } else { // Device in BITMAP format ulSpanVisibility = wglSpanVisible(xScr, yScr, w, &cWalls, &Walls); } // Proceed as long as the span is (partially or fully) visible. if (ulSpanVisibility != WGL_SPAN_NONE) { GLboolean bCheckWalls = GL_FALSE; GLboolean bDraw; GLint NextWall; if (ulSpanVisibility == WGL_SPAN_PARTIAL) { bCheckWalls = GL_TRUE; if (cWalls & 0x01) { bDraw = GL_TRUE; } else { bDraw = GL_FALSE; } NextWall = *Walls++; cWalls--; } // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + xScr) : gengc->ColorsBits; pujEnd = puj + w; // Case: no dithering, no masking, no blending // // Check for the common case (which we'll do the fastest). if ( !(enables & (__GL_DITHER_ENABLE)) && !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE ) ) { //!!!XXX -- we can also opt. by unrolling the loops incr = __glHalf; for (; puj < pujEnd; puj++, cp++) { if (bCheckWalls) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; } DitheredRGBColorToBuffer(cp, incr, cfb, result, GLubyte); *puj = gengc->pajTranslateVector[result]; } } // Case: dithering, no masking, no blending // // Dithering is pretty common for 8-bit displays, so its probably // worth special case also. else if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { for (; puj < pujEnd; puj++, cp++, xFrag++) { if (bCheckWalls) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; } incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; DitheredRGBColorToBuffer(cp, incr, cfb, result, GLubyte); *puj = gengc->pajTranslateVector[result]; } } // Case: general // // Otherwise, we'll do it slower. else { // Fetch pixels we will modify: if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE ); // Blend. if (enables & __GL_BLEND_ENABLE) { int i; // this overwrites fragment colors array with blended values SPECIAL_ALPHA_BLEND_SPAN( (dst_pix = gengc->pajInvTranslateVector[*(puj+i)])); } for (; puj < pujEnd; puj++, cp++) { if (bCheckWalls) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; } // Dither. if (enables & __GL_DITHER_ENABLE) { incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; xFrag++; } else { incr = __glHalf; } // Convert the RGB color to color index. DitheredRGBColorToBuffer(cp, incr, cfb, result, GLubyte); // Color mask if (cfb->buf.flags & NEED_FETCH) { dst_pix = gengc->pajInvTranslateVector[*puj]; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLubyte) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if (cfb->buf.flags & COLORMASK_ON) { result = (GLubyte)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *puj = gengc->pajTranslateVector[result]; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); // Note that we ignore walls here for simplicity... if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); } return GL_FALSE; } /******************************Public*Routine******************************\ * Bitfield16StoreSpan * * Copies the current span in the renderer into a bitmap. If bDIB is TRUE, * then the bitmap is the display in DIB format (or a memory DC). If bDIB * is FALSE, then the bitmap is an offscreen scanline buffer and it will be * output to the buffer by (*gengc->pfnCopyPixels)(). * * This handles general 16-bit BITFIELDS mode. Blending is supported. There * is dithering. * * Returns: * GL_FALSE always. Soft code ignores return value. * * History: * 08-Dec-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ //XXX The returnSpan routine follows this routine very closely. Any changes //XXX to this routine should also be reflected in the returnSpan routine STATIC GLboolean FASTCALL Bitfield16StoreSpanPartial(__GLcontext *gc, GLboolean bDIB, GLint cWalls, GLint *Walls ) { GLint xFrag, yFrag; // current fragment coordinates __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLint xScr, yScr; // current screen (pixel) coordinates GLushort result, *pus; // current pixel color, current pixel ptr GLushort *pusEnd; // end of scan line __GLfloat incr; // current dither adj. GLint w; // span width GLboolean bDraw; GLint NextWall; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLushort dst_pix; // Get span position and length. w = gc->polygon.shader.length; xFrag = gc->polygon.shader.frag.x; yFrag = gc->polygon.shader.frag.y; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, xFrag) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, yFrag) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; if (cWalls & 0x01) { bDraw = GL_TRUE; } else { bDraw = GL_FALSE; } NextWall = *Walls++; cWalls--; // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. pus = bDIB ? (GLushort *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<1)) : gengc->ColorsBits; pusEnd = pus + w; // Case: no masking, no dithering, no blending if ( !(enables & (__GL_DITHER_ENABLE)) && !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { incr = __glHalf; for (; pus < pusEnd; pus++, cp++) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; DitheredColorToBuffer(cp, incr, cfb, result, GLushort); *pus = result; } } // Case: dithering, no masking, no blending else if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { for (; pus < pusEnd; pus++, cp++, xFrag++) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; DitheredColorToBuffer(cp, incr, cfb, result, GLushort); *pus = result; } } // All other cases else { if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if ( enables & __GL_BLEND_ENABLE ) { int i; // this overwrites fragment colors array with blended values // XXX is the +i handled properly by the optimizer ? SPECIAL_ALPHA_BLEND_SPAN((dst_pix = *(pus+i))); } for (; pus < pusEnd; pus++, cp++) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; // Dither. if ( enables & __GL_DITHER_ENABLE ) { incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; xFrag++; } else { incr = __glHalf; } // Convert color to 16BPP format. DitheredColorToBuffer(cp, incr, cfb, result, GLushort); // Store result with optional masking. if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pus; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLushort) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if ( cfb->buf.flags & COLORMASK_ON ) { result = (GLushort)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *pus = result; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); return GL_FALSE; } STATIC GLboolean FASTCALL Bitfield16StoreSpan(__GLcontext *gc) { GLint xFrag, yFrag; // current fragment coordinates __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLboolean bDIB; GLint xScr, yScr; // current screen (pixel) coordinates GLushort result, *pus; // current pixel color, current pixel ptr GLushort *pusEnd; // end of scan line __GLfloat incr; // current dither adj. GLint w; // span width GLint cWalls; GLint *Walls; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLushort dst_pix; ASSERT_CHOP_ROUND(); // Get span position and length. w = gc->polygon.shader.length; xFrag = gc->polygon.shader.frag.x; yFrag = gc->polygon.shader.frag.y; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, xFrag) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, yFrag) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; bDIB = flags & DIB_FORMAT; // Check span visibility if( bDIB && !(flags & NO_CLIP) ) { // Device in BITMAP format ULONG ulSpanVisibility; // span visibility mode ulSpanVisibility = wglSpanVisible(xScr, yScr, w, &cWalls, &Walls); if (ulSpanVisibility == WGL_SPAN_NONE) return GL_FALSE; else if (ulSpanVisibility == WGL_SPAN_PARTIAL) return Bitfield16StoreSpanPartial( gc, bDIB, cWalls, Walls ); // else span fully visible } // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. pus = bDIB ? (GLushort *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<1)) : gengc->ColorsBits; pusEnd = pus + w; // Case: no masking, no dithering, no blending if ( !(enables & (__GL_DITHER_ENABLE)) && !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { incr = __glHalf; if( ALPHA_PIXEL_WRITE( cfb ) ) { for (; pus < pusEnd; pus++, cp++) DitheredRGBAColorToBuffer(cp, incr, cfb, *pus, GLushort); } else { for (; pus < pusEnd; pus++, cp++) DitheredRGBColorToBuffer(cp, incr, cfb, *pus, GLushort); } } // Case: dithering, no masking, no blending else if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { if( ALPHA_PIXEL_WRITE( cfb ) ) { for (; pus < pusEnd; pus++, cp++, xFrag++) { incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; DitheredRGBAColorToBuffer(cp, incr, cfb, *pus, GLushort); } } else { for (; pus < pusEnd; pus++, cp++, xFrag++) { incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; DitheredRGBColorToBuffer(cp, incr, cfb, *pus, GLushort); } } } // All other cases else { if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if ( enables & __GL_BLEND_ENABLE ) { int i; // this overwrites fragment colors array with blended values SPECIAL_ALPHA_BLEND_SPAN((dst_pix = *(pus+i))); } for (; pus < pusEnd; pus++, cp++) { // Dither. if ( enables & __GL_DITHER_ENABLE ) { incr = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; xFrag++; } else { incr = __glHalf; } // Convert color to 16BPP format. DitheredColorToBuffer(cp, incr, cfb, result, GLushort); // Store result with optional masking. if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pus; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = (GLushort) (DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask); } if ( cfb->buf.flags & COLORMASK_ON ) { result = (GLushort)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } } *pus = result; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); return GL_FALSE; } /******************************Public*Routine******************************\ * BGRStoreSpan * * Copies the current span in the renderer into a bitmap. If bDIB is TRUE, * then the bitmap is the display in DIB format (or a memory DC). If bDIB * is FALSE, then the bitmap is an offscreen scanline buffer and it will be * output to the buffer by (*gengc->pfnCopyPixels)(). * * This handles GBR 24-bit mode. Blending is supported. There * is no dithering. * * Returns: * GL_FALSE always. Soft code ignores return value. * * History: * 10-Jan-1994 -by- Marc Fortier [v-marcf] * Wrote it. \**************************************************************************/ //XXX The returnSpan routine follows this routine very closely. Any changes //XXX to this routine should also be reflected in the returnSpan routine STATIC GLboolean FASTCALL BGRStoreSpan(__GLcontext *gc ) { __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLint xScr, yScr; // current screen (pixel) coordinates GLubyte *puj; // current pixel ptr GLuint *pul; // current pixel ptr GLuint result; // current pixel color GLubyte *pujEnd; // end of scan line GLint w; // span width ULONG ulSpanVisibility; // span visibility mode GLint cWalls; GLint *Walls; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLboolean bDIB; GLuint dst_pix; ASSERT_CHOP_ROUND(); // Get span position and length. w = gc->polygon.shader.length; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, gc->polygon.shader.frag.x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, gc->polygon.shader.frag.y) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; bDIB = flags & DIB_FORMAT; if( !bDIB || (flags & NO_CLIP) ) { // Device managed or unclipped surface ulSpanVisibility = WGL_SPAN_ALL; } else { // Device in BITMAP format ulSpanVisibility = wglSpanVisible(xScr, yScr, w, &cWalls, &Walls); } // Proceed as long as the span is (partially or fully) visible. if (ulSpanVisibility != WGL_SPAN_NONE) { GLboolean bCheckWalls = GL_FALSE; GLboolean bDraw; GLint NextWall; if (ulSpanVisibility == WGL_SPAN_PARTIAL) { bCheckWalls = GL_TRUE; if (cWalls & 0x01) { bDraw = GL_TRUE; } else { bDraw = GL_FALSE; } NextWall = *Walls++; cWalls--; } // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr*3)) : gengc->ColorsBits; pujEnd = puj + 3*w; // Case: no masking, no blending //!!!XXX -- do extra opt. for RGB and BGR cases //!!!XXX -- we can also opt. by unrolling the loops if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { for (; puj < pujEnd; cp++) { if (bCheckWalls) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) { puj += 3; continue; } } StoreColorAsBGR(cp, puj); } } // All other cases else { if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if (enables & __GL_BLEND_ENABLE) { // this overwrites fragment colors array with blended values (*gc->procs.blendSpan)( gc ); } for (; puj < pujEnd; cp++) { if (bCheckWalls) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) { puj += 3; continue; } } if (cfb->buf.flags & NEED_FETCH) { Copy3Bytes(&dst_pix, puj); UnditheredRGBColorToBuffer(cp, cfb, result, GLuint); if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (result & cfb->sourceMask) | (dst_pix & cfb->destMask); } Copy3Bytes( puj, &result ); puj += 3; } else { StoreColorAsBGR(cp, puj); } } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); } return GL_FALSE; } /******************************Public*Routine******************************\ * Bitfield32StoreSpan * * Copies the current span in the renderer into a bitmap. If bDIB is TRUE, * then the bitmap is the display in DIB format (or a memory DC). If bDIB * is FALSE, then the bitmap is an offscreen scanline buffer and it will be * output to the buffer by (*gengc->pfnCopyPixels)(). * * This handles general 32-bit BITFIELDS mode. Blending is supported. There * is no dithering. * * Returns: * GL_FALSE always. Soft code ignores return value. * * History: * 15-Nov-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ //XXX The returnSpan routine follows this routine very closely. Any changes //XXX to this routine should also be reflected in the returnSpan routine STATIC GLboolean FASTCALL Bitfield32StoreSpanPartial(__GLcontext *gc, GLboolean bDIB, GLint cWalls, GLint *Walls ) { __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLint xScr, yScr; // current screen (pixel) coordinates GLuint result, *pul; // current pixel color, current pixel ptr GLuint *pulEnd; // end of scan line GLint w; // span width GLboolean bDraw; GLint NextWall; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLuint dst_pix; // Get span position and length. w = gc->polygon.shader.length; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, gc->polygon.shader.frag.x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, gc->polygon.shader.frag.y) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; if (cWalls & 0x01) { bDraw = GL_TRUE; } else { bDraw = GL_FALSE; } NextWall = *Walls++; cWalls--; // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. pul = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<2)) : gengc->ColorsBits; pulEnd = pul + w; // Case: no masking, no blending //!!!XXX -- do extra opt. for RGB and BGR cases //!!!XXX -- we can also opt. by unrolling the loops if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { for (; pul < pulEnd; pul++, cp++) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; UnditheredColorToBuffer(cp, cfb, result, GLuint); *pul = result; } } // All other cases else { if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if (enables & __GL_BLEND_ENABLE) { int i; SPECIAL_ALPHA_BLEND_SPAN((dst_pix = *(pul+i))); } for (; pul < pulEnd; pul++, cp++) { if (xScr++ >= NextWall) { if (bDraw) bDraw = GL_FALSE; else bDraw = GL_TRUE; if (cWalls <= 0) { NextWall = gc->constants.maxViewportWidth; } else { NextWall = *Walls++; cWalls--; } } if (bDraw == GL_FALSE) continue; UnditheredColorToBuffer(cp, cfb, result, GLuint); //!!!XXX again, opt. by unrolling loop if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pul; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } } *pul = result; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); return GL_FALSE; } STATIC GLboolean FASTCALL Bitfield32StoreSpan( __GLcontext *gc ) { __GLcolor *cp; // current fragment color __GLcolorBuffer *cfb; // color frame buffer GLboolean bDIB; GLint xScr, yScr; // current screen (pixel) coordinates GLuint result, *pul; // current pixel color, current pixel ptr GLuint *pulEnd; // end of scan line GLint w; // span width ULONG ulSpanVisibility; // span visibility mode GLint cWalls; GLint *Walls; __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLuint flags; GLuint dst_pix; ASSERT_CHOP_ROUND(); // Get span position and length. w = gc->polygon.shader.length; gengc = (__GLGENcontext *)gc; cfb = gc->drawBuffer; xScr = __GL_UNBIAS_X(gc, gc->polygon.shader.frag.x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, gc->polygon.shader.frag.y) + cfb->buf.yOrigin; enables = gc->state.enables.general; flags = cfb->buf.flags; bDIB = flags & DIB_FORMAT; // Check span visibility if( bDIB && !(flags & NO_CLIP) ) { // Device in BITMAP format ULONG ulSpanVisibility; // span visibility mode ulSpanVisibility = wglSpanVisible(xScr, yScr, w, &cWalls, &Walls); if (ulSpanVisibility == WGL_SPAN_NONE) return GL_FALSE; else if (ulSpanVisibility == WGL_SPAN_PARTIAL) return Bitfield32StoreSpanPartial( gc, bDIB, cWalls, Walls ); // else span fully visible } // Get pointers to fragment colors array and frame buffer. cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; // Get pointer to bitmap. pul = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<2)) : gengc->ColorsBits; pulEnd = pul + w; // Case: no masking, no blending //!!!XXX -- do extra opt. for RGB and BGR cases //!!!XXX -- we can also opt. by unrolling the loops if ( !(cfb->buf.flags & NEED_FETCH) && !(enables & __GL_BLEND_ENABLE) ) { if( ALPHA_PIXEL_WRITE( cfb ) ) { for (; pul < pulEnd; pul++, cp++) { UnditheredRGBAColorToBuffer(cp, cfb, result, GLuint); *pul = result; } } else { for (; pul < pulEnd; pul++, cp++) { UnditheredRGBColorToBuffer(cp, cfb, result, GLuint); *pul = result; } } } // All other cases else { if( (!bDIB) && (cfb->buf.flags & NEED_FETCH) ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if (enables & __GL_BLEND_ENABLE) { int i; SPECIAL_ALPHA_BLEND_SPAN((dst_pix = *(pul+i))); } for (; pul < pulEnd; pul++, cp++) { UnditheredColorToBuffer(cp, cfb, result, GLuint); //!!!XXX again, opt. by unrolling loop if (cfb->buf.flags & NEED_FETCH) { dst_pix = *pul; if (enables & __GL_COLOR_LOGIC_OP_ENABLE) { result = DoLogicOp(gc->state.raster.logicOp, result, dst_pix) & gc->modes.allMask; } if (cfb->buf.flags & COLORMASK_ON) { result = (dst_pix & cfb->destMask) | (result & cfb->sourceMask); } } *pul = result; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); return GL_FALSE; } STATIC GLboolean FASTCALL AlphaStoreSpan(__GLcontext *gc) { __GLcolorBuffer *cfb = gc->drawBuffer; ASSERT_CHOP_ROUND(); (*cfb->alphaBuf.storeSpan)( &cfb->alphaBuf ); return GL_FALSE; } STATIC GLboolean FASTCALL StoreMaskedSpan(__GLcontext *gc, GLboolean masked) { #ifdef REWRITE GLint x, y, len; int i; __GLcolor *cp; DWORD *pul; WORD *pus; BYTE *puj; __GLGENcontext *gengc = (__GLGENcontext *)gc; len = gc->polygon.shader.length; x = __GL_UNBIAS_X(gc, gc->polygon.shader.frag.x); y = __GL_UNBIAS_Y(gc, gc->polygon.shader.frag.y); cp = gc->polygon.shader.colors; switch (gengc->iFormatDC) { case BMF_8BPP: break; case BMF_16BPP: pus = gengc->ColorsBits; for (i = 0; i < len; i++) { *pus++ = __GL_COLOR_TO_BMF_16BPP(cp); cp++; } break; case BMF_24BPP: puj = gengc->ColorsBits; for (i = 0; i < len; i++) { *puj++ = (BYTE)cp->b; // XXX check order *puj++ = (BYTE)cp->g; *puj++ = (BYTE)cp->r; cp++; } break; case BMF_32BPP: pul = gengc->ColorsBits; for (i = 0; i < len; i++) { *pul++ = __GL_COLOR_TO_BMF_32BPP(cp); cp++; } break; default: break; } if (masked == GL_TRUE) // XXX mask is BigEndian!!! { unsigned long *pulstipple; unsigned long stip; GLint count; pul = gengc->StippleBits; pulstipple = gc->polygon.shader.stipplePat; count = (len+31)/32; for (i = 0; i < count; i++) { stip = *pulstipple++; *pul++ = (stip&0xff)<<24 | (stip&0xff00)<<8 | (stip&0xff0000)>>8 | (stip&0xff000000)>>24; } wglSpanBlt(CURRENT_DC, gengc->ColorsBitmap, gengc->StippleBitmap, x, y, len); } else { wglSpanBlt(CURRENT_DC, gengc->ColorsBitmap, (HBITMAP)NULL, x, y, len); } #endif return GL_FALSE; } #ifdef TESTSTIPPLE STATIC void FASTCALL MessUpStippledSpan(__GLcontext *gc) { __GLcolor *cp; __GLcolorBuffer *cfb; __GLstippleWord inMask, bit, *sp; GLint count; GLint w; w = gc->polygon.shader.length; sp = gc->polygon.shader.stipplePat; cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; while (w) { count = w; if (count > __GL_STIPPLE_BITS) { count = __GL_STIPPLE_BITS; } w -= count; inMask = *sp++; bit = __GL_STIPPLE_SHIFT(0); while (--count >= 0) { if (!(inMask & bit)) { cp->r = cfb->redMax; cp->g = cfb->greenMax; cp->b = cfb->blueMax; } cp++; #ifdef __GL_STIPPLE_MSB bit >>= 1; #else bit <<= 1; #endif } } } #endif // From the PIXMAP code, calls store for each fragment STATIC GLboolean FASTCALL SlowStoreSpan(__GLcontext *gc) { int x, x1; int i; __GLfragment frag; __GLcolor *cp; __GLcolorBuffer *cfb; GLint w; w = gc->polygon.shader.length; frag.y = gc->polygon.shader.frag.y; x = gc->polygon.shader.frag.x; x1 = gc->polygon.shader.frag.x + w; cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; for (i = x; i < x1; i++) { frag.x = i; frag.color = *cp++; (*cfb->store)(cfb, &frag); } return GL_FALSE; } // From the PIXMAP code, calls store for each fragment with mask test STATIC GLboolean FASTCALL SlowStoreStippledSpan(__GLcontext *gc) { int x; __GLfragment frag; __GLcolor *cp; __GLcolorBuffer *cfb; __GLstippleWord inMask, bit, *sp; GLint count; GLint w; w = gc->polygon.shader.length; sp = gc->polygon.shader.stipplePat; frag.y = gc->polygon.shader.frag.y; x = gc->polygon.shader.frag.x; cp = gc->polygon.shader.colors; cfb = gc->polygon.shader.cfb; while (w) { count = w; if (count > __GL_STIPPLE_BITS) { count = __GL_STIPPLE_BITS; } w -= count; inMask = *sp++; bit = __GL_STIPPLE_SHIFT((__GLstippleWord)0); while (--count >= 0) { if (inMask & bit) { frag.x = x; frag.color = *cp; (*cfb->store)(cfb, &frag); } x++; cp++; #ifdef __GL_STIPPLE_MSB bit >>= 1; #else bit <<= 1; #endif } } return GL_FALSE; } // // Tables to convert 4-bit index to RGB component // These tables assume the VGA fixed palette // History: // 22-NOV-93 Eddie Robinson [v-eddier] Wrote it. // #ifdef __GL_DOUBLE static __GLfloat vfVGAtoR[16] = { 0.0, // black 0.5, // dim red 0.0, // dim green 0.5, // dim yellow 0.0, // dim blue 0.5, // dim magenta 0.0, // dim cyan 0.5, // dim grey 0.75, // medium grey 1.0, // bright red 0.0, // bright green 1.0, // bright yellow 0.0, // bright blue 1.0, // bright magenta 0.0, // bright cyan 1.0 // white }; static __GLfloat vfVGAtoG[16] = { 0.0, // black 0.0, // dim red 0.5, // dim green 0.5, // dim yellow 0.0, // dim blue 0.0, // dim magenta 0.5, // dim cyan 0.5, // dim grey 0.75, // medium grey 0.0, // bright red 1.0, // bright green 1.0, // bright yellow 0.0, // bright blue 0.0, // bright magenta 1.0, // bright cyan 1.0 // white }; static __GLfloat vfVGAtoB[16] = { 0.0, // black 0.0, // dim red 0.0, // dim green 0.0, // dim yellow 0.5, // dim blue 0.5, // dim magenta 0.5, // dim cyan 0.5, // dim grey 0.75, // medium grey 0.0, // bright red 0.0, // bright green 0.0, // bright yellow 1.0, // bright blue 1.0, // bright magenta 1.0, // bright cyan 1.0 // white }; #else static __GLfloat vfVGAtoR[16] = { 0.0F, // black 0.5F, // dim red 0.0F, // dim green 0.5F, // dim yellow 0.0F, // dim blue 0.5F, // dim magenta 0.0F, // dim cyan 0.5F, // dim grey 0.75F, // medium grey 1.0F, // bright red 0.0F, // bright green 1.0F, // bright yellow 0.0F, // bright blue 1.0F, // bright magenta 0.0F, // bright cyan 1.0F // white }; static __GLfloat vfVGAtoG[16] = { 0.0F, // black 0.0F, // dim red 0.5F, // dim green 0.5F, // dim yellow 0.0F, // dim blue 0.0F, // dim magenta 0.5F, // dim cyan 0.5F, // dim grey 0.75F, // medium grey 0.0F, // bright red 1.0F, // bright green 1.0F, // bright yellow 0.0F, // bright blue 0.0F, // bright magenta 1.0F, // bright cyan 1.0F // white }; static __GLfloat vfVGAtoB[16] = { 0.0F, // black 0.0F, // dim red 0.0F, // dim green 0.0F, // dim yellow 0.5F, // dim blue 0.5F, // dim magenta 0.5F, // dim cyan 0.5F, // dim grey 0.75F, // medium grey 0.0F, // bright red 0.0F, // bright green 0.0F, // bright yellow 1.0F, // bright blue 1.0F, // bright magenta 1.0F, // bright cyan 1.0F // white }; #endif void RGBFetchNone(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { result->r = 0.0F; result->g = 0.0F; result->b = 0.0F; if( cfb->buf.gc->modes.alphaBits ) result->a = 0.0F; else result->a = cfb->alphaScale; } void RGBReadSpanNone(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *results, GLint w) { GLint i; __GLcolor *pResults; __GLfloat alphaVal; if( cfb->buf.gc->modes.alphaBits ) alphaVal = 0.0F; else alphaVal = cfb->alphaScale; for (i = 0, pResults = results; i < w; i++, pResults++) { pResults->r = 0.0F; pResults->g = 0.0F; pResults->b = 0.0F; pResults->a = alphaVal; } } void DIBIndex4RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; // Do alpha first, before x,y unbiased if( gc->modes.alphaBits ) { (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } else result->a = cfb->alphaScale; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x >> 1)); pixel = *puj; if (!(x & 1)) pixel >>= 4; pixel = gengc->pajInvTranslateVector[pixel&0xf]; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); } void DIBIndex8RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + x); pixel = gengc->pajInvTranslateVector[*puj]; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DIBIndex8RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + x); pixel = gengc->pajInvTranslateVector[*puj]; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); } void DIBBGRFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); result->b = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->r = (__GLfloat) *puj; result->a = cfb->alphaScale; } void DIBBGRAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); result->b = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->r = (__GLfloat) *puj; } void DIBRGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); result->r = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->b = (__GLfloat) *puj; result->a = cfb->alphaScale; } void DIBRGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x * 3)); result->r = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->b = (__GLfloat) *puj; } void DIBBitfield16RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLushort *pus, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; pus = (GLushort *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x << 1)); pixel = *pus; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DIBBitfield16RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLushort *pus, pixel; GLint xScr, yScr; // current screen (pixel) coordinates gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; pus = (GLushort *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr << 1)); pixel = *pus; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); if( ALPHA_IN_PIXEL( cfb ) ) result->a = (__GLfloat) ((pixel & gc->modes.alphaMask) >> cfb->alphaShift); else (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } void DIBBitfield32RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint *pul, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; pul = (GLuint *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x << 2)); pixel = *pul; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DIBBitfield32RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint *pul, pixel; GLint xScr, yScr; gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; pul = (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr << 2)); pixel = *pul; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); if( ALPHA_IN_PIXEL( cfb ) ) result->a = (__GLfloat) ((pixel & gc->modes.alphaMask) >> cfb->alphaShift); else (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } void DisplayIndex4RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; if( gc->modes.alphaBits ) { (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } else result->a = cfb->alphaScale; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; pixel = *puj >> 4; result->r = vfVGAtoR[pixel]; result->g = vfVGAtoG[pixel]; result->b = vfVGAtoB[pixel]; } void DisplayIndex8RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; pixel = gengc->pajInvTranslateVector[*puj]; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DisplayIndex8RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; pixel = gengc->pajInvTranslateVector[*puj]; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); } void DisplayBGRFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; result->b = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->r = (__GLfloat) *puj; result->a = cfb->alphaScale; } void DisplayBGRAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; result->b = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->r = (__GLfloat) *puj; } void DisplayRGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; result->r = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->b = (__GLfloat) *puj; result->a = cfb->alphaScale; } void DisplayRGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); puj = gengc->ColorsBits; result->r = (__GLfloat) *puj++; result->g = (__GLfloat) *puj++; result->b = (__GLfloat) *puj; } void DisplayBitfield16RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLushort *pus, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); pus = gengc->ColorsBits; pixel = *pus; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DisplayBitfield16RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLushort *pus, pixel; GLint xScr, yScr; // current screen (pixel) coordinates gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); pus = gengc->ColorsBits; pixel = *pus; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); if( ALPHA_IN_PIXEL( cfb ) ) result->a = (__GLfloat) ((pixel & gc->modes.alphaMask) >> cfb->alphaShift); else (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } void DisplayBitfield32RGBFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint *pul, pixel; gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, 1, FALSE); pul = gengc->ColorsBits; pixel = *pul; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); result->a = cfb->alphaScale; } void DisplayBitfield32RGBAFetch(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *result) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint *pul, pixel; GLint xScr, yScr; gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, 1, FALSE); pul = gengc->ColorsBits; pixel = *pul; result->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); result->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); result->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); if( ALPHA_IN_PIXEL( cfb ) ) result->a = (__GLfloat) ((pixel & gc->modes.alphaMask) >> cfb->alphaShift); else (*cfb->alphaBuf.fetch)(&cfb->alphaBuf, x, y, result); } static void ReadAlphaSpan( __GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; if( gc->modes.alphaBits ) (*cfb->alphaBuf.readSpan)(&cfb->alphaBuf, x, y, w, pResults); else { for( ; w ; w--, pResults++ ) pResults->a = cfb->alphaScale; } } void DIBIndex4RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *results, GLint w) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; __GLcolor *pResults; ReadAlphaSpan( cfb, x, y, results, w ); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + (x >> 1)); pResults = results; if (x & 1) { pixel = *puj++; pixel = gengc->pajInvTranslateVector[pixel & 0xf]; pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); pResults++; w--; } while (w > 1) { pixel = *puj >> 4; pixel = gengc->pajInvTranslateVector[pixel]; pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); pResults++; pixel = *puj++; pixel = gengc->pajInvTranslateVector[pixel & 0xf]; pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); pResults++; w -= 2; } if (w > 0) { pixel = *puj >> 4; pixel = gengc->pajInvTranslateVector[pixel]; pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); } } void DisplayIndex4RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *results, GLint w) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; __GLcolor *pResults; ReadAlphaSpan( cfb, x, y, results, w ); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; (*gengc->pfnCopyPixels)(gengc, cfb, x, y, w, FALSE); puj = gengc->ColorsBits; pResults = results; while (w > 1) { pixel = *puj >> 4; pResults->r = vfVGAtoR[pixel]; pResults->g = vfVGAtoG[pixel]; pResults->b = vfVGAtoB[pixel]; pResults++; pixel = *puj++ & 0xf; pResults->r = vfVGAtoR[pixel]; pResults->g = vfVGAtoG[pixel]; pResults->b = vfVGAtoB[pixel]; pResults++; w -= 2; } if (w > 0) { pixel = *puj >> 4; pResults->r = vfVGAtoR[pixel]; pResults->g = vfVGAtoG[pixel]; pResults->b = vfVGAtoB[pixel]; } } void Index8RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj, pixel; ReadAlphaSpan( cfb, x, y, pResults, w ); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; if( cfb->buf.flags & DIB_FORMAT ) { puj = (GLubyte *)((ULONG_PTR)cfb->buf.base + (y*cfb->buf.outerWidth) + x); } else { (*gengc->pfnCopyPixels)(gengc, cfb, x, y, w, FALSE); puj = gengc->ColorsBits; } for ( ; w; w--, pResults++) { pixel = gengc->pajInvTranslateVector[*puj++]; pResults->r = (__GLfloat) ((pixel & gc->modes.redMask) >> cfb->redShift); pResults->g = (__GLfloat) ((pixel & gc->modes.greenMask) >> cfb->greenShift); pResults->b = (__GLfloat) ((pixel & gc->modes.blueMask) >> cfb->blueShift); } } void BGRAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; ReadAlphaSpan( cfb, x, y, pResults, w ); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; if( cfb->buf.flags & DIB_FORMAT ) { 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 ( ; w; w--, pResults++) { pResults->b = (__GLfloat) *puj++; pResults->g = (__GLfloat) *puj++; pResults->r = (__GLfloat) *puj++; } } void RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLubyte *puj; ReadAlphaSpan( cfb, x, y, pResults, w ); gengc = (__GLGENcontext *)gc; x = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; y = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; if( cfb->buf.flags & DIB_FORMAT ) { 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 ( ; w; w--, pResults++) { pResults->r = (__GLfloat) *puj++; pResults->g = (__GLfloat) *puj++; pResults->b = (__GLfloat) *puj++; } } void Bitfield16RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLushort *pus, pixel; GLint xScr, yScr; gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; if( cfb->buf.flags & DIB_FORMAT ) { pus = (GLushort *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr << 1)); } else { (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); pus = gengc->ColorsBits; } READ_RGBA_BITFIELD_SPAN( (pixel = *pus++) ); } void Bitfield32RGBAReadSpan(__GLcolorBuffer *cfb, GLint x, GLint y, __GLcolor *pResults, GLint w ) { __GLcontext *gc = cfb->buf.gc; __GLGENcontext *gengc; GLuint *pul, pixel; GLint xScr, yScr; gengc = (__GLGENcontext *)gc; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; if( cfb->buf.flags & DIB_FORMAT ) { pul = (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr << 2)); } else { (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); pul = gengc->ColorsBits; } READ_RGBA_BITFIELD_SPAN( (pixel = *pul++) ); } /************************************************************************/ // Used in accumulation // Accumulation helper macros and functions // Clamp a color component between 0 and max #define ACCUM_CLAMP_COLOR_COMPONENT( col, max ) \ if ((col) < (__GLfloat) 0.0) \ (col) = (__GLfloat) 0.0; \ else if ((col) > max ) \ (col) = max; // Extract an accumulation buffer color component by shifting and masking, then // multiply it by scale (Requires ap and icol defined). #define ACCUM_SCALE_SIGNED_COLOR_COMPONENT( col, shift, sign, mask, scale ) \ icol = (*ap >> shift) & mask; \ if (icol & sign) \ icol |= ~mask; \ (col) = (icol * scale); // Fetch and scale a span of rgba values from a 32-bit accumulation buffer void GetClampedRGBAccum32Values( __GLcolorBuffer *cfb, GLuint *pac, __GLcolor *cDest, GLint width, __GLfloat scale ) { GLint w, i; GLint icol; __GLfloat rval, gval, bval, aval; __GLuicolor *shift, *mask, *sign; GLuint *ap; __GLcolor *cp; __GLcontext *gc = cfb->buf.gc; __GLaccumBuffer *afb = &gc->accumBuffer; rval = scale * afb->oneOverRedScale; gval = scale * afb->oneOverGreenScale; bval = scale * afb->oneOverBlueScale; shift = &afb->shift; mask = &afb->mask; sign = &afb->sign; for ( w = width, cp = cDest, ap = pac; w; w--, cp++, ap++ ) { ACCUM_SCALE_SIGNED_COLOR_COMPONENT( cp->r, shift->r, sign->r, mask->r, rval ); ACCUM_CLAMP_COLOR_COMPONENT( cp->r, cfb->redScale ); ACCUM_SCALE_SIGNED_COLOR_COMPONENT( cp->g, shift->g, sign->g, mask->g, gval ); ACCUM_CLAMP_COLOR_COMPONENT( cp->g, cfb->greenScale ); ACCUM_SCALE_SIGNED_COLOR_COMPONENT( cp->b, shift->b, sign->b, mask->b, bval ); ACCUM_CLAMP_COLOR_COMPONENT( cp->b, cfb->blueScale ); } if( ! ALPHA_WRITE_ENABLED( cfb ) ) return; aval = scale * afb->oneOverAlphaScale; for ( w = width, cp = cDest, ap = pac; w; w--, cp++, ap++ ) { ACCUM_SCALE_SIGNED_COLOR_COMPONENT( cp->a, shift->a, sign->a, mask->a, aval ); ACCUM_CLAMP_COLOR_COMPONENT( cp->a, cfb->alphaScale ); } } // Fetch and scale a span of rgba values from a 64-bit accumulation buffer void GetClampedRGBAccum64Values( __GLcolorBuffer *cfb, GLshort *pac, __GLcolor *cDest, GLint width, __GLfloat scale ) { GLint w; __GLcontext *gc = cfb->buf.gc; __GLaccumBuffer *afb = &gc->accumBuffer; __GLfloat rval, gval, bval, aval; __GLcolor *cp; GLshort *ap; rval = scale * afb->oneOverRedScale; gval = scale * afb->oneOverGreenScale; bval = scale * afb->oneOverBlueScale; for ( w = width, cp = cDest, ap = pac; w; w--, cp++, ap+=4 ) { cp->r = (ap[0] * rval); ACCUM_CLAMP_COLOR_COMPONENT( cp->r, cfb->redScale ); cp->g = (ap[1] * gval); ACCUM_CLAMP_COLOR_COMPONENT( cp->g, cfb->greenScale ); cp->b = (ap[2] * bval); ACCUM_CLAMP_COLOR_COMPONENT( cp->b, cfb->blueScale ); } if( ! ALPHA_WRITE_ENABLED( cfb ) ) return; aval = scale * afb->oneOverAlphaScale; // Offset the accumulation pointer to the alpha value: ap = pac + 3; for ( w = width, cp = cDest; w; w--, cp++, ap+=4 ) { cp->a = (*ap * rval); ACCUM_CLAMP_COLOR_COMPONENT( cp->a, cfb->alphaScale ); } } /******************************Public*Routine******************************\ * Index4ReturnSpan * Reads from a 16-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * Since accumulation of 4-bit RGB isn't very useful, this routine is very * general and calls through the store function pointers. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void Index4ReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w) { __GLcontext *gc = cfb->buf.gc; GLuint *ap; // current accum entry __GLGENcontext *gengc; // generic graphics context GLuint saveEnables; // modes enabled in graphics context __GLaccumBuffer *afb; __GLfragment frag; __GLcolor *pAccumCol, *pac; afb = &gc->accumBuffer; ap = (GLuint *)ac; saveEnables = gc->state.enables.general; // save current enables gc->state.enables.general &= ~__GL_BLEND_ENABLE; // disable blend for store procs frag.x = x; frag.y = y; // Pre-fetch/clamp/scale the accum buffer values afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum32Values( cfb, ap, pAccumCol, w, scale ); for( pac = pAccumCol ; w; w--, pac++ ) { frag.color = *pac; (*cfb->store)(cfb, &frag); frag.x++; } gc->state.enables.general = saveEnables; // restore current enables } /******************************Public*Routine******************************\ * Index8ReturnSpan * Reads from a 32-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void Index8ReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w ) { __GLcontext *gc = cfb->buf.gc; GLuint *ap; // current accum entry GLint xFrag, yFrag; // current window (pixel) coordinates GLint xScr, yScr; // current screen (pixel) coordinates GLubyte result, *puj; // current pixel color, current pixel ptr GLubyte *pujEnd; // end of scan line __GLfloat inc; // current dither adj. __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLboolean bDIB; __GLaccumBuffer *afb; GLubyte dst_pix; __GLcolor *pAccumCol, *pac; ASSERT_CHOP_ROUND(); gengc = (__GLGENcontext *)gc; ap = (GLuint *)ac; xFrag = x; yFrag = y; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; enables = gc->state.enables.general; bDIB = cfb->buf.flags & DIB_FORMAT; // Use to call wglSpanVisible, if window level security is added reimplement // Get pointer to bitmap. puj = bDIB ? (GLubyte *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + xScr) : gengc->ColorsBits; pujEnd = puj + w; afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum32Values( cfb, ap, pAccumCol, w, scale ); pac = pAccumCol; // Case: no dithering, no masking // // Check for the common case (which we'll do the fastest). if ( !(enables & (__GL_DITHER_ENABLE)) && !(cfb->buf.flags & COLORMASK_ON) ) { //!!!XXX -- we can also opt. by unrolling the loops for ( ; puj < pujEnd; puj++, pac++ ) { result = ((BYTE) FTOL(pac->r + __glHalf) << cfb->redShift) | ((BYTE) FTOL(pac->g + __glHalf) << cfb->greenShift) | ((BYTE) FTOL(pac->b + __glHalf) << cfb->blueShift); *puj = gengc->pajTranslateVector[result]; } } // Case: dithering, no masking, no blending // // Dithering is pretty common for 8-bit displays, so its probably // worth special case also. else if ( !(cfb->buf.flags & COLORMASK_ON) ) { for ( ; puj < pujEnd; puj++, pac++, xFrag++) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; result = ((BYTE) FTOL(pac->r + inc) << cfb->redShift) | ((BYTE) FTOL(pac->g + inc) << cfb->greenShift) | ((BYTE) FTOL(pac->b + inc) << cfb->blueShift); *puj = gengc->pajTranslateVector[result]; } } // Case: general // // Otherwise, we'll do it slower. else { // Color mask pre-fetch if ((cfb->buf.flags & COLORMASK_ON) && !bDIB) { (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE ); } for ( ; puj < pujEnd; puj++, pac++ ) { if (enables & __GL_DITHER_ENABLE) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; xFrag++; } else { inc = __glHalf; } result = ((BYTE)FTOL(pac->r + inc) << cfb->redShift) | ((BYTE)FTOL(pac->g + inc) << cfb->greenShift) | ((BYTE)FTOL(pac->b + inc) << cfb->blueShift); // Color mask if (cfb->buf.flags & COLORMASK_ON) { dst_pix = gengc->pajInvTranslateVector[*puj]; result = (GLubyte)((dst_pix & cfb->destMask) | (result & cfb->sourceMask)); } *puj = gengc->pajTranslateVector[result]; } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); // Store alpha values if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.storeSpan2)( &cfb->alphaBuf, x, y, w, pAccumCol ); } /******************************Public*Routine******************************\ * RGBReturnSpan * Reads from a 64-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void RGBReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w ) { __GLcontext *gc = cfb->buf.gc; GLshort *ap; // current accum entry GLint xScr, yScr; // current screen (pixel) coordinates GLubyte *puj; // current pixel color, current pixel ptr GLubyte *pujEnd; // end of scan line __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLboolean bDIB; __GLaccumBuffer *afb; __GLcolor *pAccumCol, *pac; ASSERT_CHOP_ROUND(); afb = &gc->accumBuffer; gengc = (__GLGENcontext *)gc; ap = (GLshort *)ac; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; enables = gc->state.enables.general; bDIB = cfb->buf.flags & DIB_FORMAT; // Use to call wglSpanVisible, if window level security is added reimplement // Get pointer to bitmap. puj = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr*3)) : gengc->ColorsBits; pujEnd = puj + w*3; // Pre-fetch/clamp/scale the accum buffer values afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum64Values( cfb, ap, pAccumCol, w, scale ); pac = pAccumCol; // Case: no masking if ( !(cfb->buf.flags & COLORMASK_ON) ) { for ( ; puj < pujEnd; puj += 3, pac ++ ) { puj[0] = (GLubyte) FTOL(pac->r); puj[1] = (GLubyte) FTOL(pac->g); puj[2] = (GLubyte) FTOL(pac->b); } } // All other cases else { GLboolean bRedMask, bGreenMask, bBlueMask; GLubyte *pujStart = puj; // Color mask pre-fetch if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if( gc->state.raster.rMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->r); } pujStart++; pujEnd++; if( gc->state.raster.gMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->g); } pujStart++; pujEnd++; if( gc->state.raster.bMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->b); } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); // Store alpha values if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.storeSpan2)( &cfb->alphaBuf, x, y, w, pAccumCol ); } /******************************Public*Routine******************************\ * BGRReturnSpan * Reads from a 64-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void BGRReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w ) { __GLcontext *gc = cfb->buf.gc; GLshort *ap; // current accum entry __GLcolor *pAccumCol, *pac; GLint xScr, yScr; // current screen (pixel) coordinates GLubyte *puj; // current pixel color, current pixel ptr GLubyte *pujEnd; // end of scan line __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLboolean bDIB; __GLfloat r, g, b; __GLfloat rval, gval, bval; __GLaccumBuffer *afb; ASSERT_CHOP_ROUND(); afb = &gc->accumBuffer; rval = scale * afb->oneOverRedScale; gval = scale * afb->oneOverGreenScale; bval = scale * afb->oneOverBlueScale; gengc = (__GLGENcontext *)gc; ap = (GLshort *)ac; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; enables = gc->state.enables.general; bDIB = cfb->buf.flags & DIB_FORMAT; // Use to call wglSpanVisible, if window level security is added reimplement // Get pointer to bitmap. puj = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr*3)) : gengc->ColorsBits; pujEnd = puj + w*3; // Pre-fetch/clamp/scale the accum buffer values afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum64Values( cfb, ap, pAccumCol, w, scale ); pac = pAccumCol; // Case: no masking if ( !(cfb->buf.flags & COLORMASK_ON) ) { for ( ; puj < pujEnd; puj += 3, pac ++ ) { puj[0] = (GLubyte) FTOL(pac->b); puj[1] = (GLubyte) FTOL(pac->g); puj[2] = (GLubyte) FTOL(pac->r); } } // All other cases else { GLboolean bRedMask, bGreenMask, bBlueMask; GLubyte *pujStart = puj; // Color mask pre-fetch if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); if( gc->state.raster.bMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->b); } pujStart++; pujEnd++; if( gc->state.raster.gMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->g); } pujStart++; pujEnd++; if( gc->state.raster.rMask ) { for ( puj = pujStart, pac = pAccumCol; puj < pujEnd; puj += 3, pac++ ) *puj = (GLubyte) FTOL(pac->r); } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); // Store alpha values if( ALPHA_WRITE_ENABLED( cfb ) ) (*cfb->alphaBuf.storeSpan2)( &cfb->alphaBuf, x, y, w, pAccumCol ); } /******************************Public*Routine******************************\ * Bitfield16ReturnSpan * Reads from a 32-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void Bitfield16ReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w ) { __GLcontext *gc = cfb->buf.gc; GLuint *ap; // current accum entry GLint xFrag, yFrag; // current fragment coordinates GLint xScr, yScr; // current screen (pixel) coordinates GLushort result, *pus; // current pixel color, current pixel ptr GLushort *pusEnd; // end of scan line __GLfloat inc; // current dither adj. __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLboolean bDIB; __GLcolor *pAccumCol, *pac; __GLaccumBuffer *afb; ASSERT_CHOP_ROUND(); afb = &gc->accumBuffer; gengc = (__GLGENcontext *)gc; ap = (GLuint *)ac; xFrag = x; yFrag = y; xScr = __GL_UNBIAS_X(gc, xFrag) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, yFrag) + cfb->buf.yOrigin; enables = gc->state.enables.general; bDIB = cfb->buf.flags & DIB_FORMAT; // Use to call wglSpanVisible, if window level security is added reimplement // Get pointer to bitmap. pus = bDIB ? (GLushort *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<1)) : gengc->ColorsBits; pusEnd = pus + w; // Pre-fetch/clamp/scale the accum buffer values afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum32Values( cfb, ap, pAccumCol, w, scale ); pac = pAccumCol; // Case: no masking, no dithering if ( !(enables & (__GL_DITHER_ENABLE)) && !(cfb->buf.flags & COLORMASK_ON) ) { if( ALPHA_PIXEL_WRITE( cfb ) ) { for ( ; pus < pusEnd; pus++, pac++ ) { *pus = ((BYTE) FTOL(pac->r + __glHalf) << cfb->redShift) | ((BYTE) FTOL(pac->g + __glHalf) << cfb->greenShift) | ((BYTE) FTOL(pac->b + __glHalf) << cfb->blueShift) | ((BYTE) FTOL(pac->a + __glHalf) << cfb->alphaShift); } } else { for ( ; pus < pusEnd; pus++, pac++ ) { *pus = ((BYTE) FTOL(pac->r + __glHalf) << cfb->redShift) | ((BYTE) FTOL(pac->g + __glHalf) << cfb->greenShift) | ((BYTE) FTOL(pac->b + __glHalf) << cfb->blueShift); } } } // Case: dithering, no masking else if ( !(cfb->buf.flags & COLORMASK_ON) ) { if( ALPHA_PIXEL_WRITE( cfb ) ) { for ( ; pus < pusEnd; pus++, pac++, xFrag++ ) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; *pus = ((BYTE) FTOL(pac->r + inc) << cfb->redShift) | ((BYTE) FTOL(pac->g + inc) << cfb->greenShift) | ((BYTE) FTOL(pac->b + inc) << cfb->blueShift) | ((BYTE) FTOL(pac->a + inc) << cfb->alphaShift); } } else { for ( ; pus < pusEnd; pus++, pac++, xFrag++ ) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; *pus = ((BYTE) FTOL(pac->r + inc) << cfb->redShift) | ((BYTE) FTOL(pac->g + inc) << cfb->greenShift) | ((BYTE) FTOL(pac->b + inc) << cfb->blueShift); } } } // All other cases else { // Color mask pre-fetch if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); for ( ; pus < pusEnd; pus++, pac++ ) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; // Dither. if ( enables & __GL_DITHER_ENABLE ) { inc = fDitherIncTable[__GL_DITHER_INDEX(xFrag, yFrag)]; xFrag++; } else { inc = __glHalf; } // Convert color to 16BPP format. result = ((BYTE) FTOL(pac->r + inc) << cfb->redShift) | ((BYTE) FTOL(pac->g + inc) << cfb->greenShift) | ((BYTE) FTOL(pac->b + inc) << cfb->blueShift); if( ALPHA_PIXEL_WRITE( cfb ) ) result |= ((BYTE) FTOL(pac->a + inc) << cfb->alphaShift); // Store result with optional masking. *pus = (GLushort)((*pus & cfb->destMask) | (result & cfb->sourceMask)); } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan2)( &cfb->alphaBuf, x, y, w, pAccumCol ); } /******************************Public*Routine******************************\ * Bitfield32ReturnSpan * Reads from a 64-bit accumulation buffer and writes the span to a device or * a DIB. Only dithering and color mask are applied. Blend is ignored. * * History: * 10-DEC-93 Eddie Robinson [v-eddier] Wrote it. \**************************************************************************/ //XXX This routine follows the store span routine very closely. Any changes //XXX to the store span routine should also be reflected here void Bitfield32ReturnSpan(__GLcolorBuffer *cfb, GLint x, GLint y, const __GLaccumCell *ac, __GLfloat scale, GLint w ) { __GLcontext *gc = cfb->buf.gc; GLshort *ap; // current accum entry GLint xScr, yScr; // current screen (pixel) coordinates GLuint result, *pul; // current pixel color, current pixel ptr GLuint *pulEnd; // end of scan line __GLGENcontext *gengc; // generic graphics context GLuint enables; // modes enabled in graphics context GLboolean bDIB; __GLfloat r, g, b; __GLfloat rval, gval, bval; __GLaccumBuffer *afb; __GLcolor *pAccumCol, *pac; ASSERT_CHOP_ROUND(); afb = &gc->accumBuffer; rval = scale * afb->oneOverRedScale; gval = scale * afb->oneOverGreenScale; bval = scale * afb->oneOverBlueScale; gengc = (__GLGENcontext *)gc; ap = (GLshort *)ac; xScr = __GL_UNBIAS_X(gc, x) + cfb->buf.xOrigin; yScr = __GL_UNBIAS_Y(gc, y) + cfb->buf.yOrigin; enables = gc->state.enables.general; bDIB = cfb->buf.flags & DIB_FORMAT; // Use to call wglSpanVisible, if window level security is added reimplement // Get pointer to bitmap. pul = bDIB ? (GLuint *)((ULONG_PTR)cfb->buf.base + (yScr*cfb->buf.outerWidth) + (xScr<<2)) : gengc->ColorsBits; pulEnd = pul + w; // Pre-fetch/clamp/scale the accum buffer values afb = &gc->accumBuffer; pAccumCol = afb->colors; GetClampedRGBAccum64Values( cfb, ap, pAccumCol, w, scale ); pac = pAccumCol; // Case: no masking if ( !(cfb->buf.flags & COLORMASK_ON) ) { if( ALPHA_PIXEL_WRITE( cfb ) ) { for ( ; pul < pulEnd; pul++, pac++ ) { *pul = ((BYTE) FTOL(pac->r) << cfb->redShift) | ((BYTE) FTOL(pac->g) << cfb->greenShift) | ((BYTE) FTOL(pac->b) << cfb->blueShift) | ((BYTE) FTOL(pac->a) << cfb->alphaShift); } } else { for ( ; pul < pulEnd; pul++, pac++ ) { *pul = ((BYTE) FTOL(pac->r) << cfb->redShift) | ((BYTE) FTOL(pac->g) << cfb->greenShift) | ((BYTE) FTOL(pac->b) << cfb->blueShift); } } } // All other cases else { // Color mask pre-fetch if( !bDIB ) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, FALSE); for ( ; pul < pulEnd; pul++, pac++ ) { result = ((BYTE) FTOL(pac->r) << cfb->redShift) | ((BYTE) FTOL(pac->g) << cfb->greenShift) | ((BYTE) FTOL(pac->b) << cfb->blueShift); if( ALPHA_PIXEL_WRITE( cfb ) ) result |= ((BYTE) FTOL(pac->a) << cfb->alphaShift); //!!!XXX again, opt. by unrolling loop *pul = (*pul & cfb->destMask) | (result & cfb->sourceMask); } } // Output the offscreen scanline buffer to the device. The function // (*gengc->pfnCopyPixels) should handle clipping. if (!bDIB) (*gengc->pfnCopyPixels)(gengc, cfb, xScr, yScr, w, TRUE); if( ALPHA_BUFFER_WRITE( cfb ) ) (*cfb->alphaBuf.storeSpan2)( &cfb->alphaBuf, x, y, w, pAccumCol ); } STATIC void __glSetDrawBuffer(__GLcolorBuffer *cfb) { DBGENTRY("__glSetDrawBuffer\n"); } STATIC void setReadBuffer(__GLcolorBuffer *cfb) { DBGENTRY("setReadBuffer\n"); } /************************************************************************/ STATIC void Resize(__GLGENbuffers *buffers, __GLcolorBuffer *cfb, GLint w, GLint h) { DBGENTRY("Resize\n"); cfb->buf.width = w; cfb->buf.height = h; } #define DBG_PICK LEVEL_ENTRY // Called at each validate (lots of times, whenever states change) STATIC void FASTCALL PickRGB(__GLcontext *gc, __GLcolorBuffer *cfb) { __GLGENcontext *gengc; GLuint totalMask, sourceMask; GLboolean colormask; PIXELFORMATDESCRIPTOR *pfmt; GLuint enables = gc->state.enables.general; sourceMask = 0; colormask = GL_FALSE; if (gc->state.raster.rMask) { sourceMask |= gc->modes.redMask; } if (gc->state.raster.gMask) { sourceMask |= gc->modes.greenMask; } if (gc->state.raster.bMask) { sourceMask |= gc->modes.blueMask; } totalMask = gc->modes.redMask | gc->modes.greenMask | gc->modes.blueMask; gengc = (__GLGENcontext *)gc; // If we have alpha bits, need to determine where they belong : for a // generic pixel format, they live in the software alpha buffer, but for // an mcd type context they will be on the mcd device (or ALPHA_IN_PIXEL ). // This is used by all the 'slow' store/fetch procs. if( gc->modes.alphaBits && gengc->pMcdState ) { // Set bit in buf.flags indicating alpha is in the pixel cfb->buf.flags = cfb->buf.flags | ALPHA_IN_PIXEL_BIT; } else { // Alpha is not in the pixel, or there is no alpha cfb->buf.flags = cfb->buf.flags & ~ALPHA_IN_PIXEL_BIT; } if( ALPHA_IN_PIXEL( cfb ) ) { // There are alpha bits in the pixels, so need to include alpha in mask if (gc->state.raster.aMask) { sourceMask |= gc->modes.alphaMask; } totalMask |= gc->modes.alphaMask; } if (sourceMask == totalMask) { cfb->buf.flags = cfb->buf.flags & ~COLORMASK_ON; } else { cfb->buf.flags = cfb->buf.flags | COLORMASK_ON; } cfb->sourceMask = sourceMask; cfb->destMask = totalMask & ~sourceMask; // Determine whether writing alpha values is required if( gc->modes.alphaBits && gc->state.raster.aMask ) cfb->buf.flags = cfb->buf.flags | ALPHA_ON; else cfb->buf.flags = cfb->buf.flags & ~ALPHA_ON; // If we're doing a logic op or there is a color mask we'll need // to fetch the destination value before we write if ((enables & __GL_COLOR_LOGIC_OP_ENABLE) || (cfb->buf.flags & COLORMASK_ON)) { cfb->buf.flags = cfb->buf.flags | NEED_FETCH; } else cfb->buf.flags = cfb->buf.flags & ~NEED_FETCH; // Figure out store routines if (gc->state.raster.drawBuffer == GL_NONE) { cfb->store = Store_NOT; cfb->fetch = RGBFetchNone; cfb->readSpan = RGBReadSpanNone; cfb->storeSpan = StoreSpanNone; cfb->storeStippledSpan = StoreSpanNone; } else { pfmt = &gengc->gsurf.pfd; // Pick functions that work for both DIB and Display formats switch(pfmt->cColorBits) { case 4: cfb->clear = Index4Clear; cfb->returnSpan = Index4ReturnSpan; break; case 8: cfb->storeSpan = Index8StoreSpan; cfb->readSpan = Index8RGBAReadSpan; cfb->returnSpan = Index8ReturnSpan; cfb->clear = Index8Clear; break; case 16: cfb->storeSpan = Bitfield16StoreSpan; cfb->readSpan = Bitfield16RGBAReadSpan; cfb->returnSpan = Bitfield16ReturnSpan; cfb->clear = Bitfield16Clear; break; case 24: if (cfb->redShift == 16) { cfb->storeSpan = BGRStoreSpan; cfb->readSpan = BGRAReadSpan; cfb->returnSpan = BGRReturnSpan; } else { // XXX why no RGBStoreSpan ? cfb->readSpan = RGBAReadSpan; cfb->returnSpan = RGBReturnSpan; } cfb->clear = RGBClear; break; case 32: cfb->storeSpan = Bitfield32StoreSpan; cfb->readSpan = Bitfield32RGBAReadSpan; cfb->returnSpan = Bitfield32ReturnSpan; cfb->clear = Bitfield32Clear; break; } // Pick specific functions for DIB or Display formats if (cfb->buf.flags & DIB_FORMAT) { switch(pfmt->cColorBits) { case 4: DBGLEVEL(DBG_PICK, "DIBIndex4Store\n"); cfb->store = DIBIndex4Store; cfb->fetch = DIBIndex4RGBAFetch; cfb->readSpan = DIBIndex4RGBAReadSpan; break; case 8: DBGLEVEL(DBG_PICK, "DIBIndex8Store, " "Index8StoreSpan\n"); cfb->store = DIBIndex8Store; if( gc->modes.alphaBits ) cfb->fetch = DIBIndex8RGBAFetch; else cfb->fetch = DIBIndex8RGBFetch; break; case 16: DBGLEVEL(DBG_PICK, "DIBBitfield16Store\n"); cfb->store = DIBBitfield16Store; if( gc->modes.alphaBits ) cfb->fetch = DIBBitfield16RGBAFetch; else cfb->fetch = DIBBitfield16RGBFetch; break; case 24: if (cfb->redShift == 16) { DBGLEVEL(DBG_PICK, "DIBBGRStore\n"); cfb->store = DIBBGRStore; if( gc->modes.alphaBits ) cfb->fetch = DIBBGRAFetch; else cfb->fetch = DIBBGRFetch; } else { DBGLEVEL(DBG_PICK, "DIBRGBStore\n"); cfb->store = DIBRGBAStore; if( gc->modes.alphaBits ) cfb->fetch = DIBRGBAFetch; else cfb->fetch = DIBRGBFetch; } break; case 32: DBGLEVEL(DBG_PICK, "DIBBitfield32Store, " "Bitfield32StoreSpan\n"); cfb->store = DIBBitfield32Store; if( gc->modes.alphaBits ) cfb->fetch = DIBBitfield32RGBAFetch; else cfb->fetch = DIBBitfield32RGBFetch; break; } } else { switch(pfmt->cColorBits) { case 4: DBGLEVEL(DBG_PICK, "DisplayIndex4Store\n"); cfb->store = DisplayIndex4Store; cfb->fetch = DisplayIndex4RGBAFetch; cfb->readSpan = DisplayIndex4RGBAReadSpan; break; case 8: DBGLEVEL(DBG_PICK, "DisplayIndex8Store, " "Index8StoreSpan\n"); cfb->store = DisplayIndex8Store; if( gc->modes.alphaBits ) cfb->fetch = DisplayIndex8RGBAFetch; else cfb->fetch = DisplayIndex8RGBFetch; break; case 16: DBGLEVEL(DBG_PICK, "DisplayBitfield16Store\n"); cfb->store = DisplayBitfield16Store; if( gc->modes.alphaBits ) cfb->fetch = DisplayBitfield16RGBAFetch; else cfb->fetch = DisplayBitfield16RGBFetch; break; case 24: // Must be RGB or BGR if (cfb->redShift == 16) { DBGLEVEL(DBG_PICK, "DisplayBGRStore\n"); cfb->store = DisplayBGRStore; if( gc->modes.alphaBits ) cfb->fetch = DisplayBGRAFetch; else cfb->fetch = DisplayBGRFetch; } else { DBGLEVEL(DBG_PICK, "DisplayRGBStore\n"); cfb->store = DisplayRGBStore; if( gc->modes.alphaBits ) cfb->fetch = DisplayRGBAFetch; else cfb->fetch = DisplayRGBFetch; } break; case 32: DBGLEVEL(DBG_PICK, "DisplayBitfield32Store, " "Bitfield32StoreSpan\n"); cfb->store = DisplayBitfield32Store; if( gc->modes.alphaBits ) cfb->fetch = DisplayBitfield32RGBAFetch; else cfb->fetch = DisplayBitfield32RGBFetch; break; } } // cfb->readColor is the same as cfb->fetch (so why do we need it ?) cfb->readColor = cfb->fetch; // If we are only writing alpha (rgb all masked), can further optimize: // Don't bother if logicOp or blending are enabled, and only if we // have a software alpha buffer if( gc->modes.alphaBits && ! ALPHA_IN_PIXEL( cfb ) && (sourceMask == 0) && gc->state.raster.aMask && !(enables & __GL_COLOR_LOGIC_OP_ENABLE) && ! (enables & __GL_BLEND_ENABLE) ) { cfb->store = AlphaStore; cfb->storeSpan = AlphaStoreSpan; } } } /************************************************************************/ void FASTCALL __glGenFreeRGB(__GLcontext *gc, __GLcolorBuffer *cfb) { DBGENTRY("__glGenFreeRGB\n"); } /************************************************************************/ // Note: this used to be defined in generic\genrgb.h #define __GL_GENRGB_COMPONENT_SCALE_ALPHA 255 // called at makecurrent time // need to get info out of pixel format structure void FASTCALL __glGenInitRGB(__GLcontext *gc, __GLcolorBuffer *cfb, GLenum type) { __GLGENcontext *gengc = (__GLGENcontext *)gc; PIXELFORMATDESCRIPTOR *pfmt; __glInitGenericCB(gc, cfb); cfb->redMax = (1 << gc->modes.redBits) - 1; cfb->greenMax = (1 << gc->modes.greenBits) - 1; cfb->blueMax = (1 << gc->modes.blueBits) - 1; gc->redVertexScale = cfb->redScale = (__GLfloat)cfb->redMax; gc->greenVertexScale = cfb->greenScale = (__GLfloat)cfb->greenMax; gc->blueVertexScale = cfb->blueScale = (__GLfloat)cfb->blueMax; cfb->iRedScale = cfb->redMax; cfb->iGreenScale = cfb->greenMax; cfb->iBlueScale = cfb->blueMax; // Do any initialization related to alpha if( gc->modes.alphaBits ) { cfb->alphaMax = (1 << gc->modes.alphaBits) - 1; cfb->iAlphaScale = cfb->alphaMax; gc->alphaVertexScale = cfb->alphaScale = (__GLfloat)cfb->alphaMax; // Initialize the software alpha buffer. Actually, we may not need to // do this, since if an mcd pixel format supports alpha, we don't need // the software alpha buffer. But this is the most convenient place to // do it, and no memory will be allocated anyways. just function ptrs // initialized. __glInitAlpha( gc, cfb ); } else { cfb->alphaMax = __GL_GENRGB_COMPONENT_SCALE_ALPHA; cfb->iAlphaScale = __GL_GENRGB_COMPONENT_SCALE_ALPHA; gc->alphaVertexScale = cfb->alphaScale = (__GLfloat)cfb->redMax; } cfb->buf.elementSize = sizeof(GLubyte); // XXX needed? cfb->pick = PickRGB; // called at each validate cfb->resize = Resize; cfb->fetchSpan = __glFetchSpan; cfb->fetchStippledSpan = __glFetchSpan; cfb->storeSpan = SlowStoreSpan; cfb->storeStippledSpan = SlowStoreStippledSpan; pfmt = &gengc->gsurf.pfd; cfb->redShift = pfmt->cRedShift; cfb->greenShift = pfmt->cGreenShift; cfb->blueShift = pfmt->cBlueShift; cfb->alphaShift = pfmt->cAlphaShift; glGenInitCommon(gengc, cfb, type); DBGLEVEL3(LEVEL_INFO,"GeninitRGB: redMax %d, greenMax %d, blueMax %d\n", cfb->redMax, cfb->greenMax, cfb->blueMax); DBGLEVEL3(LEVEL_INFO," redShift %d, greenShift %d, blueShift %d\n", cfb->redShift, cfb->greenShift, cfb->blueShift); DBGLEVEL2(LEVEL_INFO," dwFlags %X, cColorBits %d\n", gengc->dwCurrentFlags, pfmt->cColorBits); }