-
/*
* Mesa 3-D graphics library
- * Version: 4.1
+ * Version: 6.5.2
*
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include "s_context.h"
+#define ALPHA_TEST(ALPHA, LOOP_CODE) \
+do { \
+ switch (ctx->Color.AlphaFunc) { \
+ case GL_LESS: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA < ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_LEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA <= ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_GEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA >= ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_GREATER: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA > ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_NOTEQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA != ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ case GL_EQUAL: \
+ for (i = 0; i < n; i++) { \
+ mask[i] &= (ALPHA == ref); \
+ LOOP_CODE; \
+ } \
+ break; \
+ default: \
+ _mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
+ return 0; \
+ } \
+} while (0)
+
+
+
/**
- * \fn GLint _swrast_alpha_test( const GLcontext *ctx, struct sw_span *span )
- * \brief Apply the alpha test to a span of pixels.
- * \return
- * - "0" = all pixels in the span failed the alpha test.
- * - "1" = one or more pixels passed the alpha test.
+ * Perform the alpha test for an array of pixels.
+ * For pixels that fail the test, mask[i] will be set to 0.
+ * \return 0 if all pixels in the span failed the alpha test,
+ * 1 if one or more pixels passed the alpha test.
*/
GLint
-_swrast_alpha_test( const GLcontext *ctx, struct sw_span *span )
+_swrast_alpha_test(const GLcontext *ctx, struct sw_span *span)
{
- const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->array->rgba;
- GLchan ref;
const GLuint n = span->end;
GLubyte *mask = span->array->mask;
GLuint i;
- CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
+ if (ctx->Color.AlphaFunc == GL_ALWAYS) {
+ /* do nothing */
+ return 1;
+ }
+ else if (ctx->Color.AlphaFunc == GL_NEVER) {
+ /* All pixels failed - caller should check for this return value and
+ * act accordingly.
+ */
+ span->writeAll = GL_FALSE;
+ return 0;
+ }
if (span->arrayMask & SPAN_RGBA) {
- /* Use the array values */
- switch (ctx->Color.AlphaFunc) {
- case GL_LESS:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] < ref);
- break;
- case GL_LEQUAL:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] <= ref);
- break;
- case GL_GEQUAL:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] >= ref);
- break;
- case GL_GREATER:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] > ref);
- break;
- case GL_NOTEQUAL:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] != ref);
- break;
- case GL_EQUAL:
- for (i = 0; i < n; i++)
- mask[i] &= (rgba[i][ACOMP] == ref);
- break;
- case GL_ALWAYS:
- /* do nothing */
- return 1;
- case GL_NEVER:
- /* caller should check for zero! */
- span->writeAll = GL_FALSE;
- return 0;
- default:
- _mesa_problem( ctx, "Invalid alpha test in _swrast_alpha_test" );
- return 0;
+ /* Use array's alpha values */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = span->array->color.sz1.rgba;
+ GLubyte ref;
+ CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(rgba[i][ACOMP], ;);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = span->array->color.sz2.rgba;
+ GLushort ref;
+ CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(rgba[i][ACOMP], ;);
+ }
+ else {
+ GLfloat (*rgba)[4] = span->array->color.sz4.rgba;
+ const GLfloat ref = ctx->Color.AlphaRef;
+ ALPHA_TEST(rgba[i][ACOMP], ;);
}
}
else {
- /* Use the interpolation values */
-#if CHAN_TYPE == GL_FLOAT
- const GLfloat alphaStep = span->alphaStep;
- GLfloat alpha = span->alpha;
+ /* Interpolate alpha values */
ASSERT(span->interpMask & SPAN_RGBA);
- switch (ctx->Color.AlphaFunc) {
- case GL_LESS:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha < ref);
- alpha += alphaStep;
- }
- break;
- case GL_LEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha <= ref);
- alpha += alphaStep;
- }
- break;
- case GL_GEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha >= ref);
- alpha += alphaStep;
- }
- break;
- case GL_GREATER:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha > ref);
- alpha += alphaStep;
- }
- break;
- case GL_NOTEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha != ref);
- alpha += alphaStep;
- }
- break;
- case GL_EQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (alpha == ref);
- alpha += alphaStep;
- }
- break;
- case GL_ALWAYS:
- /* do nothing */
- return 1;
- case GL_NEVER:
- /* caller should check for zero! */
- span->writeAll = GL_FALSE;
- return 0;
- default:
- _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
- return 0;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ const GLfixed alphaStep = span->alphaStep;
+ GLfixed alpha = span->alpha;
+ GLubyte ref;
+ CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(alpha, alpha += alphaStep);
}
-#else
- /* 8 or 16-bit channel interpolation */
- const GLfixed alphaStep = span->alphaStep;
- GLfixed alpha = span->alpha;
- ASSERT(span->interpMask & SPAN_RGBA);
- switch (ctx->Color.AlphaFunc) {
- case GL_LESS:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) < ref);
- alpha += alphaStep;
- }
- break;
- case GL_LEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) <= ref);
- alpha += alphaStep;
- }
- break;
- case GL_GEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) >= ref);
- alpha += alphaStep;
- }
- break;
- case GL_GREATER:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) > ref);
- alpha += alphaStep;
- }
- break;
- case GL_NOTEQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) != ref);
- alpha += alphaStep;
- }
- break;
- case GL_EQUAL:
- for (i = 0; i < n; i++) {
- mask[i] &= (FixedToChan(alpha) == ref);
- alpha += alphaStep;
- }
- break;
- case GL_ALWAYS:
- /* do nothing */
- return 1;
- case GL_NEVER:
- /* caller should check for zero! */
- span->writeAll = GL_FALSE;
- return 0;
- default:
- _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
- return 0;
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ const GLfixed alphaStep = span->alphaStep;
+ GLfixed alpha = span->alpha;
+ GLushort ref;
+ CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+ ALPHA_TEST(alpha, alpha += alphaStep);
+ }
+ else {
+ const GLfloat alphaStep = span->alphaStep;
+ GLfloat alpha = span->alpha;
+ const GLfloat ref = ctx->Color.AlphaRef;
+ ALPHA_TEST(alpha, alpha += alphaStep);
}
-#endif /* CHAN_TYPE */
}
-#if 0
- /* XXXX This causes conformance failures!!!! */
- while ((span->start <= span->end) &&
- (mask[span->start] == 0))
- span->start ++;
-
- while ((span->end >= span->start) &&
- (mask[span->end] == 0))
- span->end --;
-#endif
-
span->writeAll = GL_FALSE;
- if (span->start >= span->end)
- return 0;
- else
- return 1;
+ /* XXX examine mask[] values? */
+ return 1;
}
#endif
-/*
+/**
* Special case for glBlendFunc(GL_ZERO, GL_ONE)
*/
static void _BLENDAPI
-blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_noop_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
GLuint i;
- ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO);
- ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ZERO);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE);
(void) ctx;
for (i = 0; i < n; i++) {
}
-/*
+/**
* Special case for glBlendFunc(GL_ONE, GL_ZERO)
*/
static void _BLENDAPI
-blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_replace(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
- ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
- ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ZERO);
(void) ctx;
(void) n;
(void) mask;
}
-/*
+/**
* Common transparency blending mode.
*/
static void _BLENDAPI
-blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_transparency_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4],
+ GLenum chanType)
{
GLuint i;
- ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
- ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendSrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstA == GL_ONE_MINUS_SRC_ALPHA);
(void) ctx;
for (i=0;i<n;i++) {
-/*
+/**
* Add src and dest.
*/
static void _BLENDAPI
-blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_add_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
GLuint i;
- ASSERT(ctx->Color.BlendEquationRGB==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendEquationA==GL_FUNC_ADD);
- ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
- ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.BlendSrcRGB == GL_ONE);
+ ASSERT(ctx->Color.BlendDstRGB == GL_ONE);
(void) ctx;
for (i=0;i<n;i++) {
-/*
+/**
* Blend min function (for GL_EXT_blend_minmax)
*/
static void _BLENDAPI
-blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_min_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
GLuint i;
- ASSERT(ctx->Color.BlendEquationRGB==GL_MIN);
- ASSERT(ctx->Color.BlendEquationA==GL_MIN);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_MIN);
+ ASSERT(ctx->Color.BlendEquationA == GL_MIN);
(void) ctx;
for (i=0;i<n;i++) {
-/*
+/**
* Blend max function (for GL_EXT_blend_minmax)
*/
static void _BLENDAPI
-blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_max_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
GLuint i;
- ASSERT(ctx->Color.BlendEquationRGB==GL_MAX);
- ASSERT(ctx->Color.BlendEquationA==GL_MAX);
+ ASSERT(ctx->Color.BlendEquationRGB == GL_MAX);
+ ASSERT(ctx->Color.BlendEquationA == GL_MAX);
(void) ctx;
for (i=0;i<n;i++) {
-/*
+/**
* Modulate: result = src * dest
*/
static void _BLENDAPI
-blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_modulate_ubyte(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
GLuint i;
(void) ctx;
}
-
-/*
- * General case blend pixels.
- * Input: n - number of pixels
- * mask - the usual write mask
- * In/Out: rgba - the incoming and modified pixels
- * Input: dest - the pixels from the dest color buffer
+#if 0
+/**
+ * Do any blending operation, using floating point.
+ * \param n number of pixels
+ * \param mask fragment writemask array
+ * \param src array of incoming (and modified) pixels
+ * \param dst array of pixels from the dest color buffer
*/
+static void
+blend_general_float(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ GLuint i;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ /* Incoming/source Color */
+ const GLfloat Rs = rgba[i][RCOMP];
+ const GLfloat Gs = rgba[i][GCOMP];
+ const GLfloat Bs = rgba[i][BCOMP];
+ const GLfloat As = rgba[i][ACOMP];
+
+ /* Frame buffer/dest color */
+ const GLfloat Rd = dest[i][RCOMP];
+ const GLfloat Gd = dest[i][GCOMP];
+ const GLfloat Bd = dest[i][BCOMP];
+ const GLfloat Ad = dest[i][ACOMP];
+
+ GLfloat sR, sG, sB, sA; /* Source factor */
+ GLfloat dR, dG, dB, dA; /* Dest factor */
+ GLfloat r, g, b, a; /* result color */
+
+ /* XXX for the case of constant blend terms we could init
+ * the sX and dX variables just once before the loop.
+ */
+
+ /* Source RGB factor */
+ switch (ctx->Color.BlendSrcRGB) {
+ case GL_ZERO:
+ sR = sG = sB = 0.0F;
+ break;
+ case GL_ONE:
+ sR = sG = sB = 1.0F;
+ break;
+ case GL_DST_COLOR:
+ sR = Rd;
+ sG = Gd;
+ sB = Bd;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sR = 1.0F - Rd;
+ sG = 1.0F - Gd;
+ sB = 1.0F - Bd;
+ break;
+ case GL_SRC_ALPHA:
+ sR = sG = sB = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sR = sG = sB = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ sR = sG = sB = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sR = sG = sB = 1.0F - Ad;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ if (As < 1.0F - Ad) {
+ sR = sG = sB = As;
+ }
+ else {
+ sR = sG = sB = 1.0F - Ad;
+ }
+ break;
+ case GL_CONSTANT_COLOR:
+ sR = ctx->Color.BlendColor[0];
+ sG = ctx->Color.BlendColor[1];
+ sB = ctx->Color.BlendColor[2];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ sR = 1.0F - ctx->Color.BlendColor[0];
+ sG = 1.0F - ctx->Color.BlendColor[1];
+ sB = 1.0F - ctx->Color.BlendColor[2];
+ break;
+ case GL_CONSTANT_ALPHA:
+ sR = sG = sB = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_SRC_COLOR: /* GL_NV_blend_square */
+ sR = Rs;
+ sG = Gs;
+ sB = Bs;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+ sR = 1.0F - Rs;
+ sG = 1.0F - Gs;
+ sB = 1.0F - Bs;
+ break;
+ default:
+ /* this should never happen */
+ _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
+ return;
+ }
+
+ /* Source Alpha factor */
+ switch (ctx->Color.BlendSrcA) {
+ case GL_ZERO:
+ sA = 0.0F;
+ break;
+ case GL_ONE:
+ sA = 1.0F;
+ break;
+ case GL_DST_COLOR:
+ sA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sA = 1.0F - Ad;
+ break;
+ case GL_SRC_ALPHA:
+ sA = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sA = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ sA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sA = 1.0F - Ad;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sA = 1.0;
+ break;
+ case GL_CONSTANT_COLOR:
+ sA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ sA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_CONSTANT_ALPHA:
+ sA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ sA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_SRC_COLOR: /* GL_NV_blend_square */
+ sA = As;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+ sA = 1.0F - As;
+ break;
+ default:
+ /* this should never happen */
+ sA = 0.0F;
+ _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
+ return;
+ }
+
+ /* Dest RGB factor */
+ switch (ctx->Color.BlendDstRGB) {
+ case GL_ZERO:
+ dR = dG = dB = 0.0F;
+ break;
+ case GL_ONE:
+ dR = dG = dB = 1.0F;
+ break;
+ case GL_SRC_COLOR:
+ dR = Rs;
+ dG = Gs;
+ dB = Bs;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dR = 1.0F - Rs;
+ dG = 1.0F - Gs;
+ dB = 1.0F - Bs;
+ break;
+ case GL_SRC_ALPHA:
+ dR = dG = dB = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dR = dG = dB = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ dR = dG = dB = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dR = dG = dB = 1.0F - Ad;
+ break;
+ case GL_CONSTANT_COLOR:
+ dR = ctx->Color.BlendColor[0];
+ dG = ctx->Color.BlendColor[1];
+ dB = ctx->Color.BlendColor[2];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dR = 1.0F - ctx->Color.BlendColor[0];
+ dG = 1.0F - ctx->Color.BlendColor[1];
+ dB = 1.0F - ctx->Color.BlendColor[2];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dR = dG = dB = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_DST_COLOR: /* GL_NV_blend_square */
+ dR = Rd;
+ dG = Gd;
+ dB = Bd;
+ break;
+ case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+ dR = 1.0F - Rd;
+ dG = 1.0F - Gd;
+ dB = 1.0F - Bd;
+ break;
+ default:
+ /* this should never happen */
+ dR = dG = dB = 0.0F;
+ _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
+ return;
+ }
+
+ /* Dest Alpha factor */
+ switch (ctx->Color.BlendDstA) {
+ case GL_ZERO:
+ dA = 0.0F;
+ break;
+ case GL_ONE:
+ dA = 1.0F;
+ break;
+ case GL_SRC_COLOR:
+ dA = As;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dA = 1.0F - As;
+ break;
+ case GL_SRC_ALPHA:
+ dA = As;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dA = 1.0F - As;
+ break;
+ case GL_DST_ALPHA:
+ dA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dA = 1.0F - Ad;
+ break;
+ case GL_CONSTANT_COLOR:
+ dA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_DST_COLOR: /* GL_NV_blend_square */
+ dA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+ dA = 1.0F - Ad;
+ break;
+ default:
+ /* this should never happen */
+ dA = 0.0F;
+ _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
+ return;
+ }
+
+ /* compute the blended RGB */
+ switch (ctx->Color.BlendEquationRGB) {
+ case GL_FUNC_ADD:
+ r = Rs * sR + Rd * dR;
+ g = Gs * sG + Gd * dG;
+ b = Bs * sB + Bd * dB;
+ a = As * sA + Ad * dA;
+ break;
+ case GL_FUNC_SUBTRACT:
+ r = Rs * sR - Rd * dR;
+ g = Gs * sG - Gd * dG;
+ b = Bs * sB - Bd * dB;
+ a = As * sA - Ad * dA;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ r = Rd * dR - Rs * sR;
+ g = Gd * dG - Gs * sG;
+ b = Bd * dB - Bs * sB;
+ a = Ad * dA - As * sA;
+ break;
+ case GL_MIN:
+ r = MIN2( Rd, Rs );
+ g = MIN2( Gd, Gs );
+ b = MIN2( Bd, Bs );
+ break;
+ case GL_MAX:
+ r = MAX2( Rd, Rs );
+ g = MAX2( Gd, Gs );
+ b = MAX2( Bd, Bs );
+ break;
+ default:
+ /* should never get here */
+ r = g = b = 0.0F; /* silence uninitialized var warning */
+ _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
+ }
+
+ /* compute the blended alpha */
+ switch (ctx->Color.BlendEquationA) {
+ case GL_FUNC_ADD:
+ a = As * sA + Ad * dA;
+ break;
+ case GL_FUNC_SUBTRACT:
+ a = As * sA - Ad * dA;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ a = Ad * dA - As * sA;
+ break;
+ case GL_MIN:
+ a = MIN2( Ad, As );
+ break;
+ case GL_MAX:
+ a = MAX2( Ad, As );
+ break;
+ default:
+ /* should never get here */
+ a = 0.0F; /* silence uninitialized var warning */
+ _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
+ }
+
+ /* final clamping */
+#if 0
+ rgba[i][RCOMP] = MAX2( r, 0.0F );
+ rgba[i][GCOMP] = MAX2( g, 0.0F );
+ rgba[i][BCOMP] = MAX2( b, 0.0F );
+ rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
+#else
+ ASSIGN_4V(rgba[i], r, g, b, a);
+#endif
+ }
+ }
+}
+#endif
+
+
+#if 0 /* not ready yet */
+static void
+blend_general2(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ void *src, const void *dst, GLenum chanType)
+{
+ GLfloat rgbaF[MAX_WIDTH][4], destF[MAX_WIDTH][4];
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ GLuint i;
+ /* convert ubytes to floats */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
+ rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
+ rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
+ rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
+ destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
+ destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
+ destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
+ destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
+ }
+ }
+ /* do blend */
+ blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+ /* convert back to ubytes */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_UBYTE(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ GLuint i;
+ /* convert ushorts to floats */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
+ rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
+ rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
+ rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
+ destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
+ destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
+ destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
+ destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
+ }
+ }
+ /* do blend */
+ blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
+ /* convert back to ushorts */
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
+ UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
+ }
+ }
+ }
+ else {
+ blend_general_float(ctx, n, mask, (GLfloat (*)[4]) rgbaF,
+ (const GLfloat (*)[4]) destF, chanType);
+ }
+}
+#endif
+
+
static void _BLENDAPI
-blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLchan rgba[][4], CONST GLchan dest[][4] )
+blend_general(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan rgba[][4], CONST GLchan dest[][4],
+ GLenum chanType)
{
const GLfloat rscale = 1.0F / CHAN_MAXF;
const GLfloat gscale = 1.0F / CHAN_MAXF;
break;
default:
/* this should never happen */
- _mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
+ _mesa_problem(ctx, "Bad blend source RGB factor in blend_general");
return;
}
sA = 1.0F - (GLfloat) As * ascale;
break;
case GL_DST_ALPHA:
- sA =(GLfloat) Ad * ascale;
+ sA = (GLfloat) Ad * ascale;
break;
case GL_ONE_MINUS_DST_ALPHA:
sA = 1.0F - (GLfloat) Ad * ascale;
default:
/* this should never happen */
sA = 0.0F;
- _mesa_problem(ctx, "Bad blend source A factor in do_blend");
+ _mesa_problem(ctx, "Bad blend source A factor in blend_general");
+ return;
}
/* Dest RGB factor */
default:
/* this should never happen */
dR = dG = dB = 0.0F;
- _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
+ _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general");
+ return;
}
/* Dest Alpha factor */
default:
/* this should never happen */
dA = 0.0F;
- _mesa_problem(ctx, "Bad blend dest A factor in do_blend");
+ _mesa_problem(ctx, "Bad blend dest A factor in blend_general");
return;
}
/* compute blended color */
#if CHAN_TYPE == GL_FLOAT
- if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
+ switch (ctx->Color.BlendEquationRGB) {
+ case GL_FUNC_ADD:
r = Rs * sR + Rd * dR;
g = Gs * sG + Gd * dG;
b = Bs * sB + Bd * dB;
a = As * sA + Ad * dA;
- }
- else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
+ break;
+ case GL_FUNC_SUBTRACT:
r = Rs * sR - Rd * dR;
g = Gs * sG - Gd * dG;
b = Bs * sB - Bd * dB;
a = As * sA - Ad * dA;
- }
- else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
r = Rd * dR - Rs * sR;
g = Gd * dG - Gs * sG;
b = Bd * dB - Bs * sB;
a = Ad * dA - As * sA;
- }
- else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+ break;
+ case GL_MIN:
r = MIN2( Rd, Rs );
g = MIN2( Gd, Gs );
b = MIN2( Bd, Bs );
- }
- else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+ break;
+ case GL_MAX:
r = MAX2( Rd, Rs );
g = MAX2( Gd, Gs );
b = MAX2( Bd, Bs );
- }
- else {
+ break;
+ default:
/* should never get here */
r = g = b = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
}
- if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+ switch (ctx->Color.BlendEquationA) {
+ case GL_FUNC_ADD:
a = As * sA + Ad * dA;
- }
- else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+ break;
+ case GL_FUNC_SUBTRACT:
a = As * sA - Ad * dA;
- }
- else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
a = Ad * dA - As * sA;
- }
- else if (ctx->Color.BlendEquationA==GL_MIN) {
+ break;
+ case GL_MIN:
a = MIN2( Ad, As );
- }
- else if (ctx->Color.BlendEquationA==GL_MAX) {
+ break;
+ case GL_MAX:
a = MAX2( Ad, As );
- }
- else {
+ break;
+ default:
/* should never get here */
a = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
}
/* final clamping */
rgba[i][BCOMP] = MAX2( b, 0.0F );
rgba[i][ACOMP] = CLAMP( a, 0.0F, CHAN_MAXF );
#else
- if (ctx->Color.BlendEquationRGB==GL_FUNC_ADD) {
+ switch (ctx->Color.BlendEquationRGB) {
+ case GL_FUNC_ADD:
r = Rs * sR + Rd * dR + 0.5F;
g = Gs * sG + Gd * dG + 0.5F;
b = Bs * sB + Bd * dB + 0.5F;
- }
- else if (ctx->Color.BlendEquationRGB==GL_FUNC_SUBTRACT) {
+ break;
+ case GL_FUNC_SUBTRACT:
r = Rs * sR - Rd * dR + 0.5F;
g = Gs * sG - Gd * dG + 0.5F;
b = Bs * sB - Bd * dB + 0.5F;
- }
- else if (ctx->Color.BlendEquationRGB==GL_FUNC_REVERSE_SUBTRACT) {
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
r = Rd * dR - Rs * sR + 0.5F;
g = Gd * dG - Gs * sG + 0.5F;
b = Bd * dB - Bs * sB + 0.5F;
- }
- else if (ctx->Color.BlendEquationRGB==GL_MIN) {
+ break;
+ case GL_MIN:
r = MIN2( Rd, Rs );
g = MIN2( Gd, Gs );
b = MIN2( Bd, Bs );
- }
- else if (ctx->Color.BlendEquationRGB==GL_MAX) {
+ break;
+ case GL_MAX:
r = MAX2( Rd, Rs );
g = MAX2( Gd, Gs );
b = MAX2( Bd, Bs );
- }
- else {
+ break;
+ default:
/* should never get here */
r = g = b = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
}
- if (ctx->Color.BlendEquationA==GL_FUNC_ADD) {
+ switch (ctx->Color.BlendEquationA) {
+ case GL_FUNC_ADD:
a = As * sA + Ad * dA + 0.5F;
- }
- else if (ctx->Color.BlendEquationA==GL_FUNC_SUBTRACT) {
+ break;
+ case GL_FUNC_SUBTRACT:
a = As * sA - Ad * dA + 0.5F;
- }
- else if (ctx->Color.BlendEquationA==GL_FUNC_REVERSE_SUBTRACT) {
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
a = Ad * dA - As * sA + 0.5F;
- }
- else if (ctx->Color.BlendEquationA==GL_MIN) {
+ break;
+ case GL_MIN:
a = MIN2( Ad, As );
- }
- else if (ctx->Color.BlendEquationA==GL_MAX) {
+ break;
+ case GL_MAX:
a = MAX2( Ad, As );
- }
- else {
+ break;
+ default:
/* should never get here */
a = 0.0F; /* silence uninitialized var warning */
_mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
+ return;
}
/* final clamping */
}
-/*
+/**
* Analyze current blending parameters to pick fastest blending function.
* Result: the ctx->Color.BlendFunc pointer is updated.
*/
void _swrast_choose_blend_func( GLcontext *ctx )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
const GLenum eq = ctx->Color.BlendEquationRGB;
const GLenum srcRGB = ctx->Color.BlendSrcRGB;
const GLenum dstRGB = ctx->Color.BlendDstRGB;
const GLenum dstA = ctx->Color.BlendDstA;
if (ctx->Color.BlendEquationRGB != ctx->Color.BlendEquationA) {
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+ swrast->BlendFunc = blend_general;
}
- else if (eq==GL_MIN) {
+ else if (eq == GL_MIN) {
/* Note: GL_MIN ignores the blending weight factors */
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
- SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_min;
+ swrast->BlendFunc = _mesa_mmx_blend_min;
}
else
#endif
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
+ swrast->BlendFunc = blend_min_ubyte;
}
- else if (eq==GL_MAX) {
+ else if (eq == GL_MAX) {
/* Note: GL_MAX ignores the blending weight factors */
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
- SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_max;
+ swrast->BlendFunc = _mesa_mmx_blend_max;
}
else
#endif
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
+ swrast->BlendFunc = blend_max_ubyte;
}
else if (srcRGB != srcA || dstRGB != dstA) {
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+ swrast->BlendFunc = blend_general;
}
- else if (eq==GL_FUNC_ADD && srcRGB==GL_SRC_ALPHA
- && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
+ && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
- SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
+ swrast->BlendFunc = _mesa_mmx_blend_transparency;
}
else
#endif
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
+ swrast->BlendFunc = blend_transparency_ubyte;
}
- else if (eq==GL_FUNC_ADD && srcRGB==GL_ONE && dstRGB==GL_ONE) {
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
- SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_add;
+ swrast->BlendFunc = _mesa_mmx_blend_add;
}
else
#endif
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
+ swrast->BlendFunc = blend_add_ubyte;
}
- else if (((eq==GL_FUNC_ADD || eq==GL_FUNC_REVERSE_SUBTRACT)
- && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
+ else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
+ && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
||
- ((eq==GL_FUNC_ADD || eq==GL_FUNC_SUBTRACT)
- && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
+ ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
+ && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
#if defined(USE_MMX_ASM)
if ( cpu_has_mmx ) {
- SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_modulate;
+ swrast->BlendFunc = _mesa_mmx_blend_modulate;
}
else
#endif
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
+ swrast->BlendFunc = blend_modulate_ubyte;
}
- else if (eq==GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
+ swrast->BlendFunc = blend_noop_ubyte;
}
- else if (eq==GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
+ swrast->BlendFunc = blend_replace;
}
else {
- SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
+ swrast->BlendFunc = blend_general;
}
}
-/*
+/**
* Apply the blending operator to a span of pixels.
* We can handle horizontal runs of pixels (spans) or arrays of x/y
* pixel coordinates.
_swrast_blend_span(GLcontext *ctx, struct gl_renderbuffer *rb,
struct sw_span *span)
{
- GLchan framebuffer[MAX_WIDTH][4];
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ void *rbPixels;
ASSERT(span->end <= MAX_WIDTH);
ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(rb->DataType == span->array->ChanType);
ASSERT(!ctx->Color._LogicOpEnabled);
- /* Read span of current frame buffer pixels */
- if (span->arrayMask & SPAN_XY) {
- /* array of x/y pixel coords */
- _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
- framebuffer, 4 * sizeof(GLchan));
- }
- else {
- /* horizontal run of pixels */
- _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y,
- framebuffer);
- }
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
- SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->array->mask,
- span->array->rgba,
- (const GLchan (*)[4]) framebuffer );
+ swrast->BlendFunc(ctx, span->end, span->array->mask,
+ span->array->rgba, (const GLchan (*)[4]) rbPixels,
+ span->array->ChanType);
}
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
- /* convert fog color to GLchan values */
- CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[RCOMP], ctx->Fog.Color[RCOMP]);
- CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[GCOMP], ctx->Fog.Color[GCOMP]);
- CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[BCOMP], ctx->Fog.Color[BCOMP]);
-
/* determine if fog is needed, and if so, which fog mode */
swrast->_FogEnabled = GL_FALSE;
if (ctx->FragmentProgram._Enabled) {
* function, then call it.
*/
static void _ASMAPI
-_swrast_validate_blend_func( GLcontext *ctx, GLuint n,
- const GLubyte mask[],
- GLchan src[][4],
- CONST GLchan dst[][4] )
+_swrast_validate_blend_func(GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLchan src[][4], CONST GLchan dst[][4],
+ GLenum chanType )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
_swrast_validate_derived( ctx );
_swrast_choose_blend_func( ctx );
- swrast->BlendFunc( ctx, n, mask, src, dst );
+ swrast->BlendFunc( ctx, n, mask, src, dst, chanType );
}
FREE(swrast);
return GL_FALSE;
}
+ swrast->SpanArrays->ChanType = CHAN_TYPE;
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz1.rgba;
+ swrast->SpanArrays->spec = swrast->SpanArrays->color.sz1.spec;
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+ swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz2.rgba;
+ swrast->SpanArrays->spec = swrast->SpanArrays->color.sz2.spec;
+#else
+ swrast->SpanArrays->rgba = swrast->SpanArrays->color.sz4.rgba;
+ swrast->SpanArrays->spec = swrast->SpanArrays->color.sz4.spec;
+#endif
/* init point span buffer */
swrast->PointSpan.primitive = GL_POINT;
#define SPAN_VARYING 0x2000
/*@}*/
+#if 0
+/* alternate arrangement for code below */
+struct arrays2 {
+ union {
+ GLubyte sz1[MAX_WIDTH][4]; /* primary color */
+ GLushort sz2[MAX_WIDTH][4];
+ GLfloat sz4[MAX_WIDTH][4];
+ } rgba;
+ union {
+ GLubyte sz1[MAX_WIDTH][4]; /* specular color and temp storage */
+ GLushort sz2[MAX_WIDTH][4];
+ GLfloat sz4[MAX_WIDTH][4];
+ } spec;
+};
+#endif
+
/**
* \struct span_arrays
* These arrays are separated out of sw_span to conserve memory.
*/
struct span_arrays {
- GLchan rgba[MAX_WIDTH][4];
- GLchan spec[MAX_WIDTH][4]; /* specular color */
+ GLenum ChanType; /**< Color channel type, GL_UNSIGNED_BYTE, GL_FLOAT */
+ union {
+ struct {
+ GLubyte rgba[MAX_WIDTH][4]; /**< primary color */
+ GLubyte spec[MAX_WIDTH][4]; /**< specular color and temp storage */
+ } sz1;
+ struct {
+ GLushort rgba[MAX_WIDTH][4];
+ GLushort spec[MAX_WIDTH][4];
+ } sz2;
+ struct {
+ GLfloat rgba[MAX_WIDTH][4];
+ GLfloat spec[MAX_WIDTH][4];
+ } sz4;
+ } color;
+ /** XXX these are temporary fields, pointing into above color arrays */
+ GLchan (*rgba)[4];
+ GLchan (*spec)[4];
+
GLuint index[MAX_WIDTH];
GLint x[MAX_WIDTH]; /**< X/Y used for point/line rendering only */
GLint y[MAX_WIDTH]; /**< X/Y used for point/line rendering only */
typedef void (_ASMAPIP blend_func)( GLcontext *ctx, GLuint n,
const GLubyte mask[],
- GLchan src[][4], CONST GLchan dst[][4] );
+ GLchan src[][4], CONST GLchan dst[][4],
+ GLenum chanType);
typedef void (*swrast_point_func)( GLcontext *ctx, const SWvertex *);
GLfloat _BackfaceSign;
GLboolean _PreferPixelFog; /* Compute fog blend factor per fragment? */
GLboolean _AnyTextureCombine;
- GLchan _FogColor[3];
GLboolean _FogEnabled;
GLenum _FogMode; /* either GL_FOG_MODE or fragment program's fog mode */
/*
* Mesa 3-D graphics library
- * Version: 6.3
+ * Version: 6.5.2
*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include "s_context.h"
#include "s_fog.h"
-#include "s_span.h"
+
+
+/** XXX temporary */
+#define UBYTE_RGBA GLubyte (*rgba)[4] = span->array->color.sz1.rgba
+#define USHORT_RGBA GLushort (*rgba)[4] = span->array->color.sz2.rgba
+#define FLOAT_RGBA GLfloat (*rgba)[4] = span->array->color.sz4.rgba
+
/**
}
+/**
+ * Template code for computing fog blend factor and applying it to colors.
+ * \param TYPE either GLubyte, GLushort or GLfloat.
+ * \param COMPUTE_F code to compute the fog blend factor, f.
+ */
+#define FOG_LOOP(TYPE, COMPUTE_F) \
+do { \
+ const GLfloat fogStep = span->fogStep; \
+ GLfloat fogCoord = span->fog; \
+ const GLfloat wStep = haveW ? span->dwdx : 0.0F; \
+ GLfloat w = haveW ? span->w : 1.0F; \
+ GLuint i; \
+ for (i = 0; i < span->end; i++) { \
+ GLfloat f, oneMinusF; \
+ COMPUTE_F; \
+ f = CLAMP(f, 0.0F, 1.0F); \
+ oneMinusF = 1.0F - f; \
+ rgba[i][RCOMP] = (TYPE) (f * rgba[i][RCOMP] + oneMinusF * rFog); \
+ rgba[i][GCOMP] = (TYPE) (f * rgba[i][GCOMP] + oneMinusF * gFog); \
+ rgba[i][BCOMP] = (TYPE) (f * rgba[i][BCOMP] + oneMinusF * bFog); \
+ fogCoord += fogStep; \
+ w += wStep; \
+ } \
+} while (0)
+
+
+
/**
* Apply fog to a span of RGBA pixels.
* The fog value are either in the span->array->fog array or interpolated from
_swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span )
{
const SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const GLchan rFog = swrast->_FogColor[RCOMP];
- const GLchan gFog = swrast->_FogColor[GCOMP];
- const GLchan bFog = swrast->_FogColor[BCOMP];
+ const GLfloat rFog = ctx->Fog.Color[RCOMP] * CHAN_MAX;
+ const GLfloat gFog = ctx->Fog.Color[GCOMP] * CHAN_MAX;
+ const GLfloat bFog = ctx->Fog.Color[BCOMP] * CHAN_MAX;
const GLuint haveW = (span->interpMask & SPAN_W);
- GLchan (*rgba)[4] = (GLchan (*)[4]) span->array->rgba;
ASSERT(swrast->_FogEnabled);
ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG);
/* The span's fog values are fog coordinates, now compute blend factors
* and blend the fragment colors with the fog color.
*/
+ const GLfloat fogEnd = ctx->Fog.End;
+ const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
+ ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ const GLfloat density = -ctx->Fog.Density;
+ const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+
switch (swrast->_FogMode) {
case GL_LINEAR:
- {
- const GLfloat fogEnd = ctx->Fog.End;
- const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End)
- ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start);
- const GLfloat fogStep = span->fogStep;
- GLfloat fogCoord = span->fog;
- const GLfloat wStep = haveW ? span->dwdx : 0.0F;
- GLfloat w = haveW ? span->w : 1.0F;
- GLuint i;
- for (i = 0; i < span->end; i++) {
- GLfloat f, oneMinusF;
- f = (fogEnd - FABSF(fogCoord) / w) * fogScale;
- f = CLAMP(f, 0.0F, 1.0F);
- oneMinusF = 1.0F - f;
- rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
- rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
- rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
- fogCoord += fogStep;
- w += wStep;
- }
+#define COMPUTE_F f = (fogEnd - FABSF(fogCoord) / w) * fogScale;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ UBYTE_RGBA;
+ FOG_LOOP(GLubyte, COMPUTE_F);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ USHORT_RGBA;
+ FOG_LOOP(GLushort, COMPUTE_F);
}
+ else {
+ FLOAT_RGBA;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, COMPUTE_F);
+ }
+#undef COMPUTE_F
break;
+
case GL_EXP:
- {
- const GLfloat density = -ctx->Fog.Density;
- const GLfloat fogStep = span->fogStep;
- GLfloat fogCoord = span->fog;
- const GLfloat wStep = haveW ? span->dwdx : 0.0F;
- GLfloat w = haveW ? span->w : 1.0F;
- GLuint i;
- for (i = 0; i < span->end; i++) {
- GLfloat f, oneMinusF;
- f = EXPF(density * FABSF(fogCoord) / w);
- f = CLAMP(f, 0.0F, 1.0F);
- oneMinusF = 1.0F - f;
- rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
- rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
- rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
- fogCoord += fogStep;
- w += wStep;
- }
+#define COMPUTE_F f = EXPF(density * FABSF(fogCoord) / w);
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ UBYTE_RGBA;
+ FOG_LOOP(GLubyte, COMPUTE_F);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ USHORT_RGBA;
+ FOG_LOOP(GLushort, COMPUTE_F);
+ }
+ else {
+ FLOAT_RGBA;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, COMPUTE_F);
}
+#undef COMPUTE_F
break;
+
case GL_EXP2:
- {
- const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
- const GLfloat fogStep = span->fogStep;
- GLfloat fogCoord = span->fog;
- const GLfloat wStep = haveW ? span->dwdx : 0.0F;
- GLfloat w = haveW ? span->w : 1.0F;
- GLuint i;
- for (i = 0; i < span->end; i++) {
- const GLfloat coord = fogCoord / w;
- GLfloat tmp = negDensitySquared * coord * coord;
- GLfloat f, oneMinusF;
-#if defined(__alpha__) || defined(__alpha)
- /* XXX this underflow check may be needed for other systems*/
- if (tmp < FLT_MIN_10_EXP)
- tmp = FLT_MIN_10_EXP;
-#endif
- f = EXPF(tmp);
- f = CLAMP(f, 0.0F, 1.0F);
- oneMinusF = 1.0F - f;
- rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
- rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
- rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
- fogCoord += fogStep;
- w += wStep;
- }
+#define COMPUTE_F const GLfloat coord = fogCoord / w; \
+ GLfloat tmp = negDensitySquared * coord * coord; \
+ if (tmp < FLT_MIN_10_EXP) \
+ tmp = FLT_MIN_10_EXP; \
+ f = EXPF(tmp);
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ UBYTE_RGBA;
+ FOG_LOOP(GLubyte, COMPUTE_F);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ USHORT_RGBA;
+ FOG_LOOP(GLushort, COMPUTE_F);
+ }
+ else {
+ FLOAT_RGBA;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, COMPUTE_F);
}
+#undef COMPUTE_F
break;
+
default:
_mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span");
return;
* They were previously computed per-vertex.
*/
GLuint i;
- for (i = 0; i < span->end; i++) {
- const GLfloat f = span->array->fog[i];
- const GLfloat oneMinusF = 1.0F - f;
- rgba[i][RCOMP] = (GLchan) (f * rgba[i][RCOMP] + oneMinusF * rFog);
- rgba[i][GCOMP] = (GLchan) (f * rgba[i][GCOMP] + oneMinusF * gFog);
- rgba[i][BCOMP] = (GLchan) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ UBYTE_RGBA;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat f = span->array->fog[i];
+ const GLfloat oneMinusF = 1.0F - f;
+ rgba[i][RCOMP] = (GLubyte) (f * rgba[i][RCOMP] + oneMinusF * rFog);
+ rgba[i][GCOMP] = (GLubyte) (f * rgba[i][GCOMP] + oneMinusF * gFog);
+ rgba[i][BCOMP] = (GLubyte) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+ }
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ USHORT_RGBA;
+ for (i = 0; i < span->end; i++) {
+ const GLfloat f = span->array->fog[i];
+ const GLfloat oneMinusF = 1.0F - f;
+ rgba[i][RCOMP] = (GLushort) (f * rgba[i][RCOMP] + oneMinusF * rFog);
+ rgba[i][GCOMP] = (GLushort) (f * rgba[i][GCOMP] + oneMinusF * gFog);
+ rgba[i][BCOMP] = (GLushort) (f * rgba[i][BCOMP] + oneMinusF * bFog);
+ }
+ }
+ else {
+ FLOAT_RGBA;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ for (i = 0; i < span->end; i++) {
+ const GLfloat f = span->array->fog[i];
+ const GLfloat oneMinusF = 1.0F - f;
+ rgba[i][RCOMP] = f * rgba[i][RCOMP] + oneMinusF * rFog;
+ rgba[i][GCOMP] = f * rgba[i][GCOMP] + oneMinusF * gFog;
+ rgba[i][BCOMP] = f * rgba[i][BCOMP] + oneMinusF * bFog;
+ }
}
+
}
else {
/* The span's fog start/step values are blend factors.
* They were previously computed per-vertex.
*/
- const GLfloat fogStep = span->fogStep;
- GLfloat fog = span->fog;
- const GLfloat wStep = haveW ? span->dwdx : 0.0F;
- GLfloat w = haveW ? span->w : 1.0F;
- GLuint i;
- ASSERT(span->interpMask & SPAN_FOG);
- for (i = 0; i < span->end; i++) {
- const GLfloat fact = fog / w;
- const GLfloat oneMinusF = 1.0F - fact;
- rgba[i][RCOMP] = (GLchan) (fact * rgba[i][RCOMP] + oneMinusF * rFog);
- rgba[i][GCOMP] = (GLchan) (fact * rgba[i][GCOMP] + oneMinusF * gFog);
- rgba[i][BCOMP] = (GLchan) (fact * rgba[i][BCOMP] + oneMinusF * bFog);
- fog += fogStep;
- w += wStep;
+#define COMPUTE_F f = fogCoord / w;
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ UBYTE_RGBA;
+ FOG_LOOP(GLubyte, COMPUTE_F);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ USHORT_RGBA;
+ FOG_LOOP(GLushort, COMPUTE_F);
+ }
+ else {
+ FLOAT_RGBA;
+ ASSERT(span->array->ChanType == GL_FLOAT);
+ FOG_LOOP(GLfloat, COMPUTE_F);
}
+#undef COMPUTE_F
}
}
#include "s_span.h"
-#define LOGIC_OP_LOOP(MODE) \
+/**
+ * We do all logic ops on 4-byte GLuints.
+ * Depending on bytes per pixel, the mask array elements correspond to
+ * 1, 2 or 4 GLuints.
+ */
+#define LOGIC_OP_LOOP(MODE, MASKSTRIDE) \
do { \
GLuint i; \
switch (MODE) { \
case GL_CLEAR: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = 0; \
} \
} \
break; \
case GL_SET: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~0; \
} \
} \
break; \
case GL_COPY_INVERTED: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i]; \
} \
} \
break; \
case GL_NOOP: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = dest[i]; \
} \
} \
break; \
case GL_INVERT: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~dest[i]; \
} \
} \
break; \
case GL_AND: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] &= dest[i]; \
} \
} \
break; \
case GL_NAND: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] & dest[i]); \
} \
} \
break; \
case GL_OR: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] |= dest[i]; \
} \
} \
break; \
case GL_NOR: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] | dest[i]); \
} \
} \
break; \
case GL_XOR: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] ^= dest[i]; \
} \
} \
break; \
case GL_EQUIV: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~(src[i] ^ dest[i]); \
} \
} \
break; \
case GL_AND_REVERSE: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = src[i] & ~dest[i]; \
} \
} \
break; \
case GL_AND_INVERTED: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i] & dest[i]; \
} \
} \
break; \
case GL_OR_REVERSE: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = src[i] | ~dest[i]; \
} \
} \
break; \
case GL_OR_INVERTED: \
for (i = 0; i < n; i++) { \
- if (mask[i]) { \
+ if (mask[i / MASKSTRIDE]) { \
src[i] = ~src[i] | dest[i]; \
} \
} \
-static void
-logicop_ubyte(GLcontext *ctx, GLuint n, GLubyte src[], const GLubyte dest[],
+static INLINE void
+logicop_uint1(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
const GLubyte mask[])
{
- LOGIC_OP_LOOP(ctx->Color.LogicOp);
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
}
-static void
-logicop_ushort(GLcontext *ctx, GLuint n, GLushort src[], const GLushort dest[],
- const GLubyte mask[])
+static INLINE void
+logicop_uint2(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+ const GLubyte mask[])
{
- LOGIC_OP_LOOP(ctx->Color.LogicOp);
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
}
-static void
-logicop_uint(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
- const GLubyte mask[])
+static INLINE void
+logicop_uint4(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
+ const GLubyte mask[])
{
- LOGIC_OP_LOOP(ctx->Color.LogicOp);
+ LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
}
rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
}
- logicop_uint(ctx, span->end, index, dest, span->array->mask);
+ logicop_uint1(ctx, span->end, index, dest, span->array->mask);
}
_swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
struct sw_span *span)
{
- GLchan dest[MAX_WIDTH][4];
+ void *rbPixels;
ASSERT(span->end < MAX_WIDTH);
ASSERT(span->arrayMask & SPAN_RGBA);
- ASSERT(rb->DataType == CHAN_TYPE);
+ ASSERT(rb->DataType == span->array->ChanType);
- if (span->arrayMask & SPAN_XY) {
- _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
- dest, 4 * sizeof(GLchan));
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ /* treat 4*GLubyte as GLuint */
+ logicop_uint1(ctx, span->end,
+ (GLuint *) span->array->color.sz1.rgba,
+ (const GLuint *) rbPixels, span->array->mask);
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ /* treat 2*GLushort as GLuint */
+ logicop_uint2(ctx, 2 * span->end,
+ (GLuint *) span->array->color.sz2.rgba,
+ (const GLuint *) rbPixels, span->array->mask);
}
else {
- _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest);
+ logicop_uint4(ctx, 4 * span->end,
+ (GLuint *) span->array->color.sz4.rgba,
+ (const GLuint *) rbPixels, span->array->mask);
}
-
- /* XXX make this a runtime test */
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
- /* treat 4*GLubyte as GLuint */
- logicop_uint(ctx, span->end, (GLuint *) span->array->rgba,
- (const GLuint *) dest, span->array->mask);
-#elif CHAN_TYPE == GL_UNSIGNED_SHORT
- logicop_ushort(ctx, 4 * span->end, (GLushort *) span->array->rgba,
- (const GLushort *) dest, span->array->mask);
-#elif CHAN_TYPE == GL_FLOAT
- logicop_uint(ctx, 4 * span->end, (GLuint *) span->array->rgba,
- (const GLuint *) dest, span->array->mask);
-#endif
- (void) logicop_ubyte;
- (void) logicop_ushort;
- (void) logicop_uint;
}
_swrast_mask_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
struct sw_span *span)
{
- GLchan dest[MAX_WIDTH][4];
-#if CHAN_BITS == 8
- GLuint srcMask = *((GLuint*)ctx->Color.ColorMask);
- GLuint dstMask = ~srcMask;
- GLuint *rgba32 = (GLuint *) span->array->rgba;
- GLuint *dest32 = (GLuint *) dest;
-#else
- const GLboolean rMask = ctx->Color.ColorMask[RCOMP];
- const GLboolean gMask = ctx->Color.ColorMask[GCOMP];
- const GLboolean bMask = ctx->Color.ColorMask[BCOMP];
- const GLboolean aMask = ctx->Color.ColorMask[ACOMP];
-#endif
const GLuint n = span->end;
- GLuint i;
+ void *rbPixels;
ASSERT(n < MAX_WIDTH);
ASSERT(span->arrayMask & SPAN_RGBA);
+ ASSERT(rb->DataType == span->array->ChanType);
- if (span->arrayMask & SPAN_XY) {
- _swrast_get_values(ctx, rb, n, span->array->x, span->array->y,
- dest, 4 * sizeof(GLchan));
- }
- else {
- _swrast_read_rgba_span(ctx, rb, n, span->x, span->y, dest);
- }
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
-#if CHAN_BITS == 8
- for (i = 0; i < n; i++) {
- rgba32[i] = (rgba32[i] & srcMask) | (dest32[i] & dstMask);
+ /*
+ * Do component masking.
+ * Note that we're not using span->array->mask[] here. We could...
+ */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ /* treat 4xGLubyte as 1xGLuint */
+ const GLuint srcMask = *((GLuint *) ctx->Color.ColorMask);
+ const GLuint dstMask = ~srcMask;
+ const GLuint *dst = (const GLuint *) rbPixels;
+ GLuint *src = (GLuint *) span->array->color.sz1.rgba;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i] = (src[i] & srcMask) | (dst[i] & dstMask);
+ }
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ /* 2-byte components */
+ /* XXX try to use 64-bit arithmetic someday */
+ const GLushort rMask = ctx->Color.ColorMask[RCOMP] ? 0xffff : 0x0;
+ const GLushort gMask = ctx->Color.ColorMask[GCOMP] ? 0xffff : 0x0;
+ const GLushort bMask = ctx->Color.ColorMask[BCOMP] ? 0xffff : 0x0;
+ const GLushort aMask = ctx->Color.ColorMask[ACOMP] ? 0xffff : 0x0;
+ const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels;
+ GLushort (*src)[4] = span->array->color.sz2.rgba;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+ src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+ src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+ src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+ }
}
-#else
- for (i = 0; i < n; i++) {
- if (!rMask) span->array->rgba[i][RCOMP] = dest[i][RCOMP];
- if (!gMask) span->array->rgba[i][GCOMP] = dest[i][GCOMP];
- if (!bMask) span->array->rgba[i][BCOMP] = dest[i][BCOMP];
- if (!aMask) span->array->rgba[i][ACOMP] = dest[i][ACOMP];
+ else {
+ /* 4-byte components */
+ const GLuint rMask = ctx->Color.ColorMask[RCOMP] ? ~0x0 : 0x0;
+ const GLuint gMask = ctx->Color.ColorMask[GCOMP] ? ~0x0 : 0x0;
+ const GLuint bMask = ctx->Color.ColorMask[BCOMP] ? ~0x0 : 0x0;
+ const GLuint aMask = ctx->Color.ColorMask[ACOMP] ? ~0x0 : 0x0;
+ const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels;
+ GLuint (*src)[4] = (GLuint (*)[4]) span->array->color.sz4.rgba;
+ GLuint i;
+ for (i = 0; i < n; i++) {
+ src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask);
+ src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask);
+ src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask);
+ src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask);
+ }
}
-#endif
}
*/
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
- const GLuint output = 0; /* only frag progs can write to others */
+ const GLuint output = 0; /* only frag progs can write to other outputs */
const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
GLuint indexSave[MAX_WIDTH];
GLuint buf;
*/
{
struct gl_framebuffer *fb = ctx->DrawBuffer;
- const GLuint output = 0; /* only frag progs can write to others */
+ const GLuint output = 0; /* only frag progs can write to other outputs */
const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output];
GLchan rgbaSave[MAX_WIDTH][4];
GLuint buf;
4 * span->end * sizeof(GLchan));
}
+ /* XXX check that span's ChanType == rb's DataType, convert if needed */
+
for (buf = 0; buf < numDrawBuffers; buf++) {
struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf];
ASSERT(rb->_BaseFormat == GL_RGBA);
/**
* Wrapper for gl_renderbuffer::PutRow() which does clipping.
+ * \param valueSize size of each value (pixel) in bytes
*/
void
_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb,
/**
* Wrapper for gl_renderbuffer::GetRow() which does clipping.
+ * \param valueSize size of each value (pixel) in bytes
*/
void
_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb,
rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize);
}
+
+
+/**
+ * Get RGBA pixels from the given renderbuffer. Put the pixel colors into
+ * the span's specular color arrays. The specular color arrays should no
+ * longer be needed by time this function is called.
+ * Used by blending, logicop and masking functions.
+ * \return pointer to the colors we read.
+ */
+void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+ struct sw_span *span)
+{
+ GLuint pixelSize;
+ void *rbPixels;
+
+ /*
+ * Determine pixel size (in bytes).
+ * Point rbPixels to a temporary space (use specular color arrays).
+ */
+ if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+ pixelSize = 4 * sizeof(GLubyte);
+ rbPixels = span->array->color.sz1.spec;
+ }
+ else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+ pixelSize = 4 * sizeof(GLushort);
+ rbPixels = span->array->color.sz2.spec;
+ }
+ else {
+ pixelSize = 4 * sizeof(GLfloat);
+ rbPixels = span->array->color.sz4.spec;
+ }
+
+ /* Get destination values from renderbuffer */
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
+ rbPixels, pixelSize);
+ }
+ else {
+ _swrast_get_row(ctx, rb, span->end, span->x, span->y,
+ rbPixels, pixelSize);
+ }
+
+ return rbPixels;
+}
GLuint count, GLint x, GLint y,
GLvoid *values, GLuint valueSize);
+
+extern void *
+_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
+ struct sw_span *span);
+
#endif
zoomed.x = x0;
zoomed.end = zoomedWidth;
zoomed.array = &zoomed_arrays;
+ zoomed_arrays.ChanType = CHAN_TYPE;
+#if CHAN_TYPE == GL_UNSIGNED_BYTE
+ zoomed_arrays.rgba = zoomed_arrays.color.sz1.rgba;
+ zoomed_arrays.spec = zoomed_arrays.color.sz1.spec;
+#elif CHAN_TYPE == GL_UNSIGNED_SHORT
+ zoomed_arrays.rgba = zoomed_arrays.color.sz2.rgba;
+ zoomed_arrays.spec = zoomed_arrays.color.sz2.spec;
+#else
+ zoomed_arrays.rgba = zoomed_arrays.color.sz4.rgba;
+ zoomed_arrays.spec = zoomed_arrays.color.sz4.spec;
+#endif
+
/* copy fog interp info */
zoomed.fog = span->fog;