blend.c revision ead285a9266bb5f80e68de122490a6afb88df6f3
1/* $Id: blend.c,v 1.13 2000/02/24 22:04:03 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.3 6 * 7 * Copyright (C) 1999 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 29#ifdef PC_HEADER 30#include "all.h" 31#else 32#include "glheader.h" 33#include "alphabuf.h" 34#include "blend.h" 35#include "context.h" 36#include "enums.h" 37#include "macros.h" 38#include "pb.h" 39#include "span.h" 40#include "types.h" 41#endif 42 43 44void 45_mesa_BlendFunc( GLenum sfactor, GLenum dfactor ) 46{ 47 GET_CURRENT_CONTEXT(ctx); 48 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc"); 49 50 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 51 fprintf(stderr, "glBlendFunc %s %s\n", 52 gl_lookup_enum_by_nr(sfactor), 53 gl_lookup_enum_by_nr(dfactor)); 54 55 switch (sfactor) { 56 case GL_ZERO: 57 case GL_ONE: 58 case GL_DST_COLOR: 59 case GL_ONE_MINUS_DST_COLOR: 60 case GL_SRC_ALPHA: 61 case GL_ONE_MINUS_SRC_ALPHA: 62 case GL_DST_ALPHA: 63 case GL_ONE_MINUS_DST_ALPHA: 64 case GL_SRC_ALPHA_SATURATE: 65 case GL_CONSTANT_COLOR: 66 case GL_ONE_MINUS_CONSTANT_COLOR: 67 case GL_CONSTANT_ALPHA: 68 case GL_ONE_MINUS_CONSTANT_ALPHA: 69 ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor; 70 break; 71 default: 72 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" ); 73 return; 74 } 75 76 switch (dfactor) { 77 case GL_ZERO: 78 case GL_ONE: 79 case GL_SRC_COLOR: 80 case GL_ONE_MINUS_SRC_COLOR: 81 case GL_SRC_ALPHA: 82 case GL_ONE_MINUS_SRC_ALPHA: 83 case GL_DST_ALPHA: 84 case GL_ONE_MINUS_DST_ALPHA: 85 case GL_CONSTANT_COLOR: 86 case GL_ONE_MINUS_CONSTANT_COLOR: 87 case GL_CONSTANT_ALPHA: 88 case GL_ONE_MINUS_CONSTANT_ALPHA: 89 ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor; 90 break; 91 default: 92 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" ); 93 return; 94 } 95 96 if (ctx->Driver.BlendFunc) { 97 (*ctx->Driver.BlendFunc)( ctx, sfactor, dfactor ); 98 } 99 100 ctx->Color.BlendFunc = NULL; 101 ctx->NewState |= NEW_RASTER_OPS; 102} 103 104 105/* GL_EXT_blend_func_separate */ 106void 107_mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB, 108 GLenum sfactorA, GLenum dfactorA ) 109{ 110 GET_CURRENT_CONTEXT(ctx); 111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate"); 112 113 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 114 fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n", 115 gl_lookup_enum_by_nr(sfactorRGB), 116 gl_lookup_enum_by_nr(dfactorRGB), 117 gl_lookup_enum_by_nr(sfactorA), 118 gl_lookup_enum_by_nr(dfactorA)); 119 120 switch (sfactorRGB) { 121 case GL_ZERO: 122 case GL_ONE: 123 case GL_DST_COLOR: 124 case GL_ONE_MINUS_DST_COLOR: 125 case GL_SRC_ALPHA: 126 case GL_ONE_MINUS_SRC_ALPHA: 127 case GL_DST_ALPHA: 128 case GL_ONE_MINUS_DST_ALPHA: 129 case GL_SRC_ALPHA_SATURATE: 130 case GL_CONSTANT_COLOR: 131 case GL_ONE_MINUS_CONSTANT_COLOR: 132 case GL_CONSTANT_ALPHA: 133 case GL_ONE_MINUS_CONSTANT_ALPHA: 134 ctx->Color.BlendSrcRGB = sfactorRGB; 135 break; 136 default: 137 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" ); 138 return; 139 } 140 141 switch (dfactorRGB) { 142 case GL_ZERO: 143 case GL_ONE: 144 case GL_SRC_COLOR: 145 case GL_ONE_MINUS_SRC_COLOR: 146 case GL_SRC_ALPHA: 147 case GL_ONE_MINUS_SRC_ALPHA: 148 case GL_DST_ALPHA: 149 case GL_ONE_MINUS_DST_ALPHA: 150 case GL_CONSTANT_COLOR: 151 case GL_ONE_MINUS_CONSTANT_COLOR: 152 case GL_CONSTANT_ALPHA: 153 case GL_ONE_MINUS_CONSTANT_ALPHA: 154 ctx->Color.BlendDstRGB = dfactorRGB; 155 break; 156 default: 157 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" ); 158 return; 159 } 160 161 switch (sfactorA) { 162 case GL_ZERO: 163 case GL_ONE: 164 case GL_DST_COLOR: 165 case GL_ONE_MINUS_DST_COLOR: 166 case GL_SRC_ALPHA: 167 case GL_ONE_MINUS_SRC_ALPHA: 168 case GL_DST_ALPHA: 169 case GL_ONE_MINUS_DST_ALPHA: 170 case GL_SRC_ALPHA_SATURATE: 171 case GL_CONSTANT_COLOR: 172 case GL_ONE_MINUS_CONSTANT_COLOR: 173 case GL_CONSTANT_ALPHA: 174 case GL_ONE_MINUS_CONSTANT_ALPHA: 175 ctx->Color.BlendSrcA = sfactorA; 176 break; 177 default: 178 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" ); 179 return; 180 } 181 182 switch (dfactorA) { 183 case GL_ZERO: 184 case GL_ONE: 185 case GL_SRC_COLOR: 186 case GL_ONE_MINUS_SRC_COLOR: 187 case GL_SRC_ALPHA: 188 case GL_ONE_MINUS_SRC_ALPHA: 189 case GL_DST_ALPHA: 190 case GL_ONE_MINUS_DST_ALPHA: 191 case GL_CONSTANT_COLOR: 192 case GL_ONE_MINUS_CONSTANT_COLOR: 193 case GL_CONSTANT_ALPHA: 194 case GL_ONE_MINUS_CONSTANT_ALPHA: 195 ctx->Color.BlendDstA = dfactorA; 196 break; 197 default: 198 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" ); 199 return; 200 } 201 202 ctx->Color.BlendFunc = NULL; 203 ctx->NewState |= NEW_RASTER_OPS; 204 205 if (ctx->Driver.BlendFuncSeparate) { 206 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB, 207 sfactorA, dfactorA ); 208 } 209} 210 211 212 213/* This is really an extension function! */ 214void 215_mesa_BlendEquation( GLenum mode ) 216{ 217 GET_CURRENT_CONTEXT(ctx); 218 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation"); 219 220 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 221 fprintf(stderr, "glBlendEquation %s\n", 222 gl_lookup_enum_by_nr(mode)); 223 224 225 switch (mode) { 226 case GL_MIN_EXT: 227 case GL_MAX_EXT: 228 case GL_LOGIC_OP: 229 case GL_FUNC_ADD_EXT: 230 case GL_FUNC_SUBTRACT_EXT: 231 case GL_FUNC_REVERSE_SUBTRACT_EXT: 232 ctx->Color.BlendEquation = mode; 233 break; 234 default: 235 gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" ); 236 return; 237 } 238 239 /* This is needed to support 1.1's RGB logic ops AND 240 * 1.0's blending logicops. 241 */ 242 if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) { 243 ctx->Color.ColorLogicOpEnabled = GL_TRUE; 244 } 245 else { 246 ctx->Color.ColorLogicOpEnabled = GL_FALSE; 247 } 248 249 ctx->Color.BlendFunc = NULL; 250 ctx->NewState |= NEW_RASTER_OPS; 251 252 if (ctx->Driver.BlendEquation) 253 ctx->Driver.BlendEquation( ctx, mode ); 254} 255 256 257 258void 259_mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha ) 260{ 261 GET_CURRENT_CONTEXT(ctx); 262 ctx->Color.BlendColor[0] = CLAMP( red, 0.0F, 1.0F ); 263 ctx->Color.BlendColor[1] = CLAMP( green, 0.0F, 1.0F ); 264 ctx->Color.BlendColor[2] = CLAMP( blue, 0.0F, 1.0F ); 265 ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0F, 1.0F ); 266} 267 268#ifdef USE_MMX_ASM 269#define _BLENDAPI _ASMAPI 270#else 271#define _BLENDAPI 272#endif 273 274/* 275 * Common transparency blending mode. 276 */ 277static void _BLENDAPI 278blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[], 279 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 280{ 281 GLuint i; 282 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); 283 ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA); 284 ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA); 285 (void) ctx; 286 287 for (i=0;i<n;i++) { 288 if (mask[i]) { 289 const GLint t = rgba[i][ACOMP]; /* t in [0,255] */ 290 if (t == 0) { 291 /* 0% alpha */ 292 rgba[i][RCOMP] = dest[i][RCOMP]; 293 rgba[i][GCOMP] = dest[i][GCOMP]; 294 rgba[i][BCOMP] = dest[i][BCOMP]; 295 rgba[i][ACOMP] = dest[i][ACOMP]; 296 } 297 else if (t == CHAN_MAX) { 298 /* 100% alpha, no-op */ 299 } 300 else { 301 const GLint s = CHAN_MAX - t; 302 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8; 303 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8; 304 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8; 305 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8; 306 ASSERT(r <= CHAN_MAX); 307 ASSERT(g <= CHAN_MAX); 308 ASSERT(b <= CHAN_MAX); 309 ASSERT(a <= CHAN_MAX); 310 rgba[i][RCOMP] = (GLubyte) r; 311 rgba[i][GCOMP] = (GLubyte) g; 312 rgba[i][BCOMP] = (GLubyte) b; 313 rgba[i][ACOMP] = (GLubyte) a; 314 } 315 } 316 } 317} 318 319 320 321/* 322 * Add src and dest. 323 */ 324static void _BLENDAPI 325blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[], 326 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 327{ 328 GLuint i; 329 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT); 330 ASSERT(ctx->Color.BlendSrcRGB==GL_ONE); 331 ASSERT(ctx->Color.BlendDstRGB==GL_ONE); 332 (void) ctx; 333 334 for (i=0;i<n;i++) { 335 if (mask[i]) { 336 GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; 337 GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; 338 GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; 339 GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; 340 rgba[i][RCOMP] = (GLubyte) MIN2( r, CHAN_MAX ); 341 rgba[i][GCOMP] = (GLubyte) MIN2( g, CHAN_MAX ); 342 rgba[i][BCOMP] = (GLubyte) MIN2( b, CHAN_MAX ); 343 rgba[i][ACOMP] = (GLubyte) MIN2( a, CHAN_MAX ); 344 } 345 } 346} 347 348 349 350/* 351 * Blend min function (for GL_EXT_blend_minmax) 352 */ 353static void _BLENDAPI 354blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[], 355 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 356{ 357 GLuint i; 358 ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT); 359 (void) ctx; 360 361 for (i=0;i<n;i++) { 362 if (mask[i]) { 363 rgba[i][RCOMP] = (GLubyte) MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 364 rgba[i][GCOMP] = (GLubyte) MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 365 rgba[i][BCOMP] = (GLubyte) MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 366 rgba[i][ACOMP] = (GLubyte) MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 367 } 368 } 369} 370 371 372 373/* 374 * Blend max function (for GL_EXT_blend_minmax) 375 */ 376static void _BLENDAPI 377blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[], 378 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 379{ 380 GLuint i; 381 ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT); 382 (void) ctx; 383 384 for (i=0;i<n;i++) { 385 if (mask[i]) { 386 rgba[i][RCOMP] = (GLubyte) MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 387 rgba[i][GCOMP] = (GLubyte) MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 388 rgba[i][BCOMP] = (GLubyte) MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 389 rgba[i][ACOMP] = (GLubyte) MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 390 } 391 } 392} 393 394 395 396/* 397 * Modulate: result = src * dest 398 */ 399static void _BLENDAPI 400blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[], 401 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 402{ 403 GLuint i; 404 (void) ctx; 405 406 for (i=0;i<n;i++) { 407 if (mask[i]) { 408 GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8; 409 GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8; 410 GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8; 411 GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8; 412 rgba[i][RCOMP] = (GLubyte) r; 413 rgba[i][GCOMP] = (GLubyte) g; 414 rgba[i][BCOMP] = (GLubyte) b; 415 rgba[i][ACOMP] = (GLubyte) a; 416 } 417 } 418} 419 420 421 422/* 423 * General case blend pixels. 424 * Input: n - number of pixels 425 * mask - the usual write mask 426 * In/Out: rgba - the incoming and modified pixels 427 * Input: dest - the pixels from the dest color buffer 428 */ 429static void _BLENDAPI 430blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[], 431 GLubyte rgba[][4], CONST GLubyte dest[][4] ) 432{ 433 GLfloat rscale = 1.0F / CHAN_MAXF; 434 GLfloat gscale = 1.0F / CHAN_MAXF; 435 GLfloat bscale = 1.0F / CHAN_MAXF; 436 GLfloat ascale = 1.0F / CHAN_MAXF; 437 GLuint i; 438 439 for (i=0;i<n;i++) { 440 if (mask[i]) { 441 GLint Rs, Gs, Bs, As; /* Source colors */ 442 GLint Rd, Gd, Bd, Ad; /* Dest colors */ 443 GLfloat sR, sG, sB, sA; /* Source scaling */ 444 GLfloat dR, dG, dB, dA; /* Dest scaling */ 445 GLfloat r, g, b, a; 446 447 /* Source Color */ 448 Rs = rgba[i][RCOMP]; 449 Gs = rgba[i][GCOMP]; 450 Bs = rgba[i][BCOMP]; 451 As = rgba[i][ACOMP]; 452 453 /* Frame buffer color */ 454 Rd = dest[i][RCOMP]; 455 Gd = dest[i][GCOMP]; 456 Bd = dest[i][BCOMP]; 457 Ad = dest[i][ACOMP]; 458 459 /* Source RGB factor */ 460 switch (ctx->Color.BlendSrcRGB) { 461 case GL_ZERO: 462 sR = sG = sB = 0.0F; 463 break; 464 case GL_ONE: 465 sR = sG = sB = 1.0F; 466 break; 467 case GL_DST_COLOR: 468 sR = (GLfloat) Rd * rscale; 469 sG = (GLfloat) Gd * gscale; 470 sB = (GLfloat) Bd * bscale; 471 break; 472 case GL_ONE_MINUS_DST_COLOR: 473 sR = 1.0F - (GLfloat) Rd * rscale; 474 sG = 1.0F - (GLfloat) Gd * gscale; 475 sB = 1.0F - (GLfloat) Bd * bscale; 476 break; 477 case GL_SRC_ALPHA: 478 sR = sG = sB = (GLfloat) As * ascale; 479 break; 480 case GL_ONE_MINUS_SRC_ALPHA: 481 sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale; 482 break; 483 case GL_DST_ALPHA: 484 sR = sG = sB = (GLfloat) Ad * ascale; 485 break; 486 case GL_ONE_MINUS_DST_ALPHA: 487 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale; 488 break; 489 case GL_SRC_ALPHA_SATURATE: 490 if (As < CHAN_MAX - Ad) { 491 sR = sG = sB = (GLfloat) As * ascale; 492 } 493 else { 494 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale; 495 } 496 break; 497 case GL_CONSTANT_COLOR: 498 sR = ctx->Color.BlendColor[0]; 499 sG = ctx->Color.BlendColor[1]; 500 sB = ctx->Color.BlendColor[2]; 501 break; 502 case GL_ONE_MINUS_CONSTANT_COLOR: 503 sR = 1.0F - ctx->Color.BlendColor[0]; 504 sG = 1.0F - ctx->Color.BlendColor[1]; 505 sB = 1.0F - ctx->Color.BlendColor[2]; 506 break; 507 case GL_CONSTANT_ALPHA: 508 sR = sG = sB = ctx->Color.BlendColor[3]; 509 break; 510 case GL_ONE_MINUS_CONSTANT_ALPHA: 511 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3]; 512 break; 513 default: 514 /* this should never happen */ 515 gl_problem(ctx, "Bad blend source RGB factor in do_blend"); 516 return; 517 } 518 519 /* Source Alpha factor */ 520 switch (ctx->Color.BlendSrcA) { 521 case GL_ZERO: 522 sA = 0.0F; 523 break; 524 case GL_ONE: 525 sA = 1.0F; 526 break; 527 case GL_DST_COLOR: 528 sA = (GLfloat) Ad * ascale; 529 break; 530 case GL_ONE_MINUS_DST_COLOR: 531 sA = 1.0F - (GLfloat) Ad * ascale; 532 break; 533 case GL_SRC_ALPHA: 534 sA = (GLfloat) As * ascale; 535 break; 536 case GL_ONE_MINUS_SRC_ALPHA: 537 sA = (GLfloat) 1.0F - (GLfloat) As * ascale; 538 break; 539 case GL_DST_ALPHA: 540 sA =(GLfloat) Ad * ascale; 541 break; 542 case GL_ONE_MINUS_DST_ALPHA: 543 sA = 1.0F - (GLfloat) Ad * ascale; 544 break; 545 case GL_SRC_ALPHA_SATURATE: 546 sA = 1.0; 547 break; 548 case GL_CONSTANT_COLOR: 549 sA = ctx->Color.BlendColor[3]; 550 break; 551 case GL_ONE_MINUS_CONSTANT_COLOR: 552 sA = 1.0F - ctx->Color.BlendColor[3]; 553 break; 554 case GL_CONSTANT_ALPHA: 555 sA = ctx->Color.BlendColor[3]; 556 break; 557 case GL_ONE_MINUS_CONSTANT_ALPHA: 558 sA = 1.0F - ctx->Color.BlendColor[3]; 559 break; 560 default: 561 /* this should never happen */ 562 sA = 0.0F; 563 gl_problem(ctx, "Bad blend source A factor in do_blend"); 564 } 565 566 /* Dest RGB factor */ 567 switch (ctx->Color.BlendDstRGB) { 568 case GL_ZERO: 569 dR = dG = dB = 0.0F; 570 break; 571 case GL_ONE: 572 dR = dG = dB = 1.0F; 573 break; 574 case GL_SRC_COLOR: 575 dR = (GLfloat) Rs * rscale; 576 dG = (GLfloat) Gs * gscale; 577 dB = (GLfloat) Bs * bscale; 578 break; 579 case GL_ONE_MINUS_SRC_COLOR: 580 dR = 1.0F - (GLfloat) Rs * rscale; 581 dG = 1.0F - (GLfloat) Gs * gscale; 582 dB = 1.0F - (GLfloat) Bs * bscale; 583 break; 584 case GL_SRC_ALPHA: 585 dR = dG = dB = (GLfloat) As * ascale; 586 break; 587 case GL_ONE_MINUS_SRC_ALPHA: 588 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale; 589 break; 590 case GL_DST_ALPHA: 591 dR = dG = dB = (GLfloat) Ad * ascale; 592 break; 593 case GL_ONE_MINUS_DST_ALPHA: 594 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale; 595 break; 596 case GL_CONSTANT_COLOR: 597 dR = ctx->Color.BlendColor[0]; 598 dG = ctx->Color.BlendColor[1]; 599 dB = ctx->Color.BlendColor[2]; 600 break; 601 case GL_ONE_MINUS_CONSTANT_COLOR: 602 dR = 1.0F - ctx->Color.BlendColor[0]; 603 dG = 1.0F - ctx->Color.BlendColor[1]; 604 dB = 1.0F - ctx->Color.BlendColor[2]; 605 break; 606 case GL_CONSTANT_ALPHA: 607 dR = dG = dB = ctx->Color.BlendColor[3]; 608 break; 609 case GL_ONE_MINUS_CONSTANT_ALPHA: 610 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale; 611 break; 612 default: 613 /* this should never happen */ 614 dR = dG = dB = 0.0F; 615 gl_problem(ctx, "Bad blend dest RGB factor in do_blend"); 616 } 617 618 /* Dest Alpha factor */ 619 switch (ctx->Color.BlendDstA) { 620 case GL_ZERO: 621 dA = 0.0F; 622 break; 623 case GL_ONE: 624 dA = 1.0F; 625 break; 626 case GL_SRC_COLOR: 627 dA = (GLfloat) As * ascale; 628 break; 629 case GL_ONE_MINUS_SRC_COLOR: 630 dA = 1.0F - (GLfloat) As * ascale; 631 break; 632 case GL_SRC_ALPHA: 633 dA = (GLfloat) As * ascale; 634 break; 635 case GL_ONE_MINUS_SRC_ALPHA: 636 dA = (GLfloat) 1.0F - (GLfloat) As * ascale; 637 break; 638 case GL_DST_ALPHA: 639 dA = (GLfloat) Ad * ascale; 640 break; 641 case GL_ONE_MINUS_DST_ALPHA: 642 dA = 1.0F - (GLfloat) Ad * ascale; 643 break; 644 case GL_CONSTANT_COLOR: 645 dA = ctx->Color.BlendColor[3]; 646 break; 647 case GL_ONE_MINUS_CONSTANT_COLOR: 648 dA = 1.0F - ctx->Color.BlendColor[3]; 649 break; 650 case GL_CONSTANT_ALPHA: 651 dA = ctx->Color.BlendColor[3]; 652 break; 653 case GL_ONE_MINUS_CONSTANT_ALPHA: 654 dA = 1.0F - ctx->Color.BlendColor[3] * ascale; 655 break; 656 default: 657 /* this should never happen */ 658 dA = 0.0F; 659 gl_problem(ctx, "Bad blend dest A factor in do_blend"); 660 return; 661 } 662 663 /* Due to round-off problems we have to clamp against zero. */ 664 /* Optimization: we don't have to do this for all src & dst factors */ 665 if (dA < 0.0F) dA = 0.0F; 666 if (dR < 0.0F) dR = 0.0F; 667 if (dG < 0.0F) dG = 0.0F; 668 if (dB < 0.0F) dB = 0.0F; 669 if (sA < 0.0F) sA = 0.0F; 670 if (sR < 0.0F) sR = 0.0F; 671 if (sG < 0.0F) sG = 0.0F; 672 if (sB < 0.0F) sB = 0.0F; 673 674 ASSERT( sR <= 1.0 ); 675 ASSERT( sG <= 1.0 ); 676 ASSERT( sB <= 1.0 ); 677 ASSERT( sA <= 1.0 ); 678 ASSERT( dR <= 1.0 ); 679 ASSERT( dG <= 1.0 ); 680 ASSERT( dB <= 1.0 ); 681 ASSERT( dA <= 1.0 ); 682 683 /* compute blended color */ 684 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 685 r = Rs * sR + Rd * dR; 686 g = Gs * sG + Gd * dG; 687 b = Bs * sB + Bd * dB; 688 a = As * sA + Ad * dA; 689 } 690 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) { 691 r = Rs * sR - Rd * dR; 692 g = Gs * sG - Gd * dG; 693 b = Bs * sB - Bd * dB; 694 a = As * sA - Ad * dA; 695 } 696 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) { 697 r = Rd * dR - Rs * sR; 698 g = Gd * dG - Gs * sG; 699 b = Bd * dB - Bs * sB; 700 a = Ad * dA - As * sA; 701 } 702 else { 703 /* should never get here */ 704 r = g = b = a = 0.0F; /* silence uninitialized var warning */ 705 gl_problem(ctx, "unexpected BlendEquation in blend_general()"); 706 } 707 708 /* final clamping */ 709 rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, CHAN_MAXF ); 710 rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, CHAN_MAXF ); 711 rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, CHAN_MAXF ); 712 rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, CHAN_MAXF ); 713 } 714 } 715} 716 717 718 719#if defined(USE_MMX_ASM) 720#include "X86/mmx.h" 721#include "X86/common_x86asm.h" 722#endif 723 724 725/* 726 * Analyze current blending parameters to pick fastest blending function. 727 * Result: the ctx->Color.BlendFunc pointer is updated. 728 */ 729static void set_blend_function( GLcontext *ctx ) 730{ 731 const GLenum eq = ctx->Color.BlendEquation; 732 const GLenum srcRGB = ctx->Color.BlendSrcRGB; 733 const GLenum dstRGB = ctx->Color.BlendDstRGB; 734 const GLenum srcA = ctx->Color.BlendSrcA; 735 const GLenum dstA = ctx->Color.BlendDstA; 736 737#if defined(USE_MMX_ASM) 738 /* Hmm. A table here would have 12^4 == way too many entries. 739 * Provide a hook for MMX instead. 740 */ 741 if (gl_x86_cpu_features & GL_CPU_MMX) { 742 gl_mmx_set_blend_function (ctx); 743 } 744 else 745#endif 746 if (srcRGB != srcA || dstRGB != dstA) { 747 ctx->Color.BlendFunc = blend_general; 748 } 749 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA 750 && dstRGB==GL_ONE_MINUS_SRC_ALPHA) { 751 ctx->Color.BlendFunc = blend_transparency; 752 } 753 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) { 754 ctx->Color.BlendFunc = blend_add; 755 } 756 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT) 757 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR)) 758 || 759 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT) 760 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) { 761 ctx->Color.BlendFunc = blend_modulate; 762 } 763 else if (eq==GL_MIN_EXT) { 764 ctx->Color.BlendFunc = blend_min; 765 } 766 else if (eq==GL_MAX_EXT) { 767 ctx->Color.BlendFunc = blend_max; 768 } 769 else { 770 ctx->Color.BlendFunc = blend_general; 771 } 772} 773 774 775 776/* 777 * Apply the blending operator to a span of pixels. 778 * Input: n - number of pixels in span 779 * x, y - location of leftmost pixel in span in window coords. 780 * mask - boolean mask indicating which pixels to blend. 781 * In/Out: rgba - pixel values 782 */ 783void 784_mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y, 785 GLubyte rgba[][4], const GLubyte mask[] ) 786{ 787 GLubyte dest[MAX_WIDTH][4]; 788 789 /* Check if device driver can do the work */ 790 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) { 791 return; 792 } 793 794 /* Read span of current frame buffer pixels */ 795 gl_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest ); 796 797 if (!ctx->Color.BlendFunc) 798 set_blend_function(ctx); 799 800 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest ); 801} 802 803 804 805 806 807/* 808 * Apply the blending operator to an array of pixels. 809 * Input: n - number of pixels in span 810 * x, y - array of pixel locations 811 * mask - boolean mask indicating which pixels to blend. 812 * In/Out: rgba - pixel values 813 */ 814void 815_mesa_blend_pixels( GLcontext *ctx, 816 GLuint n, const GLint x[], const GLint y[], 817 GLubyte rgba[][4], const GLubyte mask[] ) 818{ 819 GLubyte dest[PB_SIZE][4]; 820 821 /* Check if device driver can do the work */ 822 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) { 823 return; 824 } 825 826 /* Read pixels from current color buffer */ 827 (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask ); 828 if (ctx->RasterMask & ALPHABUF_BIT) { 829 gl_read_alpha_pixels( ctx, n, x, y, dest, mask ); 830 } 831 832 if (!ctx->Color.BlendFunc) 833 set_blend_function(ctx); 834 835 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest ); 836} 837