aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src')
-rw-r--r--mesalib/src/glsl/ast_to_hir.cpp39
-rw-r--r--mesalib/src/glsl/ir.cpp5
-rw-r--r--mesalib/src/glsl/ir.h8
-rw-r--r--mesalib/src/glsl/ir_clone.cpp1
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c10
-rw-r--r--mesalib/src/mesa/drivers/dri/common/dri_util.c4
-rw-r--r--mesalib/src/mesa/drivers/windows/gdi/wmesa.c9
-rw-r--r--mesalib/src/mesa/main/attrib.c8
-rw-r--r--mesalib/src/mesa/main/blend.c1665
-rw-r--r--mesalib/src/mesa/main/clear.c82
-rw-r--r--mesalib/src/mesa/main/colormac.h11
-rw-r--r--mesalib/src/mesa/main/dd.h3
-rw-r--r--mesalib/src/mesa/main/get.c11
-rw-r--r--mesalib/src/mesa/main/image.c8
-rw-r--r--mesalib/src/mesa/main/mtypes.h32
-rw-r--r--mesalib/src/mesa/main/uniforms.c22
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_clear.c14
-rw-r--r--mesalib/src/mesa/state_tracker/st_format.c5
-rw-r--r--mesalib/src/mesa/swrast/s_blend.c2024
-rw-r--r--mesalib/src/mesa/swrast/s_clear.c41
20 files changed, 2006 insertions, 1996 deletions
diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index 484786c5f..ce29d5a87 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -2120,25 +2120,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
var->depth_layout = ir_depth_layout_unchanged;
else
var->depth_layout = ir_depth_layout_none;
-
- /* From page 46 (page 52 of the PDF) of the GLSL ES specification:
- *
- * "Array variables are l-values and may be passed to parameters
- * declared as out or inout. However, they may not be used as
- * the target of an assignment."
- *
- * From page 32 (page 38 of the PDF) of the GLSL 1.10 spec:
- *
- * "Other binary or unary expressions, non-dereferenced arrays,
- * function names, swizzles with repeated fields, and constants
- * cannot be l-values."
- *
- * So we only mark 1.10 as non-lvalues, and check for array
- * assignment in 100 specifically in do_assignment.
- */
- if (var->type->is_array() && state->language_version != 110) {
- var->array_lvalue = true;
- }
}
/**
@@ -2953,6 +2934,26 @@ ast_parameter_declarator::hir(exec_list *instructions,
type = glsl_type::error_type;
}
+ /* From page 39 (page 45 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "When calling a function, expressions that do not evaluate to
+ * l-values cannot be passed to parameters declared as out or inout."
+ *
+ * From page 32 (page 38 of the PDF) of the GLSL 1.10 spec:
+ *
+ * "Other binary or unary expressions, non-dereferenced arrays,
+ * function names, swizzles with repeated fields, and constants
+ * cannot be l-values."
+ *
+ * So for GLSL 1.10, passing an array as an out or inout parameter is not
+ * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES.
+ */
+ if ((var->mode == ir_var_inout || var->mode == ir_var_out)
+ && type->is_array() && state->language_version == 110) {
+ _mesa_glsl_error(&loc, state, "Arrays cannot be out or inout parameters in GLSL 1.10");
+ type = glsl_type::error_type;
+ }
+
instructions->push_tail(var);
/* Parameter declarations do not have r-values.
diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp
index 41ed4f114..d6594cd9a 100644
--- a/mesalib/src/glsl/ir.cpp
+++ b/mesalib/src/glsl/ir.cpp
@@ -1105,9 +1105,6 @@ ir_dereference::is_lvalue() const
if ((var == NULL) || var->read_only)
return false;
- if (this->type->is_array() && !var->array_lvalue)
- return false;
-
/* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec:
*
* "Samplers cannot be treated as l-values; hence cannot be used
@@ -1323,7 +1320,7 @@ ir_swizzle::variable_referenced() const
ir_variable::ir_variable(const struct glsl_type *type, const char *name,
ir_variable_mode mode)
: max_array_access(0), read_only(false), centroid(false), invariant(false),
- mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
+ mode(mode), interpolation(ir_var_smooth)
{
this->ir_type = ir_type_variable;
this->type = type;
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 2e899f3ed..cc4e68002 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -346,14 +346,6 @@ public:
unsigned interpolation:2;
/**
- * Flag that the whole array is assignable
- *
- * In GLSL 1.20 and later whole arrays are assignable (and comparable for
- * equality). This flag enables this behavior.
- */
- unsigned array_lvalue:1;
-
- /**
* \name ARB_fragment_coord_conventions
* @{
*/
diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp
index f0757365d..c1befa95c 100644
--- a/mesalib/src/glsl/ir_clone.cpp
+++ b/mesalib/src/glsl/ir_clone.cpp
@@ -47,7 +47,6 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
var->centroid = this->centroid;
var->invariant = this->invariant;
var->interpolation = this->interpolation;
- var->array_lvalue = this->array_lvalue;
var->location = this->location;
var->warn_extension = this->warn_extension;
var->origin_upper_left = this->origin_upper_left;
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index 2ebcd35bd..482bd98a2 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1569,10 +1569,10 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers)
/* vertex colors */
for (i = 0; i < 4; i++) {
- verts[i].r = ctx->Color.ClearColorUnclamped[0];
- verts[i].g = ctx->Color.ClearColorUnclamped[1];
- verts[i].b = ctx->Color.ClearColorUnclamped[2];
- verts[i].a = ctx->Color.ClearColorUnclamped[3];
+ verts[i].r = ctx->Color.ClearColor.f[0];
+ verts[i].g = ctx->Color.ClearColor.f[1];
+ verts[i].b = ctx->Color.ClearColor.f[2];
+ verts[i].a = ctx->Color.ClearColor.f[3];
}
/* upload new vertex data */
@@ -1679,7 +1679,7 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers)
_mesa_UseProgramObjectARB(clear->ShaderProg);
_mesa_Uniform4fvARB(clear->ColorLocation, 1,
- ctx->Color.ClearColorUnclamped);
+ ctx->Color.ClearColor.f);
_mesa_BindVertexArray(clear->ArrayObj);
_mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO);
diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c
index 6d6401934..cdd413737 100644
--- a/mesalib/src/mesa/drivers/dri/common/dri_util.c
+++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c
@@ -816,8 +816,10 @@ driCreateNewScreen(int scrn,
(void) loaderPrivate;
- if (driDriverAPI.InitScreen == NULL)
+ if (driDriverAPI.InitScreen == NULL) {
+ __driUtilMessage("driver does not support DRI1");
return NULL;
+ }
psp = calloc(1, sizeof *psp);
if (!psp)
diff --git a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
index 35a150d06..14d15ed6c 100644
--- a/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/mesalib/src/mesa/drivers/windows/gdi/wmesa.c
@@ -249,14 +249,15 @@ static void wmesa_flush(struct gl_context *ctx)
/*
* Set the color used to clear the color buffer.
*/
-static void clear_color(struct gl_context *ctx, const GLfloat color[4])
+static void clear_color(struct gl_context *ctx,
+ const union gl_color_union color)
{
WMesaContext pwc = wmesa_context(ctx);
GLubyte col[3];
- CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
- CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
- CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(col[0], color.f[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(col[1], color.f[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(col[2], color.f[2]);
pwc->clearColorRef = RGB(col[0], col[1], col[2]);
DeleteObject(pwc->clearPen);
DeleteObject(pwc->clearBrush);
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index 573100402..9767740a3 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -884,10 +884,10 @@ _mesa_PopAttrib(void)
color = (const struct gl_colorbuffer_attrib *) attr->data;
_mesa_ClearIndex((GLfloat) color->ClearIndex);
- _mesa_ClearColor(color->ClearColorUnclamped[0],
- color->ClearColorUnclamped[1],
- color->ClearColorUnclamped[2],
- color->ClearColorUnclamped[3]);
+ _mesa_ClearColor(color->ClearColor.f[0],
+ color->ClearColor.f[1],
+ color->ClearColor.f[2],
+ color->ClearColor.f[3]);
_mesa_IndexMask(color->IndexMask);
if (!ctx->Extensions.EXT_draw_buffers2) {
_mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0),
diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c
index 94a457f58..4214a661b 100644
--- a/mesalib/src/mesa/main/blend.c
+++ b/mesalib/src/mesa/main/blend.c
@@ -1,833 +1,832 @@
-/**
- * \file blend.c
- * Blending operations.
- */
-
-/*
- * Mesa 3-D graphics library
- * Version: 6.5.1
- *
- * 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-
-#include "glheader.h"
-#include "blend.h"
-#include "context.h"
-#include "enums.h"
-#include "macros.h"
-#include "mtypes.h"
-
-
-
-/**
- * Check if given blend source factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_src_factor(const struct gl_context *ctx, GLenum factor)
-{
- switch (factor) {
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- return ctx->Extensions.NV_blend_square;
- case GL_ZERO:
- case GL_ONE:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if given blend destination factor is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_dst_factor(const struct gl_context *ctx, GLenum factor)
-{
- switch (factor) {
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- return ctx->Extensions.NV_blend_square;
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return GL_TRUE;
- default:
- return GL_FALSE;
- }
-}
-
-
-/**
- * Check if src/dest RGB/A blend factors are legal. If not generate
- * a GL error.
- * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
- */
-static GLboolean
-validate_blend_factors(struct gl_context *ctx, const char *func,
- GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA)
-{
- if (!legal_src_factor(ctx, sfactorRGB)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(sfactorRGB = %s)", func,
- _mesa_lookup_enum_by_nr(sfactorRGB));
- return GL_FALSE;
- }
-
- if (!legal_dst_factor(ctx, dfactorRGB)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(dfactorRGB = %s)", func,
- _mesa_lookup_enum_by_nr(dfactorRGB));
- return GL_FALSE;
- }
-
- if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(sfactorA = %s)", func,
- _mesa_lookup_enum_by_nr(sfactorA));
- return GL_FALSE;
- }
-
- if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "%s(dfactorA = %s)", func,
- _mesa_lookup_enum_by_nr(dfactorA));
- return GL_FALSE;
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Specify the blending operation.
- *
- * \param sfactor source factor operator.
- * \param dfactor destination factor operator.
- *
- * \sa glBlendFunc, glBlendFuncSeparateEXT
- */
-void GLAPIENTRY
-_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
-{
- _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set the separate blend source/dest factors for all draw buffers.
- *
- * \param sfactorRGB RGB source factor operator.
- * \param dfactorRGB RGB destination factor operator.
- * \param sfactorA alpha source factor operator.
- * \param dfactorA alpha destination factor operator.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
- _mesa_lookup_enum_by_nr(sfactorRGB),
- _mesa_lookup_enum_by_nr(dfactorRGB),
- _mesa_lookup_enum_by_nr(sfactorA),
- _mesa_lookup_enum_by_nr(dfactorA));
-
- if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
- sfactorRGB, dfactorRGB,
- sfactorA, dfactorA)) {
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
- ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
- ctx->Color.Blend[buf].SrcA != sfactorA ||
- ctx->Color.Blend[buf].DstA != dfactorA) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
-
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
- ctx->Color.Blend[buf].DstRGB = dfactorRGB;
- ctx->Color.Blend[buf].SrcA = sfactorA;
- ctx->Color.Blend[buf].DstA = dfactorA;
- }
- ctx->Color._BlendFuncPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendFuncSeparate) {
- ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
- sfactorA, dfactorA);
- }
-}
-
-
-#if _HAVE_FULL_GL
-
-
-/**
- * Set blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
-{
- _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
-}
-
-
-/**
- * Set separate blend source/dest factors for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
- GLenum sfactorA, GLenum dfactorA)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (!ctx->Extensions.ARB_draw_buffers_blend) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
- return;
- }
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
- sfactorRGB, dfactorRGB,
- sfactorA, dfactorA)) {
- return;
- }
-
- if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
- ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
- ctx->Color.Blend[buf].SrcA == sfactorA &&
- ctx->Color.Blend[buf].DstA == dfactorA)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
-
- ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
- ctx->Color.Blend[buf].DstRGB = dfactorRGB;
- ctx->Color.Blend[buf].SrcA = sfactorA;
- ctx->Color.Blend[buf].DstA = dfactorA;
- ctx->Color._BlendFuncPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendFuncSeparatei) {
- ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
- sfactorA, dfactorA);
- }
-}
-
-
-/**
- * Check if given blend equation is legal.
- * \return GL_TRUE if legal, GL_FALSE otherwise.
- */
-static GLboolean
-legal_blend_equation(const struct gl_context *ctx,
- GLenum mode, GLboolean is_separate)
-{
- switch (mode) {
- case GL_FUNC_ADD:
- return GL_TRUE;
- case GL_MIN:
- case GL_MAX:
- return ctx->Extensions.EXT_blend_minmax;
- case GL_LOGIC_OP:
- /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
- */
- return ctx->Extensions.EXT_blend_logic_op && !is_separate;
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- return ctx->Extensions.EXT_blend_subtract;
- default:
- return GL_FALSE;
- }
-}
-
-
-/* This is really an extension function! */
-void GLAPIENTRY
-_mesa_BlendEquation( GLenum mode )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquation(%s)\n",
- _mesa_lookup_enum_by_nr(mode));
-
- if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].EquationRGB != mode ||
- ctx->Color.Blend[buf].EquationA != mode) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].EquationRGB = mode;
- ctx->Color.Blend[buf].EquationA = mode;
- }
- ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendEquationSeparate)
- (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
-}
-
-
-/**
- * Set blend equation for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendEquationi(GLuint buf, GLenum mode)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
- buf, _mesa_lookup_enum_by_nr(mode));
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
- return;
- }
-
- if (ctx->Color.Blend[buf].EquationRGB == mode &&
- ctx->Color.Blend[buf].EquationA == mode)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.Blend[buf].EquationRGB = mode;
- ctx->Color.Blend[buf].EquationA = mode;
- ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendEquationSeparatei)
- ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
-}
-
-
-void GLAPIENTRY
-_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
-{
- GLuint buf, numBuffers;
- GLboolean changed;
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
- _mesa_lookup_enum_by_nr(modeRGB),
- _mesa_lookup_enum_by_nr(modeA));
-
- if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glBlendEquationSeparateEXT not supported by driver");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
- return;
- }
-
- numBuffers = ctx->Extensions.ARB_draw_buffers_blend
- ? ctx->Const.MaxDrawBuffers : 1;
-
- changed = GL_FALSE;
- for (buf = 0; buf < numBuffers; buf++) {
- if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
- ctx->Color.Blend[buf].EquationA != modeA) {
- changed = GL_TRUE;
- break;
- }
- }
- if (!changed)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- for (buf = 0; buf < numBuffers; buf++) {
- ctx->Color.Blend[buf].EquationRGB = modeRGB;
- ctx->Color.Blend[buf].EquationA = modeA;
- }
- ctx->Color._BlendEquationPerBuffer = GL_FALSE;
-
- if (ctx->Driver.BlendEquationSeparate)
- ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
-}
-
-
-/**
- * Set separate blend equations for one color buffer/target.
- */
-void GLAPIENTRY
-_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
- _mesa_lookup_enum_by_nr(modeRGB),
- _mesa_lookup_enum_by_nr(modeA));
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
- buf);
- return;
- }
-
- if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
- return;
- }
-
- if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
- return;
- }
-
- if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
- ctx->Color.Blend[buf].EquationA == modeA)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.Blend[buf].EquationRGB = modeRGB;
- ctx->Color.Blend[buf].EquationA = modeA;
- ctx->Color._BlendEquationPerBuffer = GL_TRUE;
-
- if (ctx->Driver.BlendEquationSeparatei)
- ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
-}
-
-
-
-#endif /* _HAVE_FULL_GL */
-
-
-/**
- * Set the blending color.
- *
- * \param red red color component.
- * \param green green color component.
- * \param blue blue color component.
- * \param alpha alpha color component.
- *
- * \sa glBlendColor().
- *
- * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
- * change, flushes the vertices and notifies the driver via
- * dd_function_table::BlendColor callback.
- */
-void GLAPIENTRY
-_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
-{
- GLfloat tmp[4];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- tmp[0] = red;
- tmp[1] = green;
- tmp[2] = blue;
- tmp[3] = alpha;
-
- if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
-
- ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
- ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
- ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
- ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
-
- if (ctx->Driver.BlendColor)
- (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor);
-}
-
-
-/**
- * Specify the alpha test function.
- *
- * \param func alpha comparison function.
- * \param ref reference value.
- *
- * Verifies the parameters and updates gl_colorbuffer_attrib.
- * On a change, flushes the vertices and notifies the driver via
- * dd_function_table::AlphaFunc callback.
- */
-void GLAPIENTRY
-_mesa_AlphaFunc( GLenum func, GLclampf ref )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
- _mesa_lookup_enum_by_nr(func), ref);
-
- switch (func) {
- case GL_NEVER:
- case GL_LESS:
- case GL_EQUAL:
- case GL_LEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- case GL_GEQUAL:
- case GL_ALWAYS:
- if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
- return; /* no change */
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.AlphaFunc = func;
- ctx->Color.AlphaRefUnclamped = ref;
- ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
-
- if (ctx->Driver.AlphaFunc)
- ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
- return;
-
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
- return;
- }
-}
-
-
-/**
- * Specify a logic pixel operation for color index rendering.
- *
- * \param opcode operation.
- *
- * Verifies that \p opcode is a valid enum and updates
-gl_colorbuffer_attrib::LogicOp.
- * On a change, flushes the vertices and notifies the driver via the
- * dd_function_table::LogicOpcode callback.
- */
-void GLAPIENTRY
-_mesa_LogicOp( GLenum opcode )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
-
- switch (opcode) {
- case GL_CLEAR:
- case GL_SET:
- case GL_COPY:
- case GL_COPY_INVERTED:
- case GL_NOOP:
- case GL_INVERT:
- case GL_AND:
- case GL_NAND:
- case GL_OR:
- case GL_NOR:
- case GL_XOR:
- case GL_EQUIV:
- case GL_AND_REVERSE:
- case GL_AND_INVERTED:
- case GL_OR_REVERSE:
- case GL_OR_INVERTED:
- break;
- default:
- _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
- return;
- }
-
- if (ctx->Color.LogicOp == opcode)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.LogicOp = opcode;
-
- if (ctx->Driver.LogicOpcode)
- ctx->Driver.LogicOpcode( ctx, opcode );
-}
-
-#if _HAVE_FULL_GL
-void GLAPIENTRY
-_mesa_IndexMask( GLuint mask )
-{
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (ctx->Color.IndexMask == mask)
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.IndexMask = mask;
-}
-#endif
-
-
-/**
- * Enable or disable writing of frame buffer color components.
- *
- * \param red whether to mask writing of the red color component.
- * \param green whether to mask writing of the green color component.
- * \param blue whether to mask writing of the blue color component.
- * \param alpha whether to mask writing of the alpha color component.
- *
- * \sa glColorMask().
- *
- * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
- * change, flushes the vertices and notifies the driver via the
- * dd_function_table::ColorMask callback.
- */
-void GLAPIENTRY
-_mesa_ColorMask( GLboolean red, GLboolean green,
- GLboolean blue, GLboolean alpha )
-{
- GET_CURRENT_CONTEXT(ctx);
- GLubyte tmp[4];
- GLuint i;
- GLboolean flushed;
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
- red, green, blue, alpha);
-
- /* Shouldn't have any information about channel depth in core mesa
- * -- should probably store these as the native booleans:
- */
- tmp[RCOMP] = red ? 0xff : 0x0;
- tmp[GCOMP] = green ? 0xff : 0x0;
- tmp[BCOMP] = blue ? 0xff : 0x0;
- tmp[ACOMP] = alpha ? 0xff : 0x0;
-
- flushed = GL_FALSE;
- for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
- if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
- if (!flushed) {
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- }
- flushed = GL_TRUE;
- COPY_4UBV(ctx->Color.ColorMask[i], tmp);
- }
- }
-
- if (ctx->Driver.ColorMask)
- ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
-}
-
-
-/**
- * For GL_EXT_draw_buffers2 and GL3
- */
-void GLAPIENTRY
-_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
- GLboolean blue, GLboolean alpha )
-{
- GLubyte tmp[4];
- GET_CURRENT_CONTEXT(ctx);
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
- buf, red, green, blue, alpha);
-
- if (buf >= ctx->Const.MaxDrawBuffers) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
- return;
- }
-
- /* Shouldn't have any information about channel depth in core mesa
- * -- should probably store these as the native booleans:
- */
- tmp[RCOMP] = red ? 0xff : 0x0;
- tmp[GCOMP] = green ? 0xff : 0x0;
- tmp[BCOMP] = blue ? 0xff : 0x0;
- tmp[ACOMP] = alpha ? 0xff : 0x0;
-
- if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
- return;
-
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
-
- if (ctx->Driver.ColorMaskIndexed)
- ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
-}
-
-
-void GLAPIENTRY
-_mesa_ClampColorARB(GLenum target, GLenum clamp)
-{
- GET_CURRENT_CONTEXT(ctx);
-
- ASSERT_OUTSIDE_BEGIN_END(ctx);
-
- if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
- _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
- return;
- }
-
- switch (target) {
- case GL_CLAMP_VERTEX_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_LIGHT);
- ctx->Light.ClampVertexColor = clamp;
- break;
- case GL_CLAMP_FRAGMENT_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
- ctx->Color.ClampFragmentColor = clamp;
- break;
- case GL_CLAMP_READ_COLOR_ARB:
- FLUSH_VERTICES(ctx, _NEW_COLOR);
- ctx->Color.ClampReadColor = clamp;
- break;
- default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
- return;
- }
-}
-
-
-
-
-/**********************************************************************/
-/** \name Initialization */
-/*@{*/
-
-/**
- * Initialization of the context's Color attribute group.
- *
- * \param ctx GL context.
- *
- * Initializes the related fields in the context color attribute group,
- * __struct gl_contextRec::Color.
- */
-void _mesa_init_color( struct gl_context * ctx )
-{
- GLuint i;
-
- /* Color buffer group */
- ctx->Color.IndexMask = ~0u;
- memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
- ctx->Color.ClearIndex = 0;
- ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
- ASSIGN_4V( ctx->Color.ClearColorUnclamped, 0, 0, 0, 0 );
- ctx->Color.AlphaEnabled = GL_FALSE;
- ctx->Color.AlphaFunc = GL_ALWAYS;
- ctx->Color.AlphaRef = 0;
- ctx->Color.BlendEnabled = 0x0;
- for (i = 0; i < Elements(ctx->Color.Blend); i++) {
- ctx->Color.Blend[i].SrcRGB = GL_ONE;
- ctx->Color.Blend[i].DstRGB = GL_ZERO;
- ctx->Color.Blend[i].SrcA = GL_ONE;
- ctx->Color.Blend[i].DstA = GL_ZERO;
- ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
- ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
- }
- ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
- ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
- ctx->Color.IndexLogicOpEnabled = GL_FALSE;
- ctx->Color.ColorLogicOpEnabled = GL_FALSE;
- ctx->Color._LogicOpEnabled = GL_FALSE;
- ctx->Color.LogicOp = GL_COPY;
- ctx->Color.DitherFlag = GL_TRUE;
-
- if (ctx->Visual.doubleBufferMode) {
- ctx->Color.DrawBuffer[0] = GL_BACK;
- }
- else {
- ctx->Color.DrawBuffer[0] = GL_FRONT;
- }
-
- ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
- ctx->Color._ClampFragmentColor = GL_TRUE;
- ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
- ctx->Color._ClampReadColor = GL_TRUE;
-}
-
-/*@}*/
+/**
+ * \file blend.c
+ * Blending operations.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.1
+ *
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#include "glheader.h"
+#include "blend.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "mtypes.h"
+
+
+
+/**
+ * Check if given blend source factor is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_src_factor(const struct gl_context *ctx, GLenum factor)
+{
+ switch (factor) {
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ return ctx->Extensions.NV_blend_square;
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if given blend destination factor is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_dst_factor(const struct gl_context *ctx, GLenum factor)
+{
+ switch (factor) {
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ return ctx->Extensions.NV_blend_square;
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Check if src/dest RGB/A blend factors are legal. If not generate
+ * a GL error.
+ * \return GL_TRUE if factors are legal, GL_FALSE otherwise.
+ */
+static GLboolean
+validate_blend_factors(struct gl_context *ctx, const char *func,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ if (!legal_src_factor(ctx, sfactorRGB)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(sfactorRGB = %s)", func,
+ _mesa_lookup_enum_by_nr(sfactorRGB));
+ return GL_FALSE;
+ }
+
+ if (!legal_dst_factor(ctx, dfactorRGB)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(dfactorRGB = %s)", func,
+ _mesa_lookup_enum_by_nr(dfactorRGB));
+ return GL_FALSE;
+ }
+
+ if (sfactorA != sfactorRGB && !legal_src_factor(ctx, sfactorA)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(sfactorA = %s)", func,
+ _mesa_lookup_enum_by_nr(sfactorA));
+ return GL_FALSE;
+ }
+
+ if (dfactorA != dfactorRGB && !legal_dst_factor(ctx, dfactorA)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "%s(dfactorA = %s)", func,
+ _mesa_lookup_enum_by_nr(dfactorA));
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Specify the blending operation.
+ *
+ * \param sfactor source factor operator.
+ * \param dfactor destination factor operator.
+ *
+ * \sa glBlendFunc, glBlendFuncSeparateEXT
+ */
+void GLAPIENTRY
+_mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
+{
+ _mesa_BlendFuncSeparateEXT(sfactor, dfactor, sfactor, dfactor);
+}
+
+
+/**
+ * Set the separate blend source/dest factors for all draw buffers.
+ *
+ * \param sfactorRGB RGB source factor operator.
+ * \param dfactorRGB RGB destination factor operator.
+ * \param sfactorA alpha source factor operator.
+ * \param dfactorA alpha destination factor operator.
+ */
+void GLAPIENTRY
+_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
+{
+ GLuint buf, numBuffers;
+ GLboolean changed;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBlendFuncSeparate %s %s %s %s\n",
+ _mesa_lookup_enum_by_nr(sfactorRGB),
+ _mesa_lookup_enum_by_nr(dfactorRGB),
+ _mesa_lookup_enum_by_nr(sfactorA),
+ _mesa_lookup_enum_by_nr(dfactorA));
+
+ if (!validate_blend_factors(ctx, "glBlendFuncSeparate",
+ sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA)) {
+ return;
+ }
+
+ numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+ ? ctx->Const.MaxDrawBuffers : 1;
+
+ changed = GL_FALSE;
+ for (buf = 0; buf < numBuffers; buf++) {
+ if (ctx->Color.Blend[buf].SrcRGB != sfactorRGB ||
+ ctx->Color.Blend[buf].DstRGB != dfactorRGB ||
+ ctx->Color.Blend[buf].SrcA != sfactorA ||
+ ctx->Color.Blend[buf].DstA != dfactorA) {
+ changed = GL_TRUE;
+ break;
+ }
+ }
+ if (!changed)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+
+ for (buf = 0; buf < numBuffers; buf++) {
+ ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
+ ctx->Color.Blend[buf].DstRGB = dfactorRGB;
+ ctx->Color.Blend[buf].SrcA = sfactorA;
+ ctx->Color.Blend[buf].DstA = dfactorA;
+ }
+ ctx->Color._BlendFuncPerBuffer = GL_FALSE;
+
+ if (ctx->Driver.BlendFuncSeparate) {
+ ctx->Driver.BlendFuncSeparate(ctx, sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA);
+ }
+}
+
+
+#if _HAVE_FULL_GL
+
+
+/**
+ * Set blend source/dest factors for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
+{
+ _mesa_BlendFuncSeparatei(buf, sfactor, dfactor, sfactor, dfactor);
+}
+
+
+/**
+ * Set separate blend source/dest factors for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (!ctx->Extensions.ARB_draw_buffers_blend) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBlendFunc[Separate]i()");
+ return;
+ }
+
+ if (buf >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
+ buf);
+ return;
+ }
+
+ if (!validate_blend_factors(ctx, "glBlendFuncSeparatei",
+ sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA)) {
+ return;
+ }
+
+ if (ctx->Color.Blend[buf].SrcRGB == sfactorRGB &&
+ ctx->Color.Blend[buf].DstRGB == dfactorRGB &&
+ ctx->Color.Blend[buf].SrcA == sfactorA &&
+ ctx->Color.Blend[buf].DstA == dfactorA)
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+
+ ctx->Color.Blend[buf].SrcRGB = sfactorRGB;
+ ctx->Color.Blend[buf].DstRGB = dfactorRGB;
+ ctx->Color.Blend[buf].SrcA = sfactorA;
+ ctx->Color.Blend[buf].DstA = dfactorA;
+ ctx->Color._BlendFuncPerBuffer = GL_TRUE;
+
+ if (ctx->Driver.BlendFuncSeparatei) {
+ ctx->Driver.BlendFuncSeparatei(ctx, buf, sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA);
+ }
+}
+
+
+/**
+ * Check if given blend equation is legal.
+ * \return GL_TRUE if legal, GL_FALSE otherwise.
+ */
+static GLboolean
+legal_blend_equation(const struct gl_context *ctx,
+ GLenum mode, GLboolean is_separate)
+{
+ switch (mode) {
+ case GL_FUNC_ADD:
+ return GL_TRUE;
+ case GL_MIN:
+ case GL_MAX:
+ return ctx->Extensions.EXT_blend_minmax;
+ case GL_LOGIC_OP:
+ /* glBlendEquationSeparate cannot take GL_LOGIC_OP as a parameter.
+ */
+ return ctx->Extensions.EXT_blend_logic_op && !is_separate;
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return ctx->Extensions.EXT_blend_subtract;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/* This is really an extension function! */
+void GLAPIENTRY
+_mesa_BlendEquation( GLenum mode )
+{
+ GLuint buf, numBuffers;
+ GLboolean changed;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBlendEquation(%s)\n",
+ _mesa_lookup_enum_by_nr(mode));
+
+ if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation");
+ return;
+ }
+
+ numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+ ? ctx->Const.MaxDrawBuffers : 1;
+
+ changed = GL_FALSE;
+ for (buf = 0; buf < numBuffers; buf++) {
+ if (ctx->Color.Blend[buf].EquationRGB != mode ||
+ ctx->Color.Blend[buf].EquationA != mode) {
+ changed = GL_TRUE;
+ break;
+ }
+ }
+ if (!changed)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ for (buf = 0; buf < numBuffers; buf++) {
+ ctx->Color.Blend[buf].EquationRGB = mode;
+ ctx->Color.Blend[buf].EquationA = mode;
+ }
+ ctx->Color._BlendEquationPerBuffer = GL_FALSE;
+
+ if (ctx->Driver.BlendEquationSeparate)
+ (*ctx->Driver.BlendEquationSeparate)( ctx, mode, mode );
+}
+
+
+/**
+ * Set blend equation for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendEquationi(GLuint buf, GLenum mode)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBlendEquationi(%u, %s)\n",
+ buf, _mesa_lookup_enum_by_nr(mode));
+
+ if (buf >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBlendFuncSeparatei(buffer=%u)",
+ buf);
+ return;
+ }
+
+ if (!legal_blend_equation(ctx, mode, GL_FALSE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationi");
+ return;
+ }
+
+ if (ctx->Color.Blend[buf].EquationRGB == mode &&
+ ctx->Color.Blend[buf].EquationA == mode)
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.Blend[buf].EquationRGB = mode;
+ ctx->Color.Blend[buf].EquationA = mode;
+ ctx->Color._BlendEquationPerBuffer = GL_TRUE;
+
+ if (ctx->Driver.BlendEquationSeparatei)
+ ctx->Driver.BlendEquationSeparatei(ctx, buf, mode, mode);
+}
+
+
+void GLAPIENTRY
+_mesa_BlendEquationSeparateEXT( GLenum modeRGB, GLenum modeA )
+{
+ GLuint buf, numBuffers;
+ GLboolean changed;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBlendEquationSeparateEXT(%s %s)\n",
+ _mesa_lookup_enum_by_nr(modeRGB),
+ _mesa_lookup_enum_by_nr(modeA));
+
+ if ( (modeRGB != modeA) && !ctx->Extensions.EXT_blend_equation_separate ) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBlendEquationSeparateEXT not supported by driver");
+ return;
+ }
+
+ if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeRGB)");
+ return;
+ }
+
+ if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparateEXT(modeA)");
+ return;
+ }
+
+ numBuffers = ctx->Extensions.ARB_draw_buffers_blend
+ ? ctx->Const.MaxDrawBuffers : 1;
+
+ changed = GL_FALSE;
+ for (buf = 0; buf < numBuffers; buf++) {
+ if (ctx->Color.Blend[buf].EquationRGB != modeRGB ||
+ ctx->Color.Blend[buf].EquationA != modeA) {
+ changed = GL_TRUE;
+ break;
+ }
+ }
+ if (!changed)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ for (buf = 0; buf < numBuffers; buf++) {
+ ctx->Color.Blend[buf].EquationRGB = modeRGB;
+ ctx->Color.Blend[buf].EquationA = modeA;
+ }
+ ctx->Color._BlendEquationPerBuffer = GL_FALSE;
+
+ if (ctx->Driver.BlendEquationSeparate)
+ ctx->Driver.BlendEquationSeparate(ctx, modeRGB, modeA);
+}
+
+
+/**
+ * Set separate blend equations for one color buffer/target.
+ */
+void GLAPIENTRY
+_mesa_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glBlendEquationSeparatei(%u, %s %s)\n", buf,
+ _mesa_lookup_enum_by_nr(modeRGB),
+ _mesa_lookup_enum_by_nr(modeA));
+
+ if (buf >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glBlendEquationSeparatei(buffer=%u)",
+ buf);
+ return;
+ }
+
+ if (!legal_blend_equation(ctx, modeRGB, GL_TRUE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeRGB)");
+ return;
+ }
+
+ if (!legal_blend_equation(ctx, modeA, GL_TRUE)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquationSeparatei(modeA)");
+ return;
+ }
+
+ if (ctx->Color.Blend[buf].EquationRGB == modeRGB &&
+ ctx->Color.Blend[buf].EquationA == modeA)
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.Blend[buf].EquationRGB = modeRGB;
+ ctx->Color.Blend[buf].EquationA = modeA;
+ ctx->Color._BlendEquationPerBuffer = GL_TRUE;
+
+ if (ctx->Driver.BlendEquationSeparatei)
+ ctx->Driver.BlendEquationSeparatei(ctx, buf, modeRGB, modeA);
+}
+
+
+
+#endif /* _HAVE_FULL_GL */
+
+
+/**
+ * Set the blending color.
+ *
+ * \param red red color component.
+ * \param green green color component.
+ * \param blue blue color component.
+ * \param alpha alpha color component.
+ *
+ * \sa glBlendColor().
+ *
+ * Clamps the parameters and updates gl_colorbuffer_attrib::BlendColor. On a
+ * change, flushes the vertices and notifies the driver via
+ * dd_function_table::BlendColor callback.
+ */
+void GLAPIENTRY
+_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
+{
+ GLfloat tmp[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ tmp[0] = red;
+ tmp[1] = green;
+ tmp[2] = blue;
+ tmp[3] = alpha;
+
+ if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
+
+ ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
+ ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
+ ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
+ ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
+
+ if (ctx->Driver.BlendColor)
+ (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor);
+}
+
+
+/**
+ * Specify the alpha test function.
+ *
+ * \param func alpha comparison function.
+ * \param ref reference value.
+ *
+ * Verifies the parameters and updates gl_colorbuffer_attrib.
+ * On a change, flushes the vertices and notifies the driver via
+ * dd_function_table::AlphaFunc callback.
+ */
+void GLAPIENTRY
+_mesa_AlphaFunc( GLenum func, GLclampf ref )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glAlphaFunc(%s, %f)\n",
+ _mesa_lookup_enum_by_nr(func), ref);
+
+ switch (func) {
+ case GL_NEVER:
+ case GL_LESS:
+ case GL_EQUAL:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ case GL_GEQUAL:
+ case GL_ALWAYS:
+ if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
+ return; /* no change */
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.AlphaFunc = func;
+ ctx->Color.AlphaRefUnclamped = ref;
+ ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
+
+ if (ctx->Driver.AlphaFunc)
+ ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
+ return;
+
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" );
+ return;
+ }
+}
+
+
+/**
+ * Specify a logic pixel operation for color index rendering.
+ *
+ * \param opcode operation.
+ *
+ * Verifies that \p opcode is a valid enum and updates
+gl_colorbuffer_attrib::LogicOp.
+ * On a change, flushes the vertices and notifies the driver via the
+ * dd_function_table::LogicOpcode callback.
+ */
+void GLAPIENTRY
+_mesa_LogicOp( GLenum opcode )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glLogicOp(%s)\n", _mesa_lookup_enum_by_nr(opcode));
+
+ switch (opcode) {
+ case GL_CLEAR:
+ case GL_SET:
+ case GL_COPY:
+ case GL_COPY_INVERTED:
+ case GL_NOOP:
+ case GL_INVERT:
+ case GL_AND:
+ case GL_NAND:
+ case GL_OR:
+ case GL_NOR:
+ case GL_XOR:
+ case GL_EQUIV:
+ case GL_AND_REVERSE:
+ case GL_AND_INVERTED:
+ case GL_OR_REVERSE:
+ case GL_OR_INVERTED:
+ break;
+ default:
+ _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
+ return;
+ }
+
+ if (ctx->Color.LogicOp == opcode)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.LogicOp = opcode;
+
+ if (ctx->Driver.LogicOpcode)
+ ctx->Driver.LogicOpcode( ctx, opcode );
+}
+
+#if _HAVE_FULL_GL
+void GLAPIENTRY
+_mesa_IndexMask( GLuint mask )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (ctx->Color.IndexMask == mask)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.IndexMask = mask;
+}
+#endif
+
+
+/**
+ * Enable or disable writing of frame buffer color components.
+ *
+ * \param red whether to mask writing of the red color component.
+ * \param green whether to mask writing of the green color component.
+ * \param blue whether to mask writing of the blue color component.
+ * \param alpha whether to mask writing of the alpha color component.
+ *
+ * \sa glColorMask().
+ *
+ * Sets the appropriate value of gl_colorbuffer_attrib::ColorMask. On a
+ * change, flushes the vertices and notifies the driver via the
+ * dd_function_table::ColorMask callback.
+ */
+void GLAPIENTRY
+_mesa_ColorMask( GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLubyte tmp[4];
+ GLuint i;
+ GLboolean flushed;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glColorMask(%d, %d, %d, %d)\n",
+ red, green, blue, alpha);
+
+ /* Shouldn't have any information about channel depth in core mesa
+ * -- should probably store these as the native booleans:
+ */
+ tmp[RCOMP] = red ? 0xff : 0x0;
+ tmp[GCOMP] = green ? 0xff : 0x0;
+ tmp[BCOMP] = blue ? 0xff : 0x0;
+ tmp[ACOMP] = alpha ? 0xff : 0x0;
+
+ flushed = GL_FALSE;
+ for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) {
+ if (!TEST_EQ_4V(tmp, ctx->Color.ColorMask[i])) {
+ if (!flushed) {
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ }
+ flushed = GL_TRUE;
+ COPY_4UBV(ctx->Color.ColorMask[i], tmp);
+ }
+ }
+
+ if (ctx->Driver.ColorMask)
+ ctx->Driver.ColorMask( ctx, red, green, blue, alpha );
+}
+
+
+/**
+ * For GL_EXT_draw_buffers2 and GL3
+ */
+void GLAPIENTRY
+_mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha )
+{
+ GLubyte tmp[4];
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glColorMaskIndexed %u %d %d %d %d\n",
+ buf, red, green, blue, alpha);
+
+ if (buf >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glColorMaskIndexed(buf=%u)", buf);
+ return;
+ }
+
+ /* Shouldn't have any information about channel depth in core mesa
+ * -- should probably store these as the native booleans:
+ */
+ tmp[RCOMP] = red ? 0xff : 0x0;
+ tmp[GCOMP] = green ? 0xff : 0x0;
+ tmp[BCOMP] = blue ? 0xff : 0x0;
+ tmp[ACOMP] = alpha ? 0xff : 0x0;
+
+ if (TEST_EQ_4V(tmp, ctx->Color.ColorMask[buf]))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4UBV(ctx->Color.ColorMask[buf], tmp);
+
+ if (ctx->Driver.ColorMaskIndexed)
+ ctx->Driver.ColorMaskIndexed(ctx, buf, red, green, blue, alpha);
+}
+
+
+void GLAPIENTRY
+_mesa_ClampColorARB(GLenum target, GLenum clamp)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (clamp != GL_TRUE && clamp != GL_FALSE && clamp != GL_FIXED_ONLY_ARB) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(clamp)");
+ return;
+ }
+
+ switch (target) {
+ case GL_CLAMP_VERTEX_COLOR_ARB:
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.ClampVertexColor = clamp;
+ break;
+ case GL_CLAMP_FRAGMENT_COLOR_ARB:
+ FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
+ ctx->Color.ClampFragmentColor = clamp;
+ break;
+ case GL_CLAMP_READ_COLOR_ARB:
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.ClampReadColor = clamp;
+ break;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)");
+ return;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/** \name Initialization */
+/*@{*/
+
+/**
+ * Initialization of the context's Color attribute group.
+ *
+ * \param ctx GL context.
+ *
+ * Initializes the related fields in the context color attribute group,
+ * __struct gl_contextRec::Color.
+ */
+void _mesa_init_color( struct gl_context * ctx )
+{
+ GLuint i;
+
+ /* Color buffer group */
+ ctx->Color.IndexMask = ~0u;
+ memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
+ ctx->Color.ClearIndex = 0;
+ ASSIGN_4V( ctx->Color.ClearColor.f, 0, 0, 0, 0 );
+ ctx->Color.AlphaEnabled = GL_FALSE;
+ ctx->Color.AlphaFunc = GL_ALWAYS;
+ ctx->Color.AlphaRef = 0;
+ ctx->Color.BlendEnabled = 0x0;
+ for (i = 0; i < Elements(ctx->Color.Blend); i++) {
+ ctx->Color.Blend[i].SrcRGB = GL_ONE;
+ ctx->Color.Blend[i].DstRGB = GL_ZERO;
+ ctx->Color.Blend[i].SrcA = GL_ONE;
+ ctx->Color.Blend[i].DstA = GL_ZERO;
+ ctx->Color.Blend[i].EquationRGB = GL_FUNC_ADD;
+ ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
+ }
+ ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
+ ctx->Color.IndexLogicOpEnabled = GL_FALSE;
+ ctx->Color.ColorLogicOpEnabled = GL_FALSE;
+ ctx->Color._LogicOpEnabled = GL_FALSE;
+ ctx->Color.LogicOp = GL_COPY;
+ ctx->Color.DitherFlag = GL_TRUE;
+
+ if (ctx->Visual.doubleBufferMode) {
+ ctx->Color.DrawBuffer[0] = GL_BACK;
+ }
+ else {
+ ctx->Color.DrawBuffer[0] = GL_FRONT;
+ }
+
+ ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
+ ctx->Color._ClampFragmentColor = GL_TRUE;
+ ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
+ ctx->Color._ClampReadColor = GL_TRUE;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/clear.c b/mesalib/src/mesa/main/clear.c
index fa95e4522..301fe694c 100644
--- a/mesalib/src/mesa/main/clear.c
+++ b/mesalib/src/mesa/main/clear.c
@@ -83,16 +83,11 @@ _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
tmp[2] = blue;
tmp[3] = alpha;
- if (TEST_EQ_4V(tmp, ctx->Color.ClearColorUnclamped))
+ if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.f))
return; /* no change */
FLUSH_VERTICES(ctx, _NEW_COLOR);
- COPY_4V(ctx->Color.ClearColorUnclamped, tmp);
-
- ctx->Color.ClearColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
- ctx->Color.ClearColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
- ctx->Color.ClearColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
- ctx->Color.ClearColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
+ COPY_4V(ctx->Color.ClearColor.f, tmp);
if (ctx->Driver.ClearColor) {
/* it's OK to call glClearColor in CI mode but it should be a NOP */
@@ -110,25 +105,22 @@ _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
void GLAPIENTRY
_mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
{
- GLfloat tmp[4];
+ GLint tmp[4];
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- tmp[0] = (GLfloat) r;
- tmp[1] = (GLfloat) g;
- tmp[2] = (GLfloat) b;
- tmp[3] = (GLfloat) a;
+ tmp[0] = r;
+ tmp[1] = g;
+ tmp[2] = b;
+ tmp[3] = a;
- if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
+ if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.i))
return; /* no change */
FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4V(ctx->Color.ClearColor.i, tmp);
- /* XXX we should eventually have a float/int/uint union for
- * the ctx->Color.ClearColor state.
- */
- COPY_4V(ctx->Color.ClearColor, tmp);
-
+ /* these should be NOP calls for drivers supporting EXT_texture_integer */
if (ctx->Driver.ClearColor) {
ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
}
@@ -141,25 +133,22 @@ _mesa_ClearColorIiEXT(GLint r, GLint g, GLint b, GLint a)
void GLAPIENTRY
_mesa_ClearColorIuiEXT(GLuint r, GLuint g, GLuint b, GLuint a)
{
- GLfloat tmp[4];
+ GLuint tmp[4];
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
- tmp[0] = (GLfloat) r;
- tmp[1] = (GLfloat) g;
- tmp[2] = (GLfloat) b;
- tmp[3] = (GLfloat) a;
+ tmp[0] = r;
+ tmp[1] = g;
+ tmp[2] = b;
+ tmp[3] = a;
- if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
+ if (TEST_EQ_4V(tmp, ctx->Color.ClearColor.ui))
return; /* no change */
FLUSH_VERTICES(ctx, _NEW_COLOR);
+ COPY_4V(ctx->Color.ClearColor.ui, tmp);
- /* XXX we should eventually have a float/int/uint union for
- * the ctx->Color.ClearColor state.
- */
- COPY_4V(ctx->Color.ClearColor, tmp);
-
+ /* these should be NOP calls for drivers supporting EXT_texture_integer */
if (ctx->Driver.ClearColor) {
ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
}
@@ -364,21 +353,18 @@ _mesa_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
return;
}
else if (mask) {
- /* XXX note: we're putting the integer clear values into the
- * floating point state var. This will not always work. We'll
- * need a new ctx->Driver.ClearBuffer() hook....
- */
- GLclampf clearSave[4];
+ union gl_color_union clearSave;
+
/* save color */
- COPY_4V(clearSave, ctx->Color.ClearColor);
+ clearSave = ctx->Color.ClearColor;
/* set color */
- COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
+ COPY_4V(ctx->Color.ClearColor.i, value);
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
/* clear buffer(s) */
ctx->Driver.Clear(ctx, mask);
/* restore color */
- COPY_4V(ctx->Color.ClearColor, clearSave);
+ ctx->Color.ClearColor = clearSave;
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, clearSave);
}
@@ -418,21 +404,18 @@ _mesa_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
return;
}
else if (mask) {
- /* XXX note: we're putting the uint clear values into the
- * floating point state var. This will not always work. We'll
- * need a new ctx->Driver.ClearBuffer() hook....
- */
- GLclampf clearSave[4];
+ union gl_color_union clearSave;
+
/* save color */
- COPY_4V(clearSave, ctx->Color.ClearColor);
+ clearSave = ctx->Color.ClearColor;
/* set color */
- COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
+ COPY_4V(ctx->Color.ClearColor.ui, value);
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
/* clear buffer(s) */
ctx->Driver.Clear(ctx, mask);
/* restore color */
- COPY_4V(ctx->Color.ClearColor, clearSave);
+ ctx->Color.ClearColor = clearSave;
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, clearSave);
}
@@ -495,17 +478,18 @@ _mesa_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
return;
}
else if (mask) {
- GLclampf clearSave[4];
+ union gl_color_union clearSave;
+
/* save color */
- COPY_4V(clearSave, ctx->Color.ClearColor);
+ clearSave = ctx->Color.ClearColor;
/* set color */
- COPY_4V_CAST(ctx->Color.ClearColor, value, GLclampf);
+ COPY_4V_CAST(ctx->Color.ClearColor.f, value, GLclampf);
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, ctx->Color.ClearColor);
/* clear buffer(s) */
ctx->Driver.Clear(ctx, mask);
/* restore color */
- COPY_4V(ctx->Color.ClearColor, clearSave);
+ ctx->Color.ClearColor = clearSave;
if (ctx->Driver.ClearColor)
ctx->Driver.ClearColor(ctx, clearSave);
}
diff --git a/mesalib/src/mesa/main/colormac.h b/mesalib/src/mesa/main/colormac.h
index d308c48b6..4b7c3b4a0 100644
--- a/mesalib/src/mesa/main/colormac.h
+++ b/mesalib/src/mesa/main/colormac.h
@@ -169,6 +169,17 @@ do { \
} while (0)
+/**
+ * Convert four float values in [0,1] to ubytes in [0,255] with clamping.
+ */
+static inline void
+_mesa_unclamped_float_rgba_to_ubyte(GLubyte dst[4], const GLfloat src[4])
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ UNCLAMPED_FLOAT_TO_UBYTE(dst[i], src[i]);
+}
+
/**
* \name Generic color packing macros. All inputs should be GLubytes.
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index b77e4f092..d6cc0196d 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -589,7 +589,8 @@ struct dd_function_table {
GLenum sfactorRGB, GLenum dfactorRGB,
GLenum sfactorA, GLenum dfactorA);
/** Specify clear values for the color buffers */
- void (*ClearColor)(struct gl_context *ctx, const GLfloat color[4]);
+ void (*ClearColor)(struct gl_context *ctx,
+ const union gl_color_union color);
/** Specify the clear value for the depth buffer */
void (*ClearDepth)(struct gl_context *ctx, GLclampd d);
/** Specify the clear value for the stencil buffer */
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 069254b18..a777bd8c4 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -1673,10 +1673,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped);
break;
case GL_COLOR_CLEAR_VALUE:
- if(ctx->Color._ClampFragmentColor)
- COPY_4FV(v->value_float_4, ctx->Color.ClearColor);
- else
- COPY_4FV(v->value_float_4, ctx->Color.ClearColorUnclamped);
+ if(ctx->Color._ClampFragmentColor) {
+ v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F);
+ v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F);
+ v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F);
+ v->value_float_4[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F);
+ } else
+ COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f);
break;
case GL_BLEND_COLOR_EXT:
if(ctx->Color._ClampFragmentColor)
diff --git a/mesalib/src/mesa/main/image.c b/mesalib/src/mesa/main/image.c
index 3e75e7c6b..66d7eec65 100644
--- a/mesalib/src/mesa/main/image.c
+++ b/mesalib/src/mesa/main/image.c
@@ -1513,12 +1513,8 @@ _mesa_convert_colors(GLenum srcType, const GLvoid *src,
GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
GLuint i;
for (i = 0; i < count; i++) {
- if (!mask || mask[i]) {
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][RCOMP], src4[i][RCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][GCOMP], src4[i][GCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][BCOMP], src4[i][BCOMP]);
- UNCLAMPED_FLOAT_TO_UBYTE(dst1[i][ACOMP], src4[i][ACOMP]);
- }
+ if (!mask || mask[i])
+ _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]);
}
if (useTemp)
memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index ae500b4c2..8671ecda9 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -721,16 +721,26 @@ struct gl_accum_attrib
/**
+ * Used for storing clear color, texture border color, etc.
+ * The float values are typically unclamped.
+ */
+union gl_color_union
+{
+ GLfloat f[4];
+ GLint i[4];
+ GLuint ui[4];
+};
+
+
+/**
* Color buffer attribute group (GL_COLOR_BUFFER_BIT).
*/
struct gl_colorbuffer_attrib
{
- GLuint ClearIndex; /**< Index to use for glClear */
- GLfloat ClearColorUnclamped[4]; /**< Color to use for glClear*/
- GLclampf ClearColor[4]; /**< Color to use for glClear */
-
- GLuint IndexMask; /**< Color index write mask */
- GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
+ GLuint ClearIndex; /**< Index for glClear */
+ union gl_color_union ClearColor; /**< Color for glClear, unclamped */
+ GLuint IndexMask; /**< Color index write mask */
+ GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; /**< Each flag is 0xff or 0x0 */
GLenum DrawBuffer[MAX_DRAW_BUFFERS]; /**< Which buffer to draw into */
@@ -750,8 +760,8 @@ struct gl_colorbuffer_attrib
/*@{*/
GLbitfield BlendEnabled; /**< Per-buffer blend enable flags */
- /* NOTE: this does _not_ depend on fragment clamping or any other clamping control,
- * only on the fixed-pointness of the render target.
+ /* NOTE: this does _not_ depend on fragment clamping or any other clamping
+ * control, only on the fixed-pointness of the render target.
* The query does however depend on fragment color clamping.
*/
GLfloat BlendColorUnclamped[4]; /**< Blending color */
@@ -1356,11 +1366,7 @@ struct gl_sampler_object
GLenum WrapR; /**< R-axis texture image wrap mode */
GLenum MinFilter; /**< minification filter */
GLenum MagFilter; /**< magnification filter */
- union {
- GLfloat f[4];
- GLuint ui[4];
- GLint i[4];
- } BorderColor; /**< Interpreted according to texture format */
+ union gl_color_union BorderColor; /**< Interpreted according to texture format */
GLfloat MinLod; /**< min lambda, OpenGL 1.2 */
GLfloat MaxLod; /**< max lambda, OpenGL 1.2 */
GLfloat LodBias; /**< OpenGL 1.4 */
diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c
index b0f9c33b8..2323819aa 100644
--- a/mesalib/src/mesa/main/uniforms.c
+++ b/mesalib/src/mesa/main/uniforms.c
@@ -111,21 +111,43 @@ is_sampler_type(GLenum type)
{
switch (type) {
case GL_SAMPLER_1D:
+ case GL_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
case GL_SAMPLER_2D:
+ case GL_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
case GL_SAMPLER_3D:
+ case GL_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
case GL_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
case GL_SAMPLER_1D_SHADOW:
case GL_SAMPLER_2D_SHADOW:
case GL_SAMPLER_CUBE_SHADOW:
case GL_SAMPLER_2D_RECT_ARB:
+ case GL_INT_SAMPLER_2D_RECT:
+ case GL_UNSIGNED_INT_SAMPLER_2D_RECT:
case GL_SAMPLER_2D_RECT_SHADOW_ARB:
case GL_SAMPLER_1D_ARRAY_EXT:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
case GL_SAMPLER_2D_ARRAY_EXT:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
case GL_SAMPLER_CUBE_MAP_ARRAY:
case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
return GL_TRUE;
default:
return GL_FALSE;
diff --git a/mesalib/src/mesa/state_tracker/st_cb_clear.c b/mesalib/src/mesa/state_tracker/st_cb_clear.c
index 117000ba7..a4799e3cc 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_clear.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_clear.c
@@ -323,9 +323,9 @@ clear_with_quad(struct gl_context *ctx,
set_vertex_shader(st);
if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
- st_translate_color(ctx->Color.ClearColorUnclamped,
- ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
- clearColor);
+ st_translate_color(ctx->Color.ClearColor.f,
+ ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
+ clearColor);
}
/* draw quad matching scissor rect */
@@ -582,12 +582,12 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
if (ctx->DrawBuffer->_ColorDrawBuffers[0]) {
- st_translate_color(ctx->Color.ClearColor,
- ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
- clearColor);
+ st_translate_color(ctx->Color.ClearColor.f,
+ ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
+ clearColor);
}
- st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColorUnclamped,
+ st->pipe->clear(st->pipe, clear_buffers, clearColor,
ctx->Depth.Clear, ctx->Stencil.Clear);
}
if (mask & BUFFER_BIT_ACCUM)
diff --git a/mesalib/src/mesa/state_tracker/st_format.c b/mesalib/src/mesa/state_tracker/st_format.c
index bd4f0860c..6eb8a506b 100644
--- a/mesalib/src/mesa/state_tracker/st_format.c
+++ b/mesalib/src/mesa/state_tracker/st_format.c
@@ -1441,8 +1441,9 @@ st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
* This is used for translating texture border color and the clear
* color. For example, the clear color is interpreted according to
* the renderbuffer's base format. For example, if clearing a
- * GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] =
- * alpha. Similarly for texture border colors.
+ * GL_LUMINANCE buffer, we'll return colorOut[0] = colorOut[1] =
+ * colorOut[2] = colorIn[0].
+ * Similarly for texture border colors.
*/
void
st_translate_color(const GLfloat colorIn[4], GLenum baseFormat,
diff --git a/mesalib/src/mesa/swrast/s_blend.c b/mesalib/src/mesa/swrast/s_blend.c
index 125364913..3760f91d6 100644
--- a/mesalib/src/mesa/swrast/s_blend.c
+++ b/mesalib/src/mesa/swrast/s_blend.c
@@ -1,1014 +1,1010 @@
-/*
- * Mesa 3-D graphics library
- * Version: 7.1
- *
- * Copyright (C) 1999-2008 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"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/**
- * \file swrast/s_blend.c
- * \brief software blending.
- * \author Brian Paul
- *
- * Only a few blend modes have been optimized (min, max, transparency, add)
- * more optimized cases can easily be added if needed.
- * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
- */
-
-
-
-#include "main/glheader.h"
-#include "main/context.h"
-#include "main/colormac.h"
-#include "main/macros.h"
-
-#include "s_blend.h"
-#include "s_context.h"
-#include "s_span.h"
-
-
-#if defined(USE_MMX_ASM)
-#include "x86/mmx.h"
-#include "x86/common_x86_asm.h"
-#define _BLENDAPI _ASMAPI
-#else
-#define _BLENDAPI
-#endif
-
-
-/**
- * Integer divide by 255
- * Declare "int divtemp" before using.
- * This satisfies Glean and should be reasonably fast.
- * Contributed by Nathan Hand.
- */
-#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
-
-
-
-/**
- * Special case for glBlendFunc(GL_ZERO, GL_ONE).
- * No-op means the framebuffer values remain unchanged.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLint bytes;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
- (void) ctx;
-
- /* just memcpy */
- if (chanType == GL_UNSIGNED_BYTE)
- bytes = 4 * n * sizeof(GLubyte);
- else if (chanType == GL_UNSIGNED_SHORT)
- bytes = 4 * n * sizeof(GLushort);
- else
- bytes = 4 * n * sizeof(GLfloat);
-
- memcpy(src, dst, bytes);
-}
-
-
-/**
- * Special case for glBlendFunc(GL_ONE, GL_ZERO)
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO);
- (void) ctx;
- (void) n;
- (void) mask;
- (void) src;
- (void) dst;
-}
-
-
-/**
- * Common transparency blending mode:
- * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
- */
-static void _BLENDAPI
-blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_UNSIGNED_BYTE);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */
- if (t == 0) {
- /* 0% alpha */
- COPY_4UBV(rgba[i], dest[i]);
- }
- else if (t != 255) {
- GLint divtemp;
- const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
- const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
- const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
- const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
- ASSERT(r <= 255);
- ASSERT(g <= 255);
- ASSERT(b <= 255);
- ASSERT(a <= 255);
- rgba[i][RCOMP] = (GLubyte) r;
- rgba[i][GCOMP] = (GLubyte) g;
- rgba[i][BCOMP] = (GLubyte) b;
- rgba[i][ACOMP] = (GLubyte) a;
- }
- }
- }
-}
-
-
-static void _BLENDAPI
-blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_UNSIGNED_SHORT);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLint t = rgba[i][ACOMP];
- if (t == 0) {
- /* 0% alpha */
- COPY_4V(rgba[i], dest[i]);
- }
- else if (t != 65535) {
- const GLfloat tt = (GLfloat) t / 65535.0F;
- GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
- GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
- GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
- GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
- ASSIGN_4V(rgba[i], r, g, b, a);
- }
- }
- }
-}
-
-
-static void _BLENDAPI
-blend_transparency_float(struct gl_context *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;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
- ASSERT(chanType == GL_FLOAT);
-
- (void) ctx;
-
- for (i = 0; i < n; i++) {
- if (mask[i]) {
- const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */
- if (t == 0.0F) {
- /* 0% alpha */
- COPY_4V(rgba[i], dest[i]);
- }
- else if (t != 1.0F) {
- GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
- GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
- GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
- GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
- ASSIGN_4V(rgba[i], r, g, b, a);
- }
- }
- }
-}
-
-
-
-/**
- * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
-
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
- ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
- ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
- 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] = (GLubyte) MIN2( r, 255 );
- rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
- rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
- rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
- 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] = (GLshort) MIN2( r, 255 );
- rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
- rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
- rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- /* don't RGB clamp to max */
- rgba[i][RCOMP] += dest[i][RCOMP];
- rgba[i][GCOMP] += dest[i][GCOMP];
- rgba[i][BCOMP] += dest[i][BCOMP];
- rgba[i][ACOMP] += dest[i][ACOMP];
- }
- }
- }
-}
-
-
-
-/**
- * Blend min function.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- 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] );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- 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] );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- 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] );
- }
- }
- }
-}
-
-
-/**
- * Blend max function.
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX);
- ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX);
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- 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] );
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- 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] );
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- 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] );
- }
- }
- }
-}
-
-
-
-/**
- * Modulate: result = src * dest
- * Any chanType ok.
- */
-static void _BLENDAPI
-blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLvoid *src, const GLvoid *dst, GLenum chanType)
-{
- GLuint i;
- (void) ctx;
-
- if (chanType == GL_UNSIGNED_BYTE) {
- GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
- const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- GLint divtemp;
- rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
- rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
- rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
- rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
- }
- }
- }
- else if (chanType == GL_UNSIGNED_SHORT) {
- GLushort (*rgba)[4] = (GLushort (*)[4]) src;
- const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
- rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
- rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
- rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
- }
- }
- }
- else {
- GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
- const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
- ASSERT(chanType == GL_FLOAT);
- for (i=0;i<n;i++) {
- if (mask[i]) {
- rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
- rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
- rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
- rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
- }
- }
- }
-}
-
-
-/**
- * Do any blending operation, using floating point.
- * \param n number of pixels
- * \param mask fragment writemask array
- * \param rgba array of incoming (and modified) pixels
- * \param dest array of pixels from the dest color buffer
- */
-static void
-blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- GLfloat rgba[][4], GLfloat dest[][4],
- GLenum chanType)
-{
- 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.Blend[0].SrcRGB) {
- 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:
- sR = Rs;
- sG = Gs;
- sB = Bs;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- 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.Blend[0].SrcA) {
- 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:
- sA = As;
- break;
- case GL_ONE_MINUS_SRC_COLOR:
- 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.Blend[0].DstRGB) {
- 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:
- dR = Rd;
- dG = Gd;
- dB = Bd;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- 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.Blend[0].DstA) {
- 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:
- dA = Ad;
- break;
- case GL_ONE_MINUS_DST_COLOR:
- 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.Blend[0].EquationRGB) {
- 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.Blend[0].EquationA) {
- 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, 1.0F );
-#else
- ASSIGN_4V(rgba[i], r, g, b, a);
-#endif
- }
- }
-}
-
-
-/**
- * Do any blending operation, any chanType.
- */
-static void
-blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
- void *src, const void *dst, GLenum chanType)
-{
- GLfloat (*rgbaF)[4], (*destF)[4];
-
- rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
- destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
- if (!rgbaF || !destF) {
- free(rgbaF);
- free(destF);
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
- return;
- }
-
- 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]) src,
- (GLfloat (*)[4]) dst, chanType);
- }
-
- free(rgbaF);
- free(destF);
-}
-
-
-
-/**
- * Analyze current blending parameters to pick fastest blending function.
- * Result: the ctx->Color.BlendFunc pointer is updated.
- */
-void
-_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
-{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const GLenum eq = ctx->Color.Blend[0].EquationRGB;
- const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
- const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
- const GLenum srcA = ctx->Color.Blend[0].SrcA;
- const GLenum dstA = ctx->Color.Blend[0].DstA;
-
- if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
- 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 && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_min;
- }
- else
-#endif
- swrast->BlendFunc = blend_min;
- }
- else if (eq == GL_MAX) {
- /* Note: GL_MAX ignores the blending weight factors */
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_max;
- }
- else
-#endif
- swrast->BlendFunc = blend_max;
- }
- else if (srcRGB != srcA || dstRGB != dstA) {
- 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 && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_transparency;
- }
- else
-#endif
- {
- if (chanType == GL_UNSIGNED_BYTE)
- swrast->BlendFunc = blend_transparency_ubyte;
- else if (chanType == GL_UNSIGNED_SHORT)
- swrast->BlendFunc = blend_transparency_ushort;
- else
- swrast->BlendFunc = blend_transparency_float;
- }
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_add;
- }
- else
-#endif
- swrast->BlendFunc = blend_add;
- }
- 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))) {
-#if defined(USE_MMX_ASM)
- if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
- swrast->BlendFunc = _mesa_mmx_blend_modulate;
- }
- else
-#endif
- swrast->BlendFunc = blend_modulate;
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
- swrast->BlendFunc = blend_noop;
- }
- else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
- swrast->BlendFunc = blend_replace;
- }
- else {
- 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.
- */
-void
-_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
-{
- 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);
-
- rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
-
- swrast->BlendFunc(ctx, span->end, span->array->mask,
- span->array->rgba, rbPixels, span->array->ChanType);
-}
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+/**
+ * \file swrast/s_blend.c
+ * \brief software blending.
+ * \author Brian Paul
+ *
+ * Only a few blend modes have been optimized (min, max, transparency, add)
+ * more optimized cases can easily be added if needed.
+ * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
+ */
+
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+
+#include "s_blend.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+#if defined(USE_MMX_ASM)
+#include "x86/mmx.h"
+#include "x86/common_x86_asm.h"
+#define _BLENDAPI _ASMAPI
+#else
+#define _BLENDAPI
+#endif
+
+
+/**
+ * Integer divide by 255
+ * Declare "int divtemp" before using.
+ * This satisfies Glean and should be reasonably fast.
+ * Contributed by Nathan Hand.
+ */
+#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
+
+
+
+/**
+ * Special case for glBlendFunc(GL_ZERO, GL_ONE).
+ * No-op means the framebuffer values remain unchanged.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLint bytes;
+
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
+ (void) ctx;
+
+ /* just memcpy */
+ if (chanType == GL_UNSIGNED_BYTE)
+ bytes = 4 * n * sizeof(GLubyte);
+ else if (chanType == GL_UNSIGNED_SHORT)
+ bytes = 4 * n * sizeof(GLushort);
+ else
+ bytes = 4 * n * sizeof(GLfloat);
+
+ memcpy(src, dst, bytes);
+}
+
+
+/**
+ * Special case for glBlendFunc(GL_ONE, GL_ZERO)
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO);
+ (void) ctx;
+ (void) n;
+ (void) mask;
+ (void) src;
+ (void) dst;
+}
+
+
+/**
+ * Common transparency blending mode:
+ * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
+ */
+static void _BLENDAPI
+blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ GLuint i;
+
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_UNSIGNED_BYTE);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */
+ if (t == 0) {
+ /* 0% alpha */
+ COPY_4UBV(rgba[i], dest[i]);
+ }
+ else if (t != 255) {
+ GLint divtemp;
+ const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
+ const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
+ const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
+ const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP];
+ ASSERT(r <= 255);
+ ASSERT(g <= 255);
+ ASSERT(b <= 255);
+ ASSERT(a <= 255);
+ rgba[i][RCOMP] = (GLubyte) r;
+ rgba[i][GCOMP] = (GLubyte) g;
+ rgba[i][BCOMP] = (GLubyte) b;
+ rgba[i][ACOMP] = (GLubyte) a;
+ }
+ }
+ }
+}
+
+
+static void _BLENDAPI
+blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ GLuint i;
+
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_UNSIGNED_SHORT);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLint t = rgba[i][ACOMP];
+ if (t == 0) {
+ /* 0% alpha */
+ COPY_4V(rgba[i], dest[i]);
+ }
+ else if (t != 65535) {
+ const GLfloat tt = (GLfloat) t / 65535.0F;
+ GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
+ GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
+ GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
+ GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
+ ASSIGN_4V(rgba[i], r, g, b, a);
+ }
+ }
+ }
+}
+
+
+static void _BLENDAPI
+blend_transparency_float(struct gl_context *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;
+
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
+ ASSERT(chanType == GL_FLOAT);
+
+ (void) ctx;
+
+ for (i = 0; i < n; i++) {
+ if (mask[i]) {
+ const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */
+ if (t == 0.0F) {
+ /* 0% alpha */
+ COPY_4V(rgba[i], dest[i]);
+ }
+ else if (t != 1.0F) {
+ GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
+ GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
+ GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
+ GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
+ ASSIGN_4V(rgba[i], r, g, b, a);
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
+ ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
+ ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
+ 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] = (GLubyte) MIN2( r, 255 );
+ rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
+ rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
+ rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
+ 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] = (GLshort) MIN2( r, 255 );
+ rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
+ rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
+ rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ /* don't RGB clamp to max */
+ rgba[i][RCOMP] += dest[i][RCOMP];
+ rgba[i][GCOMP] += dest[i][GCOMP];
+ rgba[i][BCOMP] += dest[i][BCOMP];
+ rgba[i][ACOMP] += dest[i][ACOMP];
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Blend min function.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ 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] );
+ }
+ }
+ }
+}
+
+
+/**
+ * Blend max function.
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX);
+ ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX);
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ 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] );
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ 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] );
+ }
+ }
+ }
+}
+
+
+
+/**
+ * Modulate: result = src * dest
+ * Any chanType ok.
+ */
+static void _BLENDAPI
+blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLvoid *src, const GLvoid *dst, GLenum chanType)
+{
+ GLuint i;
+ (void) ctx;
+
+ if (chanType == GL_UNSIGNED_BYTE) {
+ GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
+ const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint divtemp;
+ rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
+ rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
+ rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
+ rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
+ }
+ }
+ }
+ else if (chanType == GL_UNSIGNED_SHORT) {
+ GLushort (*rgba)[4] = (GLushort (*)[4]) src;
+ const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
+ rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
+ rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
+ rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
+ }
+ }
+ }
+ else {
+ GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
+ const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
+ ASSERT(chanType == GL_FLOAT);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
+ rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
+ rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
+ rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
+ }
+ }
+ }
+}
+
+
+/**
+ * Do any blending operation, using floating point.
+ * \param n number of pixels
+ * \param mask fragment writemask array
+ * \param rgba array of incoming (and modified) pixels
+ * \param dest array of pixels from the dest color buffer
+ */
+static void
+blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ GLfloat rgba[][4], GLfloat dest[][4],
+ GLenum chanType)
+{
+ 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.Blend[0].SrcRGB) {
+ 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:
+ sR = Rs;
+ sG = Gs;
+ sB = Bs;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ 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.Blend[0].SrcA) {
+ 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:
+ sA = As;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ 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.Blend[0].DstRGB) {
+ 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:
+ dR = Rd;
+ dG = Gd;
+ dB = Bd;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ 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.Blend[0].DstA) {
+ 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:
+ dA = Ad;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ 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.Blend[0].EquationRGB) {
+ 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.Blend[0].EquationA) {
+ 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, 1.0F );
+#else
+ ASSIGN_4V(rgba[i], r, g, b, a);
+#endif
+ }
+ }
+}
+
+
+/**
+ * Do any blending operation, any chanType.
+ */
+static void
+blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
+ void *src, const void *dst, GLenum chanType)
+{
+ GLfloat (*rgbaF)[4], (*destF)[4];
+
+ rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
+ destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
+ if (!rgbaF || !destF) {
+ free(rgbaF);
+ free(destF);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
+ return;
+ }
+
+ 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])
+ _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]);
+ }
+ }
+ 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]) src,
+ (GLfloat (*)[4]) dst, chanType);
+ }
+
+ free(rgbaF);
+ free(destF);
+}
+
+
+
+/**
+ * Analyze current blending parameters to pick fastest blending function.
+ * Result: the ctx->Color.BlendFunc pointer is updated.
+ */
+void
+_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLenum eq = ctx->Color.Blend[0].EquationRGB;
+ const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
+ const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
+ const GLenum srcA = ctx->Color.Blend[0].SrcA;
+ const GLenum dstA = ctx->Color.Blend[0].DstA;
+
+ if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
+ 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 && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_min;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_min;
+ }
+ else if (eq == GL_MAX) {
+ /* Note: GL_MAX ignores the blending weight factors */
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_max;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_max;
+ }
+ else if (srcRGB != srcA || dstRGB != dstA) {
+ 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 && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_transparency;
+ }
+ else
+#endif
+ {
+ if (chanType == GL_UNSIGNED_BYTE)
+ swrast->BlendFunc = blend_transparency_ubyte;
+ else if (chanType == GL_UNSIGNED_SHORT)
+ swrast->BlendFunc = blend_transparency_ushort;
+ else
+ swrast->BlendFunc = blend_transparency_float;
+ }
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_add;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_add;
+ }
+ 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))) {
+#if defined(USE_MMX_ASM)
+ if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
+ swrast->BlendFunc = _mesa_mmx_blend_modulate;
+ }
+ else
+#endif
+ swrast->BlendFunc = blend_modulate;
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
+ swrast->BlendFunc = blend_noop;
+ }
+ else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
+ swrast->BlendFunc = blend_replace;
+ }
+ else {
+ 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.
+ */
+void
+_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
+{
+ 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);
+
+ rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
+
+ swrast->BlendFunc(ctx, span->end, span->array->mask,
+ span->array->rgba, rbPixels, span->array->ChanType);
+}
diff --git a/mesalib/src/mesa/swrast/s_clear.c b/mesalib/src/mesa/swrast/s_clear.c
index 9e9b53116..980d29bba 100644
--- a/mesalib/src/mesa/swrast/s_clear.c
+++ b/mesalib/src/mesa/swrast/s_clear.c
@@ -60,20 +60,17 @@ clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *r
span.array->ChanType = rb->DataType;
if (span.array->ChanType == GL_UNSIGNED_BYTE) {
GLubyte clearColor[4];
- UNCLAMPED_FLOAT_TO_UBYTE(clearColor[RCOMP], ctx->Color.ClearColor[0]);
- UNCLAMPED_FLOAT_TO_UBYTE(clearColor[GCOMP], ctx->Color.ClearColor[1]);
- UNCLAMPED_FLOAT_TO_UBYTE(clearColor[BCOMP], ctx->Color.ClearColor[2]);
- UNCLAMPED_FLOAT_TO_UBYTE(clearColor[ACOMP], ctx->Color.ClearColor[3]);
+ _mesa_unclamped_float_rgba_to_ubyte(clearColor, ctx->Color.ClearColor.f);
for (i = 0; i < width; i++) {
COPY_4UBV(span.array->rgba[i], clearColor);
}
}
else if (span.array->ChanType == GL_UNSIGNED_SHORT) {
GLushort clearColor[4];
- UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor[0]);
- UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor[1]);
- UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor[2]);
- UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor[3]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[RCOMP], ctx->Color.ClearColor.f[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[GCOMP], ctx->Color.ClearColor.f[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[BCOMP], ctx->Color.ClearColor.f[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(clearColor[ACOMP], ctx->Color.ClearColor.f[3]);
for (i = 0; i < width; i++) {
COPY_4V_CAST(span.array->rgba[i], clearColor, GLchan);
}
@@ -81,10 +78,10 @@ clear_rgba_buffer_with_masking(struct gl_context *ctx, struct gl_renderbuffer *r
else {
ASSERT(span.array->ChanType == GL_FLOAT);
for (i = 0; i < width; i++) {
- CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor[0]);
- CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor[1]);
- CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor[2]);
- CLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor[3]);
+ UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][0], ctx->Color.ClearColor.f[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][1], ctx->Color.ClearColor.f[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][2], ctx->Color.ClearColor.f[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(span.array->rgba[i][3], ctx->Color.ClearColor.f[3]);
}
}
@@ -115,6 +112,7 @@ clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf
GLubyte clear8[4];
GLushort clear16[4];
GLvoid *clearVal;
+ GLfloat clearFloat[4];
GLint i;
ASSERT(ctx->Color.ColorMask[buf][0] &&
@@ -126,21 +124,22 @@ clear_rgba_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint buf
switch (rb->DataType) {
case GL_UNSIGNED_BYTE:
- UNCLAMPED_FLOAT_TO_UBYTE(clear8[0], ctx->Color.ClearColor[0]);
- UNCLAMPED_FLOAT_TO_UBYTE(clear8[1], ctx->Color.ClearColor[1]);
- UNCLAMPED_FLOAT_TO_UBYTE(clear8[2], ctx->Color.ClearColor[2]);
- UNCLAMPED_FLOAT_TO_UBYTE(clear8[3], ctx->Color.ClearColor[3]);
+ _mesa_unclamped_float_rgba_to_ubyte(clear8, ctx->Color.ClearColor.f);
clearVal = clear8;
break;
case GL_UNSIGNED_SHORT:
- UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor[0]);
- UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor[1]);
- UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor[2]);
- UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor[3]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[0], ctx->Color.ClearColor.f[0]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[1], ctx->Color.ClearColor.f[1]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[2], ctx->Color.ClearColor.f[2]);
+ UNCLAMPED_FLOAT_TO_USHORT(clear16[3], ctx->Color.ClearColor.f[3]);
clearVal = clear16;
break;
case GL_FLOAT:
- clearVal = ctx->Color.ClearColor;
+ clearFloat[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F);
+ clearFloat[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F);
+ clearFloat[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F);
+ clearFloat[3] = CLAMP(ctx->Color.ClearColor.f[3], 0.0F, 1.0F);
+ clearVal = clearFloat;
break;
default:
_mesa_problem(ctx, "Bad rb DataType in clear_color_buffer");