sp_quad_blend.c revision f7e475280a0b98484a8c1a98f18b2733532486b4
1/************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * 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 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * quad blending 30 * \author Brian Paul 31 */ 32 33#include "pipe/p_defines.h" 34#include "pipe/p_util.h" 35#include "sp_context.h" 36#include "sp_headers.h" 37#include "sp_surface.h" 38#include "sp_tile_cache.h" 39#include "sp_quad.h" 40 41 42#define VEC4_COPY(DST, SRC) \ 43do { \ 44 DST[0] = SRC[0]; \ 45 DST[1] = SRC[1]; \ 46 DST[2] = SRC[2]; \ 47 DST[3] = SRC[3]; \ 48} while(0) 49 50#define VEC4_SCALAR(DST, SRC) \ 51do { \ 52 DST[0] = SRC; \ 53 DST[1] = SRC; \ 54 DST[2] = SRC; \ 55 DST[3] = SRC; \ 56} while(0) 57 58#define VEC4_ADD(R, A, B) \ 59do { \ 60 R[0] = A[0] + B[0]; \ 61 R[1] = A[1] + B[1]; \ 62 R[2] = A[2] + B[2]; \ 63 R[3] = A[3] + B[3]; \ 64} while (0) 65 66#define VEC4_SUB(R, A, B) \ 67do { \ 68 R[0] = A[0] - B[0]; \ 69 R[1] = A[1] - B[1]; \ 70 R[2] = A[2] - B[2]; \ 71 R[3] = A[3] - B[3]; \ 72} while (0) 73 74#define VEC4_MUL(R, A, B) \ 75do { \ 76 R[0] = A[0] * B[0]; \ 77 R[1] = A[1] * B[1]; \ 78 R[2] = A[2] * B[2]; \ 79 R[3] = A[3] * B[3]; \ 80} while (0) 81 82#define VEC4_MIN(R, A, B) \ 83do { \ 84 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \ 85 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \ 86 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \ 87 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \ 88} while (0) 89 90#define VEC4_MAX(R, A, B) \ 91do { \ 92 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \ 93 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \ 94 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \ 95 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \ 96} while (0) 97 98 99 100static void 101logicop_quad(struct quad_stage *qs, struct quad_header *quad) 102{ 103 struct softpipe_context *softpipe = qs->softpipe; 104 uint cbuf; 105 106 /* loop over colorbuffer outputs */ 107 for (cbuf = 0; cbuf < softpipe->framebuffer.num_cbufs; cbuf++) { 108 float dest[4][QUAD_SIZE]; 109 ubyte src[4][4], dst[4][4], res[4][4]; 110 uint *src4 = (uint *) src; 111 uint *dst4 = (uint *) dst; 112 uint *res4 = (uint *) res; 113 struct softpipe_cached_tile * 114 tile = sp_get_cached_tile(softpipe, 115 softpipe->cbuf_cache[cbuf], 116 quad->x0, quad->y0); 117 float (*quadColor)[4] = quad->outputs.color[cbuf]; 118 uint i, j; 119 120 /* get/swizzle dest colors */ 121 for (j = 0; j < QUAD_SIZE; j++) { 122 int x = (quad->x0 & (TILE_SIZE-1)) + (j & 1); 123 int y = (quad->y0 & (TILE_SIZE-1)) + (j >> 1); 124 for (i = 0; i < 4; i++) { 125 dest[i][j] = tile->data.color[y][x][i]; 126 } 127 } 128 129 /* convert to ubyte */ 130 for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */ 131 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][0], dest[j][0]); /* P0 */ 132 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][1], dest[j][1]); /* P1 */ 133 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][2], dest[j][2]); /* P2 */ 134 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][3], dest[j][3]); /* P3 */ 135 136 UNCLAMPED_FLOAT_TO_UBYTE(src[j][0], quadColor[j][0]); /* P0 */ 137 UNCLAMPED_FLOAT_TO_UBYTE(src[j][1], quadColor[j][1]); /* P1 */ 138 UNCLAMPED_FLOAT_TO_UBYTE(src[j][2], quadColor[j][2]); /* P2 */ 139 UNCLAMPED_FLOAT_TO_UBYTE(src[j][3], quadColor[j][3]); /* P3 */ 140 } 141 142 switch (softpipe->blend->logicop_func) { 143 case PIPE_LOGICOP_CLEAR: 144 for (j = 0; j < 4; j++) 145 res4[j] = 0; 146 break; 147 case PIPE_LOGICOP_NOR: 148 for (j = 0; j < 4; j++) 149 res4[j] = ~(src4[j] | dst4[j]); 150 break; 151 case PIPE_LOGICOP_AND_INVERTED: 152 for (j = 0; j < 4; j++) 153 res4[j] = ~src4[j] & dst4[j]; 154 break; 155 case PIPE_LOGICOP_COPY_INVERTED: 156 for (j = 0; j < 4; j++) 157 res4[j] = ~src4[j]; 158 break; 159 case PIPE_LOGICOP_AND_REVERSE: 160 for (j = 0; j < 4; j++) 161 res4[j] = src4[j] & ~dst4[j]; 162 break; 163 case PIPE_LOGICOP_INVERT: 164 for (j = 0; j < 4; j++) 165 res4[j] = ~dst4[j]; 166 break; 167 case PIPE_LOGICOP_XOR: 168 for (j = 0; j < 4; j++) 169 res4[j] = dst4[j] ^ src4[j]; 170 break; 171 case PIPE_LOGICOP_NAND: 172 for (j = 0; j < 4; j++) 173 res4[j] = ~(src4[j] & dst4[j]); 174 break; 175 case PIPE_LOGICOP_AND: 176 for (j = 0; j < 4; j++) 177 res4[j] = src4[j] & dst4[j]; 178 break; 179 case PIPE_LOGICOP_EQUIV: 180 for (j = 0; j < 4; j++) 181 res4[j] = ~(src4[j] ^ dst4[j]); 182 break; 183 case PIPE_LOGICOP_NOOP: 184 for (j = 0; j < 4; j++) 185 res4[j] = dst4[j]; 186 break; 187 case PIPE_LOGICOP_OR_INVERTED: 188 for (j = 0; j < 4; j++) 189 res4[j] = ~src4[j] | dst4[j]; 190 break; 191 case PIPE_LOGICOP_COPY: 192 for (j = 0; j < 4; j++) 193 res4[j] = src4[j]; 194 break; 195 case PIPE_LOGICOP_OR_REVERSE: 196 for (j = 0; j < 4; j++) 197 res4[j] = src4[j] | ~dst4[j]; 198 break; 199 case PIPE_LOGICOP_OR: 200 for (j = 0; j < 4; j++) 201 res4[j] = src4[j] | dst4[j]; 202 break; 203 case PIPE_LOGICOP_SET: 204 for (j = 0; j < 4; j++) 205 res4[j] = ~0; 206 break; 207 default: 208 assert(0); 209 } 210 211 for (j = 0; j < 4; j++) { 212 quadColor[j][0] = UBYTE_TO_FLOAT(res[j][0]); 213 quadColor[j][1] = UBYTE_TO_FLOAT(res[j][1]); 214 quadColor[j][2] = UBYTE_TO_FLOAT(res[j][2]); 215 quadColor[j][3] = UBYTE_TO_FLOAT(res[j][3]); 216 } 217 } 218 219 /* pass quad to next stage */ 220 qs->next->run(qs->next, quad); 221} 222 223 224 225 226static void 227blend_quad(struct quad_stage *qs, struct quad_header *quad) 228{ 229 static const float zero[4] = { 0, 0, 0, 0 }; 230 static const float one[4] = { 1, 1, 1, 1 }; 231 232 struct softpipe_context *softpipe = qs->softpipe; 233 uint cbuf; 234 235 /* loop over colorbuffer outputs */ 236 for (cbuf = 0; cbuf < softpipe->framebuffer.num_cbufs; cbuf++) { 237 float source[4][QUAD_SIZE], dest[4][QUAD_SIZE]; 238 struct softpipe_cached_tile *tile 239 = sp_get_cached_tile(softpipe, 240 softpipe->cbuf_cache[cbuf], 241 quad->x0, quad->y0); 242 float (*quadColor)[4] = quad->outputs.color[cbuf]; 243 uint i, j; 244 245 if (softpipe->blend->logicop_enable) { 246 logicop_quad(qs, quad); 247 return; 248 } 249 250 /* get/swizzle dest colors */ 251 for (j = 0; j < QUAD_SIZE; j++) { 252 int x = (quad->x0 & (TILE_SIZE-1)) + (j & 1); 253 int y = (quad->y0 & (TILE_SIZE-1)) + (j >> 1); 254 for (i = 0; i < 4; i++) { 255 dest[i][j] = tile->data.color[y][x][i]; 256 } 257 } 258 259 /* 260 * Compute src/first term RGB 261 */ 262 switch (softpipe->blend->rgb_src_factor) { 263 case PIPE_BLENDFACTOR_ONE: 264 VEC4_COPY(source[0], quadColor[0]); /* R */ 265 VEC4_COPY(source[1], quadColor[1]); /* G */ 266 VEC4_COPY(source[2], quadColor[2]); /* B */ 267 break; 268 case PIPE_BLENDFACTOR_SRC_COLOR: 269 VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */ 270 VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */ 271 VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */ 272 break; 273 case PIPE_BLENDFACTOR_SRC_ALPHA: 274 { 275 const float *alpha = quadColor[3]; 276 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 277 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 278 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 279 } 280 break; 281 case PIPE_BLENDFACTOR_DST_COLOR: 282 VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */ 283 VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */ 284 VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */ 285 break; 286 case PIPE_BLENDFACTOR_DST_ALPHA: 287 { 288 const float *alpha = dest[3]; 289 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 290 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 291 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 292 } 293 break; 294 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 295 { 296 const float *alpha = quadColor[3]; 297 float diff[4]; 298 VEC4_SUB(diff, one, dest[3]); 299 VEC4_MIN(source[0], alpha, diff); /* R */ 300 VEC4_MIN(source[1], alpha, diff); /* G */ 301 VEC4_MIN(source[2], alpha, diff); /* B */ 302 } 303 break; 304 case PIPE_BLENDFACTOR_CONST_COLOR: 305 { 306 float comp[4]; 307 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */ 308 VEC4_MUL(source[0], quadColor[0], comp); /* R */ 309 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */ 310 VEC4_MUL(source[1], quadColor[1], comp); /* G */ 311 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */ 312 VEC4_MUL(source[2], quadColor[2], comp); /* B */ 313 } 314 break; 315 case PIPE_BLENDFACTOR_CONST_ALPHA: 316 { 317 float alpha[4]; 318 VEC4_SCALAR(alpha, softpipe->blend_color.color[3]); 319 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 320 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 321 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 322 } 323 break; 324 case PIPE_BLENDFACTOR_SRC1_COLOR: 325 assert(0); /* to do */ 326 break; 327 case PIPE_BLENDFACTOR_SRC1_ALPHA: 328 assert(0); /* to do */ 329 break; 330 case PIPE_BLENDFACTOR_ZERO: 331 VEC4_COPY(source[0], zero); /* R */ 332 VEC4_COPY(source[1], zero); /* G */ 333 VEC4_COPY(source[2], zero); /* B */ 334 break; 335 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 336 { 337 float inv_comp[4]; 338 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 339 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 340 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 341 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 342 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 343 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 344 } 345 break; 346 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 347 { 348 float inv_alpha[4]; 349 VEC4_SUB(inv_alpha, one, quadColor[3]); 350 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 351 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 352 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 353 } 354 break; 355 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 356 { 357 float inv_alpha[4]; 358 VEC4_SUB(inv_alpha, one, dest[3]); 359 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 360 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 361 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 362 } 363 break; 364 case PIPE_BLENDFACTOR_INV_DST_COLOR: 365 { 366 float inv_comp[4]; 367 VEC4_SUB(inv_comp, one, dest[0]); /* R */ 368 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 369 VEC4_SUB(inv_comp, one, dest[1]); /* G */ 370 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 371 VEC4_SUB(inv_comp, one, dest[2]); /* B */ 372 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 373 } 374 break; 375 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 376 { 377 float inv_comp[4]; 378 /* R */ 379 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]); 380 VEC4_MUL(source[0], quadColor[0], inv_comp); 381 /* G */ 382 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]); 383 VEC4_MUL(source[1], quadColor[1], inv_comp); 384 /* B */ 385 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]); 386 VEC4_MUL(source[2], quadColor[2], inv_comp); 387 } 388 break; 389 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 390 { 391 float inv_alpha[4]; 392 VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]); 393 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 394 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 395 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 396 } 397 break; 398 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 399 assert(0); /* to do */ 400 break; 401 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 402 assert(0); /* to do */ 403 break; 404 default: 405 assert(0); 406 } 407 408 /* 409 * Compute src/first term A 410 */ 411 switch (softpipe->blend->alpha_src_factor) { 412 case PIPE_BLENDFACTOR_ONE: 413 VEC4_COPY(source[3], quadColor[3]); /* A */ 414 break; 415 case PIPE_BLENDFACTOR_SRC_COLOR: 416 /* fall-through */ 417 case PIPE_BLENDFACTOR_SRC_ALPHA: 418 { 419 const float *alpha = quadColor[3]; 420 VEC4_MUL(source[3], quadColor[3], alpha); /* A */ 421 } 422 break; 423 case PIPE_BLENDFACTOR_DST_COLOR: 424 /* fall-through */ 425 case PIPE_BLENDFACTOR_DST_ALPHA: 426 VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */ 427 break; 428 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 429 { 430 const float *alpha = quadColor[3]; 431 float diff[4]; 432 VEC4_SUB(diff, one, dest[3]); 433 VEC4_MIN(source[3], alpha, diff); /* A */ 434 } 435 break; 436 case PIPE_BLENDFACTOR_CONST_COLOR: 437 /* fall-through */ 438 case PIPE_BLENDFACTOR_CONST_ALPHA: 439 { 440 float comp[4]; 441 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 442 VEC4_MUL(source[3], quadColor[3], comp); /* A */ 443 } 444 break; 445 case PIPE_BLENDFACTOR_ZERO: 446 VEC4_COPY(source[3], zero); /* A */ 447 break; 448 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 449 /* fall-through */ 450 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 451 { 452 float inv_alpha[4]; 453 VEC4_SUB(inv_alpha, one, quadColor[3]); 454 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 455 } 456 break; 457 case PIPE_BLENDFACTOR_INV_DST_COLOR: 458 /* fall-through */ 459 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 460 { 461 float inv_alpha[4]; 462 VEC4_SUB(inv_alpha, one, dest[3]); 463 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 464 } 465 break; 466 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 467 /* fall-through */ 468 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 469 { 470 float inv_comp[4]; 471 /* A */ 472 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 473 VEC4_MUL(source[3], quadColor[3], inv_comp); 474 } 475 break; 476 default: 477 assert(0); 478 } 479 480 481 /* 482 * Compute dest/second term RGB 483 */ 484 switch (softpipe->blend->rgb_dst_factor) { 485 case PIPE_BLENDFACTOR_ONE: 486 /* dest = dest * 1 NO-OP, leave dest as-is */ 487 break; 488 case PIPE_BLENDFACTOR_SRC_COLOR: 489 VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */ 490 VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */ 491 VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */ 492 break; 493 case PIPE_BLENDFACTOR_SRC_ALPHA: 494 VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */ 495 VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */ 496 VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */ 497 break; 498 case PIPE_BLENDFACTOR_DST_ALPHA: 499 VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */ 500 VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */ 501 VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */ 502 break; 503 case PIPE_BLENDFACTOR_DST_COLOR: 504 VEC4_MUL(dest[0], dest[0], dest[0]); /* R */ 505 VEC4_MUL(dest[1], dest[1], dest[1]); /* G */ 506 VEC4_MUL(dest[2], dest[2], dest[2]); /* B */ 507 break; 508 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 509 assert(0); /* illegal */ 510 break; 511 case PIPE_BLENDFACTOR_CONST_COLOR: 512 { 513 float comp[4]; 514 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */ 515 VEC4_MUL(dest[0], dest[0], comp); /* R */ 516 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */ 517 VEC4_MUL(dest[1], dest[1], comp); /* G */ 518 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */ 519 VEC4_MUL(dest[2], dest[2], comp); /* B */ 520 } 521 break; 522 case PIPE_BLENDFACTOR_CONST_ALPHA: 523 { 524 float comp[4]; 525 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 526 VEC4_MUL(dest[0], dest[0], comp); /* R */ 527 VEC4_MUL(dest[1], dest[1], comp); /* G */ 528 VEC4_MUL(dest[2], dest[2], comp); /* B */ 529 } 530 break; 531 case PIPE_BLENDFACTOR_ZERO: 532 VEC4_COPY(dest[0], zero); /* R */ 533 VEC4_COPY(dest[1], zero); /* G */ 534 VEC4_COPY(dest[2], zero); /* B */ 535 break; 536 case PIPE_BLENDFACTOR_SRC1_COLOR: 537 case PIPE_BLENDFACTOR_SRC1_ALPHA: 538 /* XXX what are these? */ 539 assert(0); 540 break; 541 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 542 { 543 float inv_comp[4]; 544 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 545 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ 546 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 547 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ 548 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 549 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ 550 } 551 break; 552 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 553 { 554 float one_minus_alpha[QUAD_SIZE]; 555 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 556 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */ 557 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */ 558 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */ 559 } 560 break; 561 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 562 { 563 float inv_comp[4]; 564 VEC4_SUB(inv_comp, one, dest[3]); /* A */ 565 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ 566 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ 567 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ 568 } 569 break; 570 case PIPE_BLENDFACTOR_INV_DST_COLOR: 571 { 572 float inv_comp[4]; 573 VEC4_SUB(inv_comp, one, dest[0]); /* R */ 574 VEC4_MUL(dest[0], dest[0], inv_comp); /* R */ 575 VEC4_SUB(inv_comp, one, dest[1]); /* G */ 576 VEC4_MUL(dest[1], dest[1], inv_comp); /* G */ 577 VEC4_SUB(inv_comp, one, dest[2]); /* B */ 578 VEC4_MUL(dest[2], dest[2], inv_comp); /* B */ 579 } 580 break; 581 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 582 { 583 float inv_comp[4]; 584 /* R */ 585 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]); 586 VEC4_MUL(dest[0], dest[0], inv_comp); 587 /* G */ 588 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]); 589 VEC4_MUL(dest[1], dest[1], inv_comp); 590 /* B */ 591 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]); 592 VEC4_MUL(dest[2], dest[2], inv_comp); 593 } 594 break; 595 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 596 { 597 float inv_comp[4]; 598 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 599 VEC4_MUL(dest[0], dest[0], inv_comp); 600 VEC4_MUL(dest[1], dest[1], inv_comp); 601 VEC4_MUL(dest[2], dest[2], inv_comp); 602 } 603 break; 604 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 605 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 606 /* XXX what are these? */ 607 assert(0); 608 break; 609 default: 610 assert(0); 611 } 612 613 /* 614 * Compute dest/second term A 615 */ 616 switch (softpipe->blend->alpha_dst_factor) { 617 case PIPE_BLENDFACTOR_ONE: 618 /* dest = dest * 1 NO-OP, leave dest as-is */ 619 break; 620 case PIPE_BLENDFACTOR_SRC_COLOR: 621 /* fall-through */ 622 case PIPE_BLENDFACTOR_SRC_ALPHA: 623 VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */ 624 break; 625 case PIPE_BLENDFACTOR_DST_COLOR: 626 /* fall-through */ 627 case PIPE_BLENDFACTOR_DST_ALPHA: 628 VEC4_MUL(dest[3], dest[3], dest[3]); /* A */ 629 break; 630 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 631 assert(0); /* illegal */ 632 break; 633 case PIPE_BLENDFACTOR_CONST_COLOR: 634 /* fall-through */ 635 case PIPE_BLENDFACTOR_CONST_ALPHA: 636 { 637 float comp[4]; 638 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 639 VEC4_MUL(dest[3], dest[3], comp); /* A */ 640 } 641 break; 642 case PIPE_BLENDFACTOR_ZERO: 643 VEC4_COPY(dest[3], zero); /* A */ 644 break; 645 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 646 /* fall-through */ 647 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 648 { 649 float one_minus_alpha[QUAD_SIZE]; 650 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 651 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */ 652 } 653 break; 654 case PIPE_BLENDFACTOR_INV_DST_COLOR: 655 /* fall-through */ 656 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 657 { 658 float inv_comp[4]; 659 VEC4_SUB(inv_comp, one, dest[3]); /* A */ 660 VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */ 661 } 662 break; 663 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 664 /* fall-through */ 665 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 666 { 667 float inv_comp[4]; 668 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 669 VEC4_MUL(dest[3], dest[3], inv_comp); 670 } 671 break; 672 default: 673 assert(0); 674 } 675 676 /* 677 * Combine RGB terms 678 */ 679 switch (softpipe->blend->rgb_func) { 680 case PIPE_BLEND_ADD: 681 VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */ 682 VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */ 683 VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */ 684 break; 685 case PIPE_BLEND_SUBTRACT: 686 VEC4_SUB(quadColor[0], source[0], dest[0]); /* R */ 687 VEC4_SUB(quadColor[1], source[1], dest[1]); /* G */ 688 VEC4_SUB(quadColor[2], source[2], dest[2]); /* B */ 689 break; 690 case PIPE_BLEND_REVERSE_SUBTRACT: 691 VEC4_SUB(quadColor[0], dest[0], source[0]); /* R */ 692 VEC4_SUB(quadColor[1], dest[1], source[1]); /* G */ 693 VEC4_SUB(quadColor[2], dest[2], source[2]); /* B */ 694 break; 695 case PIPE_BLEND_MIN: 696 VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */ 697 VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */ 698 VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */ 699 break; 700 case PIPE_BLEND_MAX: 701 VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */ 702 VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */ 703 VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */ 704 break; 705 default: 706 assert(0); 707 } 708 709 /* 710 * Combine A terms 711 */ 712 switch (softpipe->blend->alpha_func) { 713 case PIPE_BLEND_ADD: 714 VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */ 715 break; 716 case PIPE_BLEND_SUBTRACT: 717 VEC4_SUB(quadColor[3], source[3], dest[3]); /* A */ 718 break; 719 case PIPE_BLEND_REVERSE_SUBTRACT: 720 VEC4_SUB(quadColor[3], dest[3], source[3]); /* A */ 721 break; 722 case PIPE_BLEND_MIN: 723 VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */ 724 break; 725 case PIPE_BLEND_MAX: 726 VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */ 727 break; 728 default: 729 assert(0); 730 } 731 732 } /* cbuf loop */ 733 734 /* pass blended quad to next stage */ 735 qs->next->run(qs->next, quad); 736} 737 738 739static void blend_begin(struct quad_stage *qs) 740{ 741 qs->next->begin(qs->next); 742} 743 744 745static void blend_destroy(struct quad_stage *qs) 746{ 747 FREE( qs ); 748} 749 750 751struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ) 752{ 753 struct quad_stage *stage = CALLOC_STRUCT(quad_stage); 754 755 stage->softpipe = softpipe; 756 stage->begin = blend_begin; 757 stage->run = blend_quad; 758 stage->destroy = blend_destroy; 759 760 return stage; 761} 762