Initial work for supporting different renderbuffer color depths at runtime.

This commit is contained in:
Brian Paul
2006-09-25 23:57:39 +00:00
parent df8632ebd8
commit a50b7dbc3b
10 changed files with 1028 additions and 495 deletions

View File

@@ -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)
{
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 (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:
if (ctx->Color.AlphaFunc == GL_ALWAYS) {
/* do nothing */
return 1;
case GL_NEVER:
/* caller should check for zero! */
}
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;
default:
_mesa_problem( ctx, "Invalid alpha test in _swrast_alpha_test" );
return 0;
}
if (span->arrayMask & SPAN_RGBA) {
/* 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;
}
#else
/* 8 or 16-bit channel interpolation */
if (span->array->ChanType == GL_UNSIGNED_BYTE) {
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;
GLubyte ref;
CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
ALPHA_TEST(alpha, alpha += alphaStep);
}
break;
case GL_LEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) <= ref);
alpha += alphaStep;
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);
}
break;
case GL_GEQUAL:
for (i = 0; i < n; i++) {
mask[i] &= (FixedToChan(alpha) >= ref);
alpha += alphaStep;
else {
const GLfloat alphaStep = span->alphaStep;
GLfloat alpha = span->alpha;
const GLfloat ref = ctx->Color.AlphaRef;
ALPHA_TEST(alpha, 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;
}
#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
/* XXX examine mask[] values? */
return 1;
}

View File

@@ -51,12 +51,12 @@
#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);
@@ -73,12 +73,12 @@ 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] )
GLchan rgba[][4], CONST GLchan dest[][4], GLenum chanType)
{
ASSERT(ctx->Color.BlendEquationRGB == GL_FUNC_ADD);
ASSERT(ctx->Color.BlendEquationA == GL_FUNC_ADD);
@@ -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.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++) {
@@ -180,12 +183,12 @@ blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
/*
/**
* 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);
@@ -219,12 +222,12 @@ blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
/*
/**
* 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);
@@ -248,12 +251,12 @@ blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
/*
/**
* 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);
@@ -277,12 +280,12 @@ blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
/*
/**
* 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;
@@ -318,17 +321,435 @@ blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
}
/*
* 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] )
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;
}
@@ -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,49 +1202,49 @@ 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) {
/* 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) {
/* 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) {
#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) {
#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))
@@ -821,26 +1253,26 @@ void _swrast_choose_blend_func( GLcontext *ctx )
&& (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;
swrast->BlendFunc = blend_noop_ubyte;
}
else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
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);
}

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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.
*/
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;
}
}
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;
}
}
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;
switch (swrast->_FogMode) {
case GL_LINEAR:
#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:
#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:
#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;
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] = (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);
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
}
}

View File

@@ -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[],
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[],
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;
}

View File

@@ -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));
rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
/*
* 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 {
_swrast_read_rgba_span(ctx, rb, n, span->x, span->y, dest);
}
#if CHAN_BITS == 8
/* 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++) {
rgba32[i] = (rgba32[i] & srcMask) | (dest32[i] & dstMask);
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];
}
#endif
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;