1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26 /** 27 * \file swrast/s_blend.c 28 * \brief software blending. 29 * \author Brian Paul 30 * 31 * Only a few blend modes have been optimized (min, max, transparency, add) 32 * more optimized cases can easily be added if needed. 33 * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example. 34 */ 35 36 37 38 #include "main/glheader.h" 39 #include "main/context.h" 40 #include "main/colormac.h" 41 #include "main/macros.h" 42 43 #include "s_blend.h" 44 #include "s_context.h" 45 #include "s_span.h" 46 47 48 #if defined(USE_MMX_ASM) 49 #include "x86/mmx.h" 50 #include "x86/common_x86_asm.h" 51 #endif 52 53 54 /** 55 * Integer divide by 255 56 * Declare "int divtemp" before using. 57 * This satisfies Glean and should be reasonably fast. 58 * Contributed by Nathan Hand. 59 */ 60 #define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16) 61 62 63 64 /** 65 * Special case for glBlendFunc(GL_ZERO, GL_ONE). 66 * No-op means the framebuffer values remain unchanged. 67 * Any chanType ok. 68 */ 69 static void 70 blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[], 71 GLvoid *src, const GLvoid *dst, GLenum chanType) 72 { 73 GLint bytes; 74 75 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 76 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 77 assert(ctx->Color.Blend[0].SrcRGB == GL_ZERO); 78 assert(ctx->Color.Blend[0].DstRGB == GL_ONE); 79 (void) ctx; 80 81 /* just memcpy */ 82 if (chanType == GL_UNSIGNED_BYTE) 83 bytes = 4 * n * sizeof(GLubyte); 84 else if (chanType == GL_UNSIGNED_SHORT) 85 bytes = 4 * n * sizeof(GLushort); 86 else 87 bytes = 4 * n * sizeof(GLfloat); 88 89 memcpy(src, dst, bytes); 90 } 91 92 93 /** 94 * Special case for glBlendFunc(GL_ONE, GL_ZERO) 95 * Any chanType ok. 96 */ 97 static void 98 blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[], 99 GLvoid *src, const GLvoid *dst, GLenum chanType) 100 { 101 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 102 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 103 assert(ctx->Color.Blend[0].SrcRGB == GL_ONE); 104 assert(ctx->Color.Blend[0].DstRGB == GL_ZERO); 105 (void) ctx; 106 (void) n; 107 (void) mask; 108 (void) src; 109 (void) dst; 110 } 111 112 113 /** 114 * Common transparency blending mode: 115 * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). 116 */ 117 static void 118 blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[], 119 GLvoid *src, const GLvoid *dst, GLenum chanType) 120 { 121 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 122 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 123 GLuint i; 124 125 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 126 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 127 assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 128 assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 129 assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 130 assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 131 assert(chanType == GL_UNSIGNED_BYTE); 132 133 (void) ctx; 134 135 for (i = 0; i < n; i++) { 136 if (mask[i]) { 137 const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */ 138 if (t == 0) { 139 /* 0% alpha */ 140 COPY_4UBV(rgba[i], dest[i]); 141 } 142 else if (t != 255) { 143 GLint divtemp; 144 const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP]; 145 const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP]; 146 const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP]; 147 const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; 148 assert(r <= 255); 149 assert(g <= 255); 150 assert(b <= 255); 151 assert(a <= 255); 152 rgba[i][RCOMP] = (GLubyte) r; 153 rgba[i][GCOMP] = (GLubyte) g; 154 rgba[i][BCOMP] = (GLubyte) b; 155 rgba[i][ACOMP] = (GLubyte) a; 156 } 157 } 158 } 159 } 160 161 162 static void 163 blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[], 164 GLvoid *src, const GLvoid *dst, GLenum chanType) 165 { 166 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 167 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 168 GLuint i; 169 170 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 171 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 172 assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 173 assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 174 assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 175 assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 176 assert(chanType == GL_UNSIGNED_SHORT); 177 178 (void) ctx; 179 180 for (i = 0; i < n; i++) { 181 if (mask[i]) { 182 const GLint t = rgba[i][ACOMP]; 183 if (t == 0) { 184 /* 0% alpha */ 185 COPY_4V(rgba[i], dest[i]); 186 } 187 else if (t != 65535) { 188 const GLfloat tt = (GLfloat) t / 65535.0F; 189 GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]); 190 GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]); 191 GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]); 192 GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]); 193 ASSIGN_4V(rgba[i], r, g, b, a); 194 } 195 } 196 } 197 } 198 199 200 static void 201 blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], 202 GLvoid *src, const GLvoid *dst, GLenum chanType) 203 { 204 GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 205 const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 206 GLuint i; 207 208 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 209 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 210 assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 211 assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 212 assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 213 assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 214 assert(chanType == GL_FLOAT); 215 216 (void) ctx; 217 218 for (i = 0; i < n; i++) { 219 if (mask[i]) { 220 const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */ 221 if (t == 0.0F) { 222 /* 0% alpha */ 223 COPY_4V(rgba[i], dest[i]); 224 } 225 else if (t != 1.0F) { 226 GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP]; 227 GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP]; 228 GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP]; 229 GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP]; 230 ASSIGN_4V(rgba[i], r, g, b, a); 231 } 232 } 233 } 234 } 235 236 237 238 /** 239 * Add src and dest: glBlendFunc(GL_ONE, GL_ONE). 240 * Any chanType ok. 241 */ 242 static void 243 blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[], 244 GLvoid *src, const GLvoid *dst, GLenum chanType) 245 { 246 GLuint i; 247 248 assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 249 assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 250 assert(ctx->Color.Blend[0].SrcRGB == GL_ONE); 251 assert(ctx->Color.Blend[0].DstRGB == GL_ONE); 252 (void) ctx; 253 254 if (chanType == GL_UNSIGNED_BYTE) { 255 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 256 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 257 for (i=0;i<n;i++) { 258 if (mask[i]) { 259 GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; 260 GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; 261 GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; 262 GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; 263 rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 ); 264 rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 ); 265 rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 ); 266 rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 ); 267 } 268 } 269 } 270 else if (chanType == GL_UNSIGNED_SHORT) { 271 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 272 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 273 for (i=0;i<n;i++) { 274 if (mask[i]) { 275 GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; 276 GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; 277 GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; 278 GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; 279 rgba[i][RCOMP] = (GLshort) MIN2( r, 255 ); 280 rgba[i][GCOMP] = (GLshort) MIN2( g, 255 ); 281 rgba[i][BCOMP] = (GLshort) MIN2( b, 255 ); 282 rgba[i][ACOMP] = (GLshort) MIN2( a, 255 ); 283 } 284 } 285 } 286 else { 287 GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 288 const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 289 assert(chanType == GL_FLOAT); 290 for (i=0;i<n;i++) { 291 if (mask[i]) { 292 /* don't RGB clamp to max */ 293 rgba[i][RCOMP] += dest[i][RCOMP]; 294 rgba[i][GCOMP] += dest[i][GCOMP]; 295 rgba[i][BCOMP] += dest[i][BCOMP]; 296 rgba[i][ACOMP] += dest[i][ACOMP]; 297 } 298 } 299 } 300 } 301 302 303 304 /** 305 * Blend min function. 306 * Any chanType ok. 307 */ 308 static void 309 blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[], 310 GLvoid *src, const GLvoid *dst, GLenum chanType) 311 { 312 GLuint i; 313 assert(ctx->Color.Blend[0].EquationRGB == GL_MIN); 314 assert(ctx->Color.Blend[0].EquationA == GL_MIN); 315 (void) ctx; 316 317 if (chanType == GL_UNSIGNED_BYTE) { 318 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 319 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 320 for (i=0;i<n;i++) { 321 if (mask[i]) { 322 rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 323 rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 324 rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 325 rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 326 } 327 } 328 } 329 else if (chanType == GL_UNSIGNED_SHORT) { 330 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 331 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 332 for (i=0;i<n;i++) { 333 if (mask[i]) { 334 rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 335 rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 336 rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 337 rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 338 } 339 } 340 } 341 else { 342 GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 343 const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 344 assert(chanType == GL_FLOAT); 345 for (i=0;i<n;i++) { 346 if (mask[i]) { 347 rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 348 rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 349 rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 350 rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 351 } 352 } 353 } 354 } 355 356 357 /** 358 * Blend max function. 359 * Any chanType ok. 360 */ 361 static void 362 blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[], 363 GLvoid *src, const GLvoid *dst, GLenum chanType) 364 { 365 GLuint i; 366 assert(ctx->Color.Blend[0].EquationRGB == GL_MAX); 367 assert(ctx->Color.Blend[0].EquationA == GL_MAX); 368 (void) ctx; 369 370 if (chanType == GL_UNSIGNED_BYTE) { 371 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 372 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 373 for (i=0;i<n;i++) { 374 if (mask[i]) { 375 rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 376 rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 377 rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 378 rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 379 } 380 } 381 } 382 else if (chanType == GL_UNSIGNED_SHORT) { 383 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 384 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 385 for (i=0;i<n;i++) { 386 if (mask[i]) { 387 rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 388 rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 389 rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 390 rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 391 } 392 } 393 } 394 else { 395 GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 396 const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 397 assert(chanType == GL_FLOAT); 398 for (i=0;i<n;i++) { 399 if (mask[i]) { 400 rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 401 rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 402 rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 403 rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 404 } 405 } 406 } 407 } 408 409 410 411 /** 412 * Modulate: result = src * dest 413 * Any chanType ok. 414 */ 415 static void 416 blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[], 417 GLvoid *src, const GLvoid *dst, GLenum chanType) 418 { 419 GLuint i; 420 (void) ctx; 421 422 if (chanType == GL_UNSIGNED_BYTE) { 423 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 424 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 425 for (i=0;i<n;i++) { 426 if (mask[i]) { 427 GLint divtemp; 428 rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]); 429 rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]); 430 rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]); 431 rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]); 432 } 433 } 434 } 435 else if (chanType == GL_UNSIGNED_SHORT) { 436 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 437 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 438 for (i=0;i<n;i++) { 439 if (mask[i]) { 440 rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16; 441 rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16; 442 rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16; 443 rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16; 444 } 445 } 446 } 447 else { 448 GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 449 const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 450 assert(chanType == GL_FLOAT); 451 for (i=0;i<n;i++) { 452 if (mask[i]) { 453 rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP]; 454 rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP]; 455 rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP]; 456 rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP]; 457 } 458 } 459 } 460 } 461 462 463 /** 464 * Do any blending operation, using floating point. 465 * \param n number of pixels 466 * \param mask fragment writemask array 467 * \param rgba array of incoming (and modified) pixels 468 * \param dest array of pixels from the dest color buffer 469 */ 470 static void 471 blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], 472 GLfloat rgba[][4], GLfloat dest[][4], 473 GLenum chanType) 474 { 475 GLuint i; 476 477 for (i = 0; i < n; i++) { 478 if (mask[i]) { 479 /* Incoming/source Color */ 480 const GLfloat Rs = rgba[i][RCOMP]; 481 const GLfloat Gs = rgba[i][GCOMP]; 482 const GLfloat Bs = rgba[i][BCOMP]; 483 const GLfloat As = rgba[i][ACOMP]; 484 485 /* Frame buffer/dest color */ 486 const GLfloat Rd = dest[i][RCOMP]; 487 const GLfloat Gd = dest[i][GCOMP]; 488 const GLfloat Bd = dest[i][BCOMP]; 489 const GLfloat Ad = dest[i][ACOMP]; 490 491 GLfloat sR, sG, sB, sA; /* Source factor */ 492 GLfloat dR, dG, dB, dA; /* Dest factor */ 493 GLfloat r, g, b, a; /* result color */ 494 495 /* XXX for the case of constant blend terms we could init 496 * the sX and dX variables just once before the loop. 497 */ 498 499 /* Source RGB factor */ 500 switch (ctx->Color.Blend[0].SrcRGB) { 501 case GL_ZERO: 502 sR = sG = sB = 0.0F; 503 break; 504 case GL_ONE: 505 sR = sG = sB = 1.0F; 506 break; 507 case GL_DST_COLOR: 508 sR = Rd; 509 sG = Gd; 510 sB = Bd; 511 break; 512 case GL_ONE_MINUS_DST_COLOR: 513 sR = 1.0F - Rd; 514 sG = 1.0F - Gd; 515 sB = 1.0F - Bd; 516 break; 517 case GL_SRC_ALPHA: 518 sR = sG = sB = As; 519 break; 520 case GL_ONE_MINUS_SRC_ALPHA: 521 sR = sG = sB = 1.0F - As; 522 break; 523 case GL_DST_ALPHA: 524 sR = sG = sB = Ad; 525 break; 526 case GL_ONE_MINUS_DST_ALPHA: 527 sR = sG = sB = 1.0F - Ad; 528 break; 529 case GL_SRC_ALPHA_SATURATE: 530 if (As < 1.0F - Ad) { 531 sR = sG = sB = As; 532 } 533 else { 534 sR = sG = sB = 1.0F - Ad; 535 } 536 break; 537 case GL_CONSTANT_COLOR: 538 sR = ctx->Color.BlendColor[0]; 539 sG = ctx->Color.BlendColor[1]; 540 sB = ctx->Color.BlendColor[2]; 541 break; 542 case GL_ONE_MINUS_CONSTANT_COLOR: 543 sR = 1.0F - ctx->Color.BlendColor[0]; 544 sG = 1.0F - ctx->Color.BlendColor[1]; 545 sB = 1.0F - ctx->Color.BlendColor[2]; 546 break; 547 case GL_CONSTANT_ALPHA: 548 sR = sG = sB = ctx->Color.BlendColor[3]; 549 break; 550 case GL_ONE_MINUS_CONSTANT_ALPHA: 551 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3]; 552 break; 553 case GL_SRC_COLOR: 554 sR = Rs; 555 sG = Gs; 556 sB = Bs; 557 break; 558 case GL_ONE_MINUS_SRC_COLOR: 559 sR = 1.0F - Rs; 560 sG = 1.0F - Gs; 561 sB = 1.0F - Bs; 562 break; 563 default: 564 /* this should never happen */ 565 _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float"); 566 return; 567 } 568 569 /* Source Alpha factor */ 570 switch (ctx->Color.Blend[0].SrcA) { 571 case GL_ZERO: 572 sA = 0.0F; 573 break; 574 case GL_ONE: 575 sA = 1.0F; 576 break; 577 case GL_DST_COLOR: 578 sA = Ad; 579 break; 580 case GL_ONE_MINUS_DST_COLOR: 581 sA = 1.0F - Ad; 582 break; 583 case GL_SRC_ALPHA: 584 sA = As; 585 break; 586 case GL_ONE_MINUS_SRC_ALPHA: 587 sA = 1.0F - As; 588 break; 589 case GL_DST_ALPHA: 590 sA = Ad; 591 break; 592 case GL_ONE_MINUS_DST_ALPHA: 593 sA = 1.0F - Ad; 594 break; 595 case GL_SRC_ALPHA_SATURATE: 596 sA = 1.0; 597 break; 598 case GL_CONSTANT_COLOR: 599 sA = ctx->Color.BlendColor[3]; 600 break; 601 case GL_ONE_MINUS_CONSTANT_COLOR: 602 sA = 1.0F - ctx->Color.BlendColor[3]; 603 break; 604 case GL_CONSTANT_ALPHA: 605 sA = ctx->Color.BlendColor[3]; 606 break; 607 case GL_ONE_MINUS_CONSTANT_ALPHA: 608 sA = 1.0F - ctx->Color.BlendColor[3]; 609 break; 610 case GL_SRC_COLOR: 611 sA = As; 612 break; 613 case GL_ONE_MINUS_SRC_COLOR: 614 sA = 1.0F - As; 615 break; 616 default: 617 /* this should never happen */ 618 sA = 0.0F; 619 _mesa_problem(ctx, "Bad blend source A factor in blend_general_float"); 620 return; 621 } 622 623 /* Dest RGB factor */ 624 switch (ctx->Color.Blend[0].DstRGB) { 625 case GL_ZERO: 626 dR = dG = dB = 0.0F; 627 break; 628 case GL_ONE: 629 dR = dG = dB = 1.0F; 630 break; 631 case GL_SRC_COLOR: 632 dR = Rs; 633 dG = Gs; 634 dB = Bs; 635 break; 636 case GL_ONE_MINUS_SRC_COLOR: 637 dR = 1.0F - Rs; 638 dG = 1.0F - Gs; 639 dB = 1.0F - Bs; 640 break; 641 case GL_SRC_ALPHA: 642 dR = dG = dB = As; 643 break; 644 case GL_ONE_MINUS_SRC_ALPHA: 645 dR = dG = dB = 1.0F - As; 646 break; 647 case GL_DST_ALPHA: 648 dR = dG = dB = Ad; 649 break; 650 case GL_ONE_MINUS_DST_ALPHA: 651 dR = dG = dB = 1.0F - Ad; 652 break; 653 case GL_CONSTANT_COLOR: 654 dR = ctx->Color.BlendColor[0]; 655 dG = ctx->Color.BlendColor[1]; 656 dB = ctx->Color.BlendColor[2]; 657 break; 658 case GL_ONE_MINUS_CONSTANT_COLOR: 659 dR = 1.0F - ctx->Color.BlendColor[0]; 660 dG = 1.0F - ctx->Color.BlendColor[1]; 661 dB = 1.0F - ctx->Color.BlendColor[2]; 662 break; 663 case GL_CONSTANT_ALPHA: 664 dR = dG = dB = ctx->Color.BlendColor[3]; 665 break; 666 case GL_ONE_MINUS_CONSTANT_ALPHA: 667 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3]; 668 break; 669 case GL_DST_COLOR: 670 dR = Rd; 671 dG = Gd; 672 dB = Bd; 673 break; 674 case GL_ONE_MINUS_DST_COLOR: 675 dR = 1.0F - Rd; 676 dG = 1.0F - Gd; 677 dB = 1.0F - Bd; 678 break; 679 default: 680 /* this should never happen */ 681 dR = dG = dB = 0.0F; 682 _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float"); 683 return; 684 } 685 686 /* Dest Alpha factor */ 687 switch (ctx->Color.Blend[0].DstA) { 688 case GL_ZERO: 689 dA = 0.0F; 690 break; 691 case GL_ONE: 692 dA = 1.0F; 693 break; 694 case GL_SRC_COLOR: 695 dA = As; 696 break; 697 case GL_ONE_MINUS_SRC_COLOR: 698 dA = 1.0F - As; 699 break; 700 case GL_SRC_ALPHA: 701 dA = As; 702 break; 703 case GL_ONE_MINUS_SRC_ALPHA: 704 dA = 1.0F - As; 705 break; 706 case GL_DST_ALPHA: 707 dA = Ad; 708 break; 709 case GL_ONE_MINUS_DST_ALPHA: 710 dA = 1.0F - Ad; 711 break; 712 case GL_CONSTANT_COLOR: 713 dA = ctx->Color.BlendColor[3]; 714 break; 715 case GL_ONE_MINUS_CONSTANT_COLOR: 716 dA = 1.0F - ctx->Color.BlendColor[3]; 717 break; 718 case GL_CONSTANT_ALPHA: 719 dA = ctx->Color.BlendColor[3]; 720 break; 721 case GL_ONE_MINUS_CONSTANT_ALPHA: 722 dA = 1.0F - ctx->Color.BlendColor[3]; 723 break; 724 case GL_DST_COLOR: 725 dA = Ad; 726 break; 727 case GL_ONE_MINUS_DST_COLOR: 728 dA = 1.0F - Ad; 729 break; 730 default: 731 /* this should never happen */ 732 dA = 0.0F; 733 _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float"); 734 return; 735 } 736 737 /* compute the blended RGB */ 738 switch (ctx->Color.Blend[0].EquationRGB) { 739 case GL_FUNC_ADD: 740 r = Rs * sR + Rd * dR; 741 g = Gs * sG + Gd * dG; 742 b = Bs * sB + Bd * dB; 743 a = As * sA + Ad * dA; 744 break; 745 case GL_FUNC_SUBTRACT: 746 r = Rs * sR - Rd * dR; 747 g = Gs * sG - Gd * dG; 748 b = Bs * sB - Bd * dB; 749 a = As * sA - Ad * dA; 750 break; 751 case GL_FUNC_REVERSE_SUBTRACT: 752 r = Rd * dR - Rs * sR; 753 g = Gd * dG - Gs * sG; 754 b = Bd * dB - Bs * sB; 755 a = Ad * dA - As * sA; 756 break; 757 case GL_MIN: 758 r = MIN2( Rd, Rs ); 759 g = MIN2( Gd, Gs ); 760 b = MIN2( Bd, Bs ); 761 break; 762 case GL_MAX: 763 r = MAX2( Rd, Rs ); 764 g = MAX2( Gd, Gs ); 765 b = MAX2( Bd, Bs ); 766 break; 767 default: 768 /* should never get here */ 769 r = g = b = 0.0F; /* silence uninitialized var warning */ 770 _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); 771 return; 772 } 773 774 /* compute the blended alpha */ 775 switch (ctx->Color.Blend[0].EquationA) { 776 case GL_FUNC_ADD: 777 a = As * sA + Ad * dA; 778 break; 779 case GL_FUNC_SUBTRACT: 780 a = As * sA - Ad * dA; 781 break; 782 case GL_FUNC_REVERSE_SUBTRACT: 783 a = Ad * dA - As * sA; 784 break; 785 case GL_MIN: 786 a = MIN2( Ad, As ); 787 break; 788 case GL_MAX: 789 a = MAX2( Ad, As ); 790 break; 791 default: 792 /* should never get here */ 793 a = 0.0F; /* silence uninitialized var warning */ 794 _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); 795 return; 796 } 797 798 /* final clamping */ 799 #if 0 800 rgba[i][RCOMP] = MAX2( r, 0.0F ); 801 rgba[i][GCOMP] = MAX2( g, 0.0F ); 802 rgba[i][BCOMP] = MAX2( b, 0.0F ); 803 rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F ); 804 #else 805 ASSIGN_4V(rgba[i], r, g, b, a); 806 #endif 807 } 808 } 809 } 810 811 812 /** 813 * Do any blending operation, any chanType. 814 */ 815 static void 816 blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[], 817 void *src, const void *dst, GLenum chanType) 818 { 819 GLfloat (*rgbaF)[4], (*destF)[4]; 820 821 rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); 822 destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); 823 if (!rgbaF || !destF) { 824 free(rgbaF); 825 free(destF); 826 _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending"); 827 return; 828 } 829 830 if (chanType == GL_UNSIGNED_BYTE) { 831 GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 832 const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 833 GLuint i; 834 /* convert ubytes to floats */ 835 for (i = 0; i < n; i++) { 836 if (mask[i]) { 837 rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]); 838 rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]); 839 rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]); 840 rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]); 841 destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]); 842 destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]); 843 destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]); 844 destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]); 845 } 846 } 847 /* do blend */ 848 blend_general_float(ctx, n, mask, rgbaF, destF, chanType); 849 /* convert back to ubytes */ 850 for (i = 0; i < n; i++) { 851 if (mask[i]) 852 _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]); 853 } 854 } 855 else if (chanType == GL_UNSIGNED_SHORT) { 856 GLushort (*rgba)[4] = (GLushort (*)[4]) src; 857 const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 858 GLuint i; 859 /* convert ushorts to floats */ 860 for (i = 0; i < n; i++) { 861 if (mask[i]) { 862 rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]); 863 rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]); 864 rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]); 865 rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]); 866 destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]); 867 destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]); 868 destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]); 869 destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]); 870 } 871 } 872 /* do blend */ 873 blend_general_float(ctx, n, mask, rgbaF, destF, chanType); 874 /* convert back to ushorts */ 875 for (i = 0; i < n; i++) { 876 if (mask[i]) { 877 UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]); 878 UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]); 879 UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]); 880 UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]); 881 } 882 } 883 } 884 else { 885 blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src, 886 (GLfloat (*)[4]) dst, chanType); 887 } 888 889 free(rgbaF); 890 free(destF); 891 } 892 893 894 895 /** 896 * Analyze current blending parameters to pick fastest blending function. 897 * Result: the ctx->Color.BlendFunc pointer is updated. 898 */ 899 void 900 _swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType) 901 { 902 SWcontext *swrast = SWRAST_CONTEXT(ctx); 903 const GLenum eq = ctx->Color.Blend[0].EquationRGB; 904 const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB; 905 const GLenum dstRGB = ctx->Color.Blend[0].DstRGB; 906 const GLenum srcA = ctx->Color.Blend[0].SrcA; 907 const GLenum dstA = ctx->Color.Blend[0].DstA; 908 909 if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) { 910 swrast->BlendFunc = blend_general; 911 } 912 else if (eq == GL_MIN) { 913 /* Note: GL_MIN ignores the blending weight factors */ 914 #if defined(USE_MMX_ASM) 915 if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 916 swrast->BlendFunc = _mesa_mmx_blend_min; 917 } 918 else 919 #endif 920 swrast->BlendFunc = blend_min; 921 } 922 else if (eq == GL_MAX) { 923 /* Note: GL_MAX ignores the blending weight factors */ 924 #if defined(USE_MMX_ASM) 925 if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 926 swrast->BlendFunc = _mesa_mmx_blend_max; 927 } 928 else 929 #endif 930 swrast->BlendFunc = blend_max; 931 } 932 else if (srcRGB != srcA || dstRGB != dstA) { 933 swrast->BlendFunc = blend_general; 934 } 935 else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA 936 && dstRGB == GL_ONE_MINUS_SRC_ALPHA) { 937 #if defined(USE_MMX_ASM) 938 if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 939 swrast->BlendFunc = _mesa_mmx_blend_transparency; 940 } 941 else 942 #endif 943 { 944 if (chanType == GL_UNSIGNED_BYTE) 945 swrast->BlendFunc = blend_transparency_ubyte; 946 else if (chanType == GL_UNSIGNED_SHORT) 947 swrast->BlendFunc = blend_transparency_ushort; 948 else 949 swrast->BlendFunc = blend_transparency_float; 950 } 951 } 952 else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) { 953 #if defined(USE_MMX_ASM) 954 if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 955 swrast->BlendFunc = _mesa_mmx_blend_add; 956 } 957 else 958 #endif 959 swrast->BlendFunc = blend_add; 960 } 961 else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT) 962 && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR)) 963 || 964 ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT) 965 && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) { 966 #if defined(USE_MMX_ASM) 967 if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 968 swrast->BlendFunc = _mesa_mmx_blend_modulate; 969 } 970 else 971 #endif 972 swrast->BlendFunc = blend_modulate; 973 } 974 else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) { 975 swrast->BlendFunc = blend_noop; 976 } 977 else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) { 978 swrast->BlendFunc = blend_replace; 979 } 980 else { 981 swrast->BlendFunc = blend_general; 982 } 983 } 984 985 986 987 /** 988 * Apply the blending operator to a span of pixels. 989 * We can handle horizontal runs of pixels (spans) or arrays of x/y 990 * pixel coordinates. 991 */ 992 void 993 _swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span) 994 { 995 SWcontext *swrast = SWRAST_CONTEXT(ctx); 996 void *rbPixels; 997 998 assert(span->end <= SWRAST_MAX_WIDTH); 999 assert(span->arrayMask & SPAN_RGBA); 1000 assert(!ctx->Color.ColorLogicOpEnabled); 1001 1002 rbPixels = _swrast_get_dest_rgba(ctx, rb, span); 1003 1004 swrast->BlendFunc(ctx, span->end, span->array->mask, 1005 span->array->rgba, rbPixels, span->array->ChanType); 1006 } 1007