blend.c revision 1b258989462e907e45abbdf8743b0a75f22c02b3
1/* $Id: blend.c,v 1.33 2001/06/18 17:26:08 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28#ifdef PC_HEADER 29#include "all.h" 30#else 31#include "glheader.h" 32#include "blend.h" 33#include "colormac.h" 34#include "context.h" 35#include "enums.h" 36#include "macros.h" 37#include "mtypes.h" 38#endif 39 40 41void 42_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) 43{ 44 45 GET_CURRENT_CONTEXT(ctx); 46 ASSERT_OUTSIDE_BEGIN_END(ctx); 47 48 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 49 fprintf(stderr, "glBlendFunc %s %s\n", 50 _mesa_lookup_enum_by_nr(sfactor), 51 _mesa_lookup_enum_by_nr(dfactor)); 52 53 switch (sfactor) { 54 case GL_SRC_COLOR: 55 case GL_ONE_MINUS_SRC_COLOR: 56 if (!ctx->Extensions.NV_blend_square) { 57 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" ); 58 return; 59 } 60 /* fall-through */ 61 case GL_ZERO: 62 case GL_ONE: 63 case GL_DST_COLOR: 64 case GL_ONE_MINUS_DST_COLOR: 65 case GL_SRC_ALPHA: 66 case GL_ONE_MINUS_SRC_ALPHA: 67 case GL_DST_ALPHA: 68 case GL_ONE_MINUS_DST_ALPHA: 69 case GL_SRC_ALPHA_SATURATE: 70 case GL_CONSTANT_COLOR: 71 case GL_ONE_MINUS_CONSTANT_COLOR: 72 case GL_CONSTANT_ALPHA: 73 case GL_ONE_MINUS_CONSTANT_ALPHA: 74 break; 75 default: 76 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" ); 77 return; 78 } 79 80 switch (dfactor) { 81 case GL_DST_COLOR: 82 case GL_ONE_MINUS_DST_COLOR: 83 if (!ctx->Extensions.NV_blend_square) { 84 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" ); 85 return; 86 } 87 /* fall-through */ 88 case GL_ZERO: 89 case GL_ONE: 90 case GL_SRC_COLOR: 91 case GL_ONE_MINUS_SRC_COLOR: 92 case GL_SRC_ALPHA: 93 case GL_ONE_MINUS_SRC_ALPHA: 94 case GL_DST_ALPHA: 95 case GL_ONE_MINUS_DST_ALPHA: 96 case GL_CONSTANT_COLOR: 97 case GL_ONE_MINUS_CONSTANT_COLOR: 98 case GL_CONSTANT_ALPHA: 99 case GL_ONE_MINUS_CONSTANT_ALPHA: 100 break; 101 default: 102 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" ); 103 return; 104 } 105 106 if (ctx->Color.BlendDstRGB == dfactor && 107 ctx->Color.BlendSrcRGB == sfactor && 108 ctx->Color.BlendDstA == dfactor && 109 ctx->Color.BlendSrcA == sfactor) 110 return; 111 112 FLUSH_VERTICES(ctx, _NEW_COLOR); 113 ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor; 114 ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor; 115 116 if (ctx->Driver.BlendFunc) 117 ctx->Driver.BlendFunc( ctx, sfactor, dfactor ); 118} 119 120 121/* GL_EXT_blend_func_separate */ 122void 123_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, 124 GLenum sfactorA, GLenum dfactorA ) 125{ 126 GET_CURRENT_CONTEXT(ctx); 127 ASSERT_OUTSIDE_BEGIN_END(ctx); 128 129 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 130 fprintf(stderr, "glBlendFuncSeparate %s %s %s %s\n", 131 _mesa_lookup_enum_by_nr(sfactorRGB), 132 _mesa_lookup_enum_by_nr(dfactorRGB), 133 _mesa_lookup_enum_by_nr(sfactorA), 134 _mesa_lookup_enum_by_nr(dfactorA)); 135 136 switch (sfactorRGB) { 137 case GL_SRC_COLOR: 138 case GL_ONE_MINUS_SRC_COLOR: 139 if (!ctx->Extensions.NV_blend_square) { 140 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)"); 141 return; 142 } 143 /* fall-through */ 144 case GL_ZERO: 145 case GL_ONE: 146 case GL_DST_COLOR: 147 case GL_ONE_MINUS_DST_COLOR: 148 case GL_SRC_ALPHA: 149 case GL_ONE_MINUS_SRC_ALPHA: 150 case GL_DST_ALPHA: 151 case GL_ONE_MINUS_DST_ALPHA: 152 case GL_SRC_ALPHA_SATURATE: 153 case GL_CONSTANT_COLOR: 154 case GL_ONE_MINUS_CONSTANT_COLOR: 155 case GL_CONSTANT_ALPHA: 156 case GL_ONE_MINUS_CONSTANT_ALPHA: 157 break; 158 default: 159 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)"); 160 return; 161 } 162 163 switch (dfactorRGB) { 164 case GL_DST_COLOR: 165 case GL_ONE_MINUS_DST_COLOR: 166 if (!ctx->Extensions.NV_blend_square) { 167 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)"); 168 return; 169 } 170 /* fall-through */ 171 case GL_ZERO: 172 case GL_ONE: 173 case GL_SRC_COLOR: 174 case GL_ONE_MINUS_SRC_COLOR: 175 case GL_SRC_ALPHA: 176 case GL_ONE_MINUS_SRC_ALPHA: 177 case GL_DST_ALPHA: 178 case GL_ONE_MINUS_DST_ALPHA: 179 case GL_CONSTANT_COLOR: 180 case GL_ONE_MINUS_CONSTANT_COLOR: 181 case GL_CONSTANT_ALPHA: 182 case GL_ONE_MINUS_CONSTANT_ALPHA: 183 break; 184 default: 185 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)"); 186 return; 187 } 188 189 switch (sfactorA) { 190 case GL_SRC_COLOR: 191 case GL_ONE_MINUS_SRC_COLOR: 192 if (!ctx->Extensions.NV_blend_square) { 193 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)"); 194 return; 195 } 196 /* fall-through */ 197 case GL_ZERO: 198 case GL_ONE: 199 case GL_DST_COLOR: 200 case GL_ONE_MINUS_DST_COLOR: 201 case GL_SRC_ALPHA: 202 case GL_ONE_MINUS_SRC_ALPHA: 203 case GL_DST_ALPHA: 204 case GL_ONE_MINUS_DST_ALPHA: 205 case GL_SRC_ALPHA_SATURATE: 206 case GL_CONSTANT_COLOR: 207 case GL_ONE_MINUS_CONSTANT_COLOR: 208 case GL_CONSTANT_ALPHA: 209 case GL_ONE_MINUS_CONSTANT_ALPHA: 210 break; 211 default: 212 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)"); 213 return; 214 } 215 216 switch (dfactorA) { 217 case GL_DST_COLOR: 218 case GL_ONE_MINUS_DST_COLOR: 219 if (!ctx->Extensions.NV_blend_square) { 220 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)"); 221 return; 222 } 223 /* fall-through */ 224 case GL_ZERO: 225 case GL_ONE: 226 case GL_SRC_COLOR: 227 case GL_ONE_MINUS_SRC_COLOR: 228 case GL_SRC_ALPHA: 229 case GL_ONE_MINUS_SRC_ALPHA: 230 case GL_DST_ALPHA: 231 case GL_ONE_MINUS_DST_ALPHA: 232 case GL_CONSTANT_COLOR: 233 case GL_ONE_MINUS_CONSTANT_COLOR: 234 case GL_CONSTANT_ALPHA: 235 case GL_ONE_MINUS_CONSTANT_ALPHA: 236 break; 237 default: 238 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" ); 239 return; 240 } 241 242 if (ctx->Color.BlendSrcRGB == sfactorRGB && 243 ctx->Color.BlendDstRGB == dfactorRGB && 244 ctx->Color.BlendSrcA == sfactorA && 245 ctx->Color.BlendDstA == dfactorA) 246 return; 247 248 FLUSH_VERTICES(ctx, _NEW_COLOR); 249 250 ctx->Color.BlendSrcRGB = sfactorRGB; 251 ctx->Color.BlendDstRGB = dfactorRGB; 252 ctx->Color.BlendSrcA = sfactorA; 253 ctx->Color.BlendDstA = dfactorA; 254 255 if (ctx->Driver.BlendFuncSeparate) { 256 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB, 257 sfactorA, dfactorA ); 258 } 259} 260 261 262 263/* This is really an extension function! */ 264void 265_mesa_BlendEquation( GLenum mode ) 266{ 267 GET_CURRENT_CONTEXT(ctx); 268 ASSERT_OUTSIDE_BEGIN_END(ctx); 269 270 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 271 fprintf(stderr, "glBlendEquation %s\n", 272 _mesa_lookup_enum_by_nr(mode)); 273 274 switch (mode) { 275 case GL_FUNC_ADD_EXT: 276 break; 277 case GL_MIN_EXT: 278 case GL_MAX_EXT: 279 if (!ctx->Extensions.EXT_blend_minmax && 280 !ctx->Extensions.ARB_imaging) { 281 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); 282 return; 283 } 284 break; 285 case GL_LOGIC_OP: 286 if (!ctx->Extensions.EXT_blend_logic_op) { 287 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); 288 return; 289 } 290 break; 291 case GL_FUNC_SUBTRACT_EXT: 292 case GL_FUNC_REVERSE_SUBTRACT_EXT: 293 if (!ctx->Extensions.EXT_blend_subtract && 294 !ctx->Extensions.ARB_imaging) { 295 _mesa_error(ctx, GL_INVALID_ENUM, "glBlendEquation"); 296 return; 297 } 298 break; 299 default: 300 _mesa_error( ctx, GL_INVALID_ENUM, "glBlendEquation" ); 301 return; 302 } 303 304 if (ctx->Color.BlendEquation == mode) 305 return; 306 307 FLUSH_VERTICES(ctx, _NEW_COLOR); 308 ctx->Color.BlendEquation = mode; 309 310 /* This is needed to support 1.1's RGB logic ops AND 311 * 1.0's blending logicops. 312 */ 313 ctx->Color.ColorLogicOpEnabled = (mode==GL_LOGIC_OP && 314 ctx->Color.BlendEnabled); 315 316 if (ctx->Driver.BlendEquation) 317 (*ctx->Driver.BlendEquation)( ctx, mode ); 318} 319 320 321 322void 323_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 324{ 325 GLfloat tmp[4]; 326 GET_CURRENT_CONTEXT(ctx); 327 ASSERT_OUTSIDE_BEGIN_END(ctx); 328 329 tmp[0] = CLAMP( red, 0.0, 1.0 ); 330 tmp[1] = CLAMP( green, 0.0, 1.0 ); 331 tmp[2] = CLAMP( blue, 0.0, 1.0 ); 332 tmp[3] = CLAMP( alpha, 0.0, 1.0 ); 333 334 if (TEST_EQ_4V(tmp, ctx->Color.BlendColor)) 335 return; 336 337 FLUSH_VERTICES(ctx, _NEW_COLOR); 338 COPY_4FV( ctx->Color.BlendColor, tmp ); 339 340 if (ctx->Driver.BlendColor) 341 (*ctx->Driver.BlendColor)(ctx, tmp); 342} 343 344 345void 346_mesa_AlphaFunc( GLenum func, GLclampf ref ) 347{ 348 GET_CURRENT_CONTEXT(ctx); 349 GLchan cref; 350 ASSERT_OUTSIDE_BEGIN_END(ctx); 351 352 switch (func) { 353 case GL_NEVER: 354 case GL_LESS: 355 case GL_EQUAL: 356 case GL_LEQUAL: 357 case GL_GREATER: 358 case GL_NOTEQUAL: 359 case GL_GEQUAL: 360 case GL_ALWAYS: 361 /* convert float alpha ref to GLchan type */ 362 UNCLAMPED_FLOAT_TO_CHAN(cref, ref); 363 364 if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == cref) 365 return; 366 367 FLUSH_VERTICES(ctx, _NEW_COLOR); 368 ctx->Color.AlphaFunc = func; 369 ctx->Color.AlphaRef = cref; 370 371 if (ctx->Driver.AlphaFunc) 372 ctx->Driver.AlphaFunc(ctx, func, cref); 373 return; 374 375 default: 376 _mesa_error( ctx, GL_INVALID_ENUM, "glAlphaFunc(func)" ); 377 return; 378 } 379} 380 381 382void 383_mesa_LogicOp( GLenum opcode ) 384{ 385 GET_CURRENT_CONTEXT(ctx); 386 ASSERT_OUTSIDE_BEGIN_END(ctx); 387 388 switch (opcode) { 389 case GL_CLEAR: 390 case GL_SET: 391 case GL_COPY: 392 case GL_COPY_INVERTED: 393 case GL_NOOP: 394 case GL_INVERT: 395 case GL_AND: 396 case GL_NAND: 397 case GL_OR: 398 case GL_NOR: 399 case GL_XOR: 400 case GL_EQUIV: 401 case GL_AND_REVERSE: 402 case GL_AND_INVERTED: 403 case GL_OR_REVERSE: 404 case GL_OR_INVERTED: 405 break; 406 default: 407 _mesa_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); 408 return; 409 } 410 411 if (ctx->Color.LogicOp == opcode) 412 return; 413 414 FLUSH_VERTICES(ctx, _NEW_COLOR); 415 ctx->Color.LogicOp = opcode; 416 417 if (ctx->Driver.LogicOpcode) 418 ctx->Driver.LogicOpcode( ctx, opcode ); 419} 420 421 422void 423_mesa_IndexMask( GLuint mask ) 424{ 425 GET_CURRENT_CONTEXT(ctx); 426 ASSERT_OUTSIDE_BEGIN_END(ctx); 427 428 if (ctx->Color.IndexMask == mask) 429 return; 430 431 FLUSH_VERTICES(ctx, _NEW_COLOR); 432 ctx->Color.IndexMask = mask; 433 434 if (ctx->Driver.IndexMask) 435 ctx->Driver.IndexMask( ctx, mask ); 436} 437 438 439void 440_mesa_ColorMask( GLboolean red, GLboolean green, 441 GLboolean blue, GLboolean alpha ) 442{ 443 GET_CURRENT_CONTEXT(ctx); 444 GLubyte tmp[4]; 445 ASSERT_OUTSIDE_BEGIN_END(ctx); 446 447 if (MESA_VERBOSE & VERBOSE_API) 448 fprintf(stderr, "glColorMask %d %d %d %d\n", red, green, blue, alpha); 449 450 /* Shouldn't have any information about channel depth in core mesa 451 * -- should probably store these as the native booleans: 452 */ 453 tmp[RCOMP] = red ? 0xff : 0x0; 454 tmp[GCOMP] = green ? 0xff : 0x0; 455 tmp[BCOMP] = blue ? 0xff : 0x0; 456 tmp[ACOMP] = alpha ? 0xff : 0x0; 457 458 if (TEST_EQ_4UBV(tmp, ctx->Color.ColorMask)) 459 return; 460 461 FLUSH_VERTICES(ctx, _NEW_COLOR); 462 COPY_4UBV(ctx->Color.ColorMask, tmp); 463 464 if (ctx->Driver.ColorMask) 465 ctx->Driver.ColorMask( ctx, red, green, blue, alpha ); 466} 467