From a50b7dbc3ba1db8c92b4bbb4f7f06de8d6c039c4 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 25 Sep 2006 23:57:39 +0000 Subject: [PATCH] Initial work for supporting different renderbuffer color depths at runtime. --- src/mesa/swrast/s_alpha.c | 270 ++++++-------- src/mesa/swrast/s_blend.c | 708 ++++++++++++++++++++++++++++-------- src/mesa/swrast/s_context.c | 25 +- src/mesa/swrast/s_context.h | 41 ++- src/mesa/swrast/s_fog.c | 229 +++++++----- src/mesa/swrast/s_logic.c | 101 ++--- src/mesa/swrast/s_masking.c | 79 ++-- src/mesa/swrast/s_span.c | 53 ++- src/mesa/swrast/s_span.h | 5 + src/mesa/swrast/s_zoom.c | 12 + 10 files changed, 1028 insertions(+), 495 deletions(-) diff --git a/src/mesa/swrast/s_alpha.c b/src/mesa/swrast/s_alpha.c index 55c1e6a58f8..8776e6128d5 100644 --- a/src/mesa/swrast/s_alpha.c +++ b/src/mesa/swrast/s_alpha.c @@ -1,9 +1,8 @@ - /* * 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"), @@ -37,188 +36,125 @@ #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; } diff --git a/src/mesa/swrast/s_blend.c b/src/mesa/swrast/s_blend.c index 91ec513d5bc..4e6c3d909f4 100644 --- a/src/mesa/swrast/s_blend.c +++ b/src/mesa/swrast/s_blend.c @@ -51,18 +51,18 @@ #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++) { @@ -73,17 +73,17 @@ blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[], } -/* +/** * 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; @@ -92,18 +92,21 @@ blend_replace( GLcontext *ctx, GLuint n, const GLubyte 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;iColor.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;iColor.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;iColor.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;iColor.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; @@ -441,7 +862,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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; } @@ -466,7 +887,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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; @@ -495,7 +916,8 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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 */ @@ -557,7 +979,8 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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 */ @@ -607,7 +1030,7 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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; } @@ -633,59 +1056,63 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], /* 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 */ @@ -694,56 +1121,60 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 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 */ @@ -757,12 +1188,13 @@ blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], } -/* +/** * 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; @@ -770,77 +1202,77 @@ void _swrast_choose_blend_func( GLcontext *ctx ) 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. @@ -849,25 +1281,17 @@ void _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); } diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index 030313aea60..bb096be75a1 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -199,11 +199,6 @@ _swrast_update_fog_state( GLcontext *ctx ) { 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) { @@ -359,17 +354,16 @@ _swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) * 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 ); } @@ -680,6 +674,17 @@ _swrast_CreateContext( GLcontext *ctx ) 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; diff --git a/src/mesa/swrast/s_context.h b/src/mesa/swrast/s_context.h index 76f08b007ea..0f3df3b48a4 100644 --- a/src/mesa/swrast/s_context.h +++ b/src/mesa/swrast/s_context.h @@ -69,6 +69,22 @@ #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 @@ -79,8 +95,25 @@ * 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 */ @@ -218,7 +251,8 @@ typedef void (*texture_sample_func)(GLcontext *ctx, 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 *); @@ -291,7 +325,6 @@ typedef struct 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 */ diff --git a/src/mesa/swrast/s_fog.c b/src/mesa/swrast/s_fog.c index e3d6274b3fe..daa74ca0ca4 100644 --- a/src/mesa/swrast/s_fog.c +++ b/src/mesa/swrast/s_fog.c @@ -1,8 +1,8 @@ /* * 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"), @@ -30,7 +30,13 @@ #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 + /** @@ -66,6 +72,33 @@ _swrast_z_to_fogfactor(GLcontext *ctx, GLfloat z) } +/** + * 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 @@ -77,11 +110,10 @@ void _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); @@ -96,79 +128,71 @@ _swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) /* 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; @@ -179,33 +203,58 @@ _swrast_fog_rgba_span( const GLcontext *ctx, struct sw_span *span ) * 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 } } diff --git a/src/mesa/swrast/s_logic.c b/src/mesa/swrast/s_logic.c index b791117af82..214e4e7735f 100644 --- a/src/mesa/swrast/s_logic.c +++ b/src/mesa/swrast/s_logic.c @@ -33,20 +33,25 @@ #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; \ } \ } \ @@ -56,91 +61,91 @@ do { \ 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]; \ } \ } \ @@ -152,27 +157,27 @@ do { \ -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); } @@ -200,7 +205,7 @@ _swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb, 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); } @@ -213,33 +218,29 @@ void _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; } diff --git a/src/mesa/swrast/s_masking.c b/src/mesa/swrast/s_masking.c index f83e305b06c..4a82bbe8e6b 100644 --- a/src/mesa/swrast/s_masking.c +++ b/src/mesa/swrast/s_masking.c @@ -43,44 +43,63 @@ void _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 } diff --git a/src/mesa/swrast/s_span.c b/src/mesa/swrast/s_span.c index 009945edb12..72b14ebf3af 100644 --- a/src/mesa/swrast/s_span.c +++ b/src/mesa/swrast/s_span.c @@ -933,7 +933,7 @@ _swrast_write_index_span( GLcontext *ctx, struct sw_span *span) */ { 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; @@ -1311,7 +1311,7 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) */ { 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; @@ -1322,6 +1322,8 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) 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); @@ -1529,6 +1531,7 @@ _swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, /** * 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, @@ -1563,6 +1566,7 @@ _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, @@ -1592,3 +1596,48 @@ _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; +} diff --git a/src/mesa/swrast/s_span.h b/src/mesa/swrast/s_span.h index 40a57e1ae53..4e8ba8e1329 100644 --- a/src/mesa/swrast/s_span.h +++ b/src/mesa/swrast/s_span.h @@ -82,4 +82,9 @@ _swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, 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 diff --git a/src/mesa/swrast/s_zoom.c b/src/mesa/swrast/s_zoom.c index 3fd914083f9..77cf8ca899f 100644 --- a/src/mesa/swrast/s_zoom.c +++ b/src/mesa/swrast/s_zoom.c @@ -144,6 +144,18 @@ zoom_span( GLcontext *ctx, GLint imgX, GLint imgY, const struct sw_span *span, 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; -- 2.30.2