-/* $Id: blend.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+/* $Id: blend.c,v 1.15 2000/05/30 02:28:03 brianp Exp $ */
/*
* Mesa 3-D graphics library
- * Version: 3.1
+ * Version: 3.3
*
* Copyright (C) 1999 Brian Paul All Rights Reserved.
*
#ifdef PC_HEADER
#include "all.h"
#else
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
+#include "glheader.h"
#include "alphabuf.h"
#include "blend.h"
#include "context.h"
#include "pb.h"
#include "span.h"
#include "types.h"
-#ifdef XFree86Server
-#include "GL/xf86glx.h"
-#endif
#endif
-void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+void
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
{
+ GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc");
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
gl_lookup_enum_by_nr(dfactor));
switch (sfactor) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_DST_COLOR:
}
switch (dfactor) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
}
-/* GL_INGR_blend_func_separate */
+/* GL_EXT_blend_func_separate */
void
-gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA )
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
{
+ GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate");
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
gl_lookup_enum_by_nr(dfactorA));
switch (sfactorRGB) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_DST_COLOR:
ctx->Color.BlendSrcRGB = sfactorRGB;
break;
default:
- gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" );
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)");
return;
}
switch (dfactorRGB) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
ctx->Color.BlendDstRGB = dfactorRGB;
break;
default:
- gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" );
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)");
return;
}
switch (sfactorA) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_DST_COLOR:
ctx->Color.BlendSrcA = sfactorA;
break;
default:
- gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" );
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)");
return;
}
switch (dfactorA) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ if (!ctx->Extensions.HaveBlendSquare) {
+ gl_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)");
+ return;
+ }
+ /* fall-through */
case GL_ZERO:
case GL_ONE:
case GL_SRC_COLOR:
ctx->Color.BlendFunc = NULL;
ctx->NewState |= NEW_RASTER_OPS;
+
+ if (ctx->Driver.BlendFuncSeparate) {
+ (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA );
+ }
}
/* This is really an extension function! */
-void gl_BlendEquation( GLcontext *ctx, GLenum mode )
+void
+_mesa_BlendEquation( GLenum mode )
{
+ GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation");
if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
fprintf(stderr, "glBlendEquation %s\n",
gl_lookup_enum_by_nr(mode));
-
switch (mode) {
case GL_MIN_EXT:
case GL_MAX_EXT:
ctx->Color.BlendFunc = NULL;
ctx->NewState |= NEW_RASTER_OPS;
+
+ if (ctx->Driver.BlendEquation)
+ ctx->Driver.BlendEquation( ctx, mode );
}
-void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
- GLclampf blue, GLclampf alpha )
+void
+_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
{
- ctx->Color.BlendColor[0] = CLAMP( red, 0.0, 1.0 );
- ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
- ctx->Color.BlendColor[2] = CLAMP( blue, 0.0, 1.0 );
- ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
+ GET_CURRENT_CONTEXT(ctx);
+ ctx->Color.BlendColor[0] = CLAMP( red, 0.0F, 1.0F );
+ ctx->Color.BlendColor[1] = CLAMP( green, 0.0F, 1.0F );
+ ctx->Color.BlendColor[2] = CLAMP( blue, 0.0F, 1.0F );
+ ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0F, 1.0F );
}
-
+#ifdef USE_MMX_ASM
+#define _BLENDAPI _ASMAPI
+#else
+#define _BLENDAPI
+#endif
/*
* Common transparency blending mode.
*/
-static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
for (i=0;i<n;i++) {
if (mask[i]) {
- GLint t = rgba[i][ACOMP]; /* t in [0,255] */
+ const GLint t = rgba[i][ACOMP]; /* t in [0,255] */
if (t == 0) {
+ /* 0% alpha */
rgba[i][RCOMP] = dest[i][RCOMP];
rgba[i][GCOMP] = dest[i][GCOMP];
rgba[i][BCOMP] = dest[i][BCOMP];
rgba[i][ACOMP] = dest[i][ACOMP];
}
- else if (t == 255) {
- /* no-op */
+ else if (t == CHAN_MAX) {
+ /* 100% alpha, no-op */
}
else {
- GLint s = 255 - t;
- GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
- GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
- GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
- GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
- ASSERT(r <= 255);
- ASSERT(g <= 255);
- ASSERT(b <= 255);
- ASSERT(a <= 255);
- rgba[i][RCOMP] = r;
- rgba[i][GCOMP] = g;
- rgba[i][BCOMP] = b;
- rgba[i][ACOMP] = a;
+ const GLint s = CHAN_MAX - t;
+ const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
+ const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
+ const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
+ const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
+ ASSERT(r <= CHAN_MAX);
+ ASSERT(g <= CHAN_MAX);
+ ASSERT(b <= CHAN_MAX);
+ ASSERT(a <= CHAN_MAX);
+ rgba[i][RCOMP] = (GLubyte) r;
+ rgba[i][GCOMP] = (GLubyte) g;
+ rgba[i][BCOMP] = (GLubyte) b;
+ rgba[i][ACOMP] = (GLubyte) a;
}
}
}
/*
* Add src and dest.
*/
-static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
- rgba[i][RCOMP] = MIN2( r, 255 );
- rgba[i][GCOMP] = MIN2( g, 255 );
- rgba[i][BCOMP] = MIN2( b, 255 );
- rgba[i][ACOMP] = MIN2( a, 255 );
+ rgba[i][RCOMP] = (GLubyte) MIN2( r, CHAN_MAX );
+ rgba[i][GCOMP] = (GLubyte) MIN2( g, CHAN_MAX );
+ rgba[i][BCOMP] = (GLubyte) MIN2( b, CHAN_MAX );
+ rgba[i][ACOMP] = (GLubyte) MIN2( a, CHAN_MAX );
}
}
}
/*
* Blend min function (for GL_EXT_blend_minmax)
*/
-static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
for (i=0;i<n;i++) {
if (mask[i]) {
- rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
+ rgba[i][RCOMP] = (GLubyte) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
+ rgba[i][GCOMP] = (GLubyte) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
+ rgba[i][BCOMP] = (GLubyte) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
+ rgba[i][ACOMP] = (GLubyte) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
}
}
}
/*
* Blend max function (for GL_EXT_blend_minmax)
*/
-static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
GLuint i;
ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
for (i=0;i<n;i++) {
if (mask[i]) {
- rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
- rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
- rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
- rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
+ rgba[i][RCOMP] = (GLubyte) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
+ rgba[i][GCOMP] = (GLubyte) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
+ rgba[i][BCOMP] = (GLubyte) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
+ rgba[i][ACOMP] = (GLubyte) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
}
}
}
/*
* Modulate: result = src * dest
*/
-static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
GLuint i;
(void) ctx;
GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
- rgba[i][RCOMP] = r;
- rgba[i][GCOMP] = g;
- rgba[i][BCOMP] = b;
- rgba[i][ACOMP] = a;
+ rgba[i][RCOMP] = (GLubyte) r;
+ rgba[i][GCOMP] = (GLubyte) g;
+ rgba[i][BCOMP] = (GLubyte) b;
+ rgba[i][ACOMP] = (GLubyte) a;
}
}
}
* In/Out: rgba - the incoming and modified pixels
* Input: dest - the pixels from the dest color buffer
*/
-static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
- GLubyte rgba[][4], CONST GLubyte dest[][4] )
+static void _BLENDAPI
+blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
{
- GLfloat rscale = 1.0F / 255.0F;
- GLfloat gscale = 1.0F / 255.0F;
- GLfloat bscale = 1.0F / 255.0F;
- GLfloat ascale = 1.0F / 255.0F;
+ GLfloat rscale = 1.0F / CHAN_MAXF;
+ GLfloat gscale = 1.0F / CHAN_MAXF;
+ GLfloat bscale = 1.0F / CHAN_MAXF;
+ GLfloat ascale = 1.0F / CHAN_MAXF;
GLuint i;
for (i=0;i<n;i++) {
sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
break;
case GL_SRC_ALPHA_SATURATE:
- if (As < 1.0F - (GLfloat) Ad * ascale) {
+ if (As < CHAN_MAX - Ad) {
sR = sG = sB = (GLfloat) As * ascale;
}
else {
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 = (GLfloat) Rs * rscale;
+ sG = (GLfloat) Gs * gscale;
+ sB = (GLfloat) Bs * bscale;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+ sR = 1.0F - (GLfloat) Rs * rscale;
+ sG = 1.0F - (GLfloat) Gs * gscale;
+ sB = 1.0F - (GLfloat) Bs * bscale;
+ break;
default:
/* this should never happen */
gl_problem(ctx, "Bad blend source RGB factor in do_blend");
case GL_ONE_MINUS_CONSTANT_ALPHA:
sA = 1.0F - ctx->Color.BlendColor[3];
break;
+ case GL_SRC_COLOR: /* GL_NV_blend_square */
+ sA = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
+ sA = 1.0F - (GLfloat) As * ascale;
+ break;
default:
/* this should never happen */
+ sA = 0.0F;
gl_problem(ctx, "Bad blend source A factor in do_blend");
}
case GL_ONE_MINUS_CONSTANT_ALPHA:
dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
break;
+ case GL_DST_COLOR: /* GL_NV_blend_square */
+ dR = (GLfloat) Rd * rscale;
+ dG = (GLfloat) Gd * gscale;
+ dB = (GLfloat) Bd * bscale;
+ break;
+ case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+ dR = 1.0F - (GLfloat) Rd * rscale;
+ dG = 1.0F - (GLfloat) Gd * gscale;
+ dB = 1.0F - (GLfloat) Bd * bscale;
+ break;
default:
/* this should never happen */
+ dR = dG = dB = 0.0F;
gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
}
case GL_ONE_MINUS_CONSTANT_ALPHA:
dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
break;
+ case GL_DST_COLOR: /* GL_NV_blend_square */
+ dA = (GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
+ dA = 1.0F - (GLfloat) Ad * ascale;
+ break;
default:
/* this should never happen */
+ dA = 0.0F;
gl_problem(ctx, "Bad blend dest A factor in do_blend");
return;
}
b = Bd * dB - Bs * sB;
a = Ad * dA - As * sA;
}
+ else {
+ /* should never get here */
+ r = g = b = a = 0.0F; /* silence uninitialized var warning */
+ gl_problem(ctx, "unexpected BlendEquation in blend_general()");
+ }
/* final clamping */
- rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F );
- rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F );
- rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F );
- rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F );
+ rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
+ rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
+ rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
+ rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
}
}
}
*/
if (gl_x86_cpu_features & GL_CPU_MMX) {
gl_mmx_set_blend_function (ctx);
- } else
+ }
+ else
#endif
if (srcRGB != srcA || dstRGB != dstA) {
ctx->Color.BlendFunc = blend_general;
* mask - boolean mask indicating which pixels to blend.
* In/Out: rgba - pixel values
*/
-void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
- GLubyte rgba[][4], const GLubyte mask[] )
+void
+_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4], const GLubyte mask[] )
{
GLubyte dest[MAX_WIDTH][4];
}
/* Read span of current frame buffer pixels */
- gl_read_rgba_span( ctx, n, x, y, dest );
+ gl_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
if (!ctx->Color.BlendFunc)
set_blend_function(ctx);
* mask - boolean mask indicating which pixels to blend.
* In/Out: rgba - pixel values
*/
-void gl_blend_pixels( GLcontext *ctx,
- GLuint n, const GLint x[], const GLint y[],
- GLubyte rgba[][4], const GLubyte mask[] )
+void
+_mesa_blend_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
{
GLubyte dest[PB_SIZE][4];
/* Read pixels from current color buffer */
(*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
-
if (ctx->RasterMask & ALPHABUF_BIT) {
- gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
- }
- else {
- GLuint i;
- for (i=0; i<n; i++) {
- dest[i][ACOMP] = 255;
- }
+ _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask );
}
if (!ctx->Color.BlendFunc)