sp_quad_blend.c revision 1078844d18367b4259cd3b6a3a73e3cd72ea019f
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 "util/u_math.h" 35#include "util/u_memory.h" 36#include "sp_context.h" 37#include "sp_quad.h" 38#include "sp_surface.h" 39#include "sp_tile_cache.h" 40#include "sp_quad_pipe.h" 41 42 43#define VEC4_COPY(DST, SRC) \ 44do { \ 45 DST[0] = SRC[0]; \ 46 DST[1] = SRC[1]; \ 47 DST[2] = SRC[2]; \ 48 DST[3] = SRC[3]; \ 49} while(0) 50 51#define VEC4_SCALAR(DST, SRC) \ 52do { \ 53 DST[0] = SRC; \ 54 DST[1] = SRC; \ 55 DST[2] = SRC; \ 56 DST[3] = SRC; \ 57} while(0) 58 59#define VEC4_ADD(R, A, B) \ 60do { \ 61 R[0] = A[0] + B[0]; \ 62 R[1] = A[1] + B[1]; \ 63 R[2] = A[2] + B[2]; \ 64 R[3] = A[3] + B[3]; \ 65} while (0) 66 67#define VEC4_SUB(R, A, B) \ 68do { \ 69 R[0] = A[0] - B[0]; \ 70 R[1] = A[1] - B[1]; \ 71 R[2] = A[2] - B[2]; \ 72 R[3] = A[3] - B[3]; \ 73} while (0) 74 75/** Add and limit result to ceiling of 1.0 */ 76#define VEC4_ADD_SAT(R, A, B) \ 77do { \ 78 R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \ 79 R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \ 80 R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \ 81 R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \ 82} while (0) 83 84/** Subtract and limit result to floor of 0.0 */ 85#define VEC4_SUB_SAT(R, A, B) \ 86do { \ 87 R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \ 88 R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \ 89 R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \ 90 R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \ 91} while (0) 92 93#define VEC4_MUL(R, A, B) \ 94do { \ 95 R[0] = A[0] * B[0]; \ 96 R[1] = A[1] * B[1]; \ 97 R[2] = A[2] * B[2]; \ 98 R[3] = A[3] * B[3]; \ 99} while (0) 100 101#define VEC4_MIN(R, A, B) \ 102do { \ 103 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \ 104 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \ 105 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \ 106 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \ 107} while (0) 108 109#define VEC4_MAX(R, A, B) \ 110do { \ 111 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \ 112 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \ 113 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \ 114 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \ 115} while (0) 116 117 118 119static void 120logicop_quad(struct quad_stage *qs, 121 float (*quadColor)[4], 122 float (*dest)[4]) 123{ 124 struct softpipe_context *softpipe = qs->softpipe; 125 ubyte src[4][4], dst[4][4], res[4][4]; 126 uint *src4 = (uint *) src; 127 uint *dst4 = (uint *) dst; 128 uint *res4 = (uint *) res; 129 uint j; 130 131 132 /* convert to ubyte */ 133 for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */ 134 dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */ 135 dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */ 136 dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */ 137 dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */ 138 139 src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */ 140 src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */ 141 src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */ 142 src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */ 143 } 144 145 switch (softpipe->blend->logicop_func) { 146 case PIPE_LOGICOP_CLEAR: 147 for (j = 0; j < 4; j++) 148 res4[j] = 0; 149 break; 150 case PIPE_LOGICOP_NOR: 151 for (j = 0; j < 4; j++) 152 res4[j] = ~(src4[j] | dst4[j]); 153 break; 154 case PIPE_LOGICOP_AND_INVERTED: 155 for (j = 0; j < 4; j++) 156 res4[j] = ~src4[j] & dst4[j]; 157 break; 158 case PIPE_LOGICOP_COPY_INVERTED: 159 for (j = 0; j < 4; j++) 160 res4[j] = ~src4[j]; 161 break; 162 case PIPE_LOGICOP_AND_REVERSE: 163 for (j = 0; j < 4; j++) 164 res4[j] = src4[j] & ~dst4[j]; 165 break; 166 case PIPE_LOGICOP_INVERT: 167 for (j = 0; j < 4; j++) 168 res4[j] = ~dst4[j]; 169 break; 170 case PIPE_LOGICOP_XOR: 171 for (j = 0; j < 4; j++) 172 res4[j] = dst4[j] ^ src4[j]; 173 break; 174 case PIPE_LOGICOP_NAND: 175 for (j = 0; j < 4; j++) 176 res4[j] = ~(src4[j] & dst4[j]); 177 break; 178 case PIPE_LOGICOP_AND: 179 for (j = 0; j < 4; j++) 180 res4[j] = src4[j] & dst4[j]; 181 break; 182 case PIPE_LOGICOP_EQUIV: 183 for (j = 0; j < 4; j++) 184 res4[j] = ~(src4[j] ^ dst4[j]); 185 break; 186 case PIPE_LOGICOP_NOOP: 187 for (j = 0; j < 4; j++) 188 res4[j] = dst4[j]; 189 break; 190 case PIPE_LOGICOP_OR_INVERTED: 191 for (j = 0; j < 4; j++) 192 res4[j] = ~src4[j] | dst4[j]; 193 break; 194 case PIPE_LOGICOP_COPY: 195 for (j = 0; j < 4; j++) 196 res4[j] = src4[j]; 197 break; 198 case PIPE_LOGICOP_OR_REVERSE: 199 for (j = 0; j < 4; j++) 200 res4[j] = src4[j] | ~dst4[j]; 201 break; 202 case PIPE_LOGICOP_OR: 203 for (j = 0; j < 4; j++) 204 res4[j] = src4[j] | dst4[j]; 205 break; 206 case PIPE_LOGICOP_SET: 207 for (j = 0; j < 4; j++) 208 res4[j] = ~0; 209 break; 210 default: 211 assert(0); 212 } 213 214 for (j = 0; j < 4; j++) { 215 quadColor[j][0] = ubyte_to_float(res[j][0]); 216 quadColor[j][1] = ubyte_to_float(res[j][1]); 217 quadColor[j][2] = ubyte_to_float(res[j][2]); 218 quadColor[j][3] = ubyte_to_float(res[j][3]); 219 } 220} 221 222 223 224static void 225blend_quad(struct quad_stage *qs, 226 float (*quadColor)[4], 227 float (*dest)[4]) 228{ 229 static const float zero[4] = { 0, 0, 0, 0 }; 230 static const float one[4] = { 1, 1, 1, 1 }; 231 struct softpipe_context *softpipe = qs->softpipe; 232 float source[4][QUAD_SIZE]; 233 234 /* 235 * Compute src/first term RGB 236 */ 237 switch (softpipe->blend->rgb_src_factor) { 238 case PIPE_BLENDFACTOR_ONE: 239 VEC4_COPY(source[0], quadColor[0]); /* R */ 240 VEC4_COPY(source[1], quadColor[1]); /* G */ 241 VEC4_COPY(source[2], quadColor[2]); /* B */ 242 break; 243 case PIPE_BLENDFACTOR_SRC_COLOR: 244 VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */ 245 VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */ 246 VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */ 247 break; 248 case PIPE_BLENDFACTOR_SRC_ALPHA: 249 { 250 const float *alpha = quadColor[3]; 251 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 252 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 253 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 254 } 255 break; 256 case PIPE_BLENDFACTOR_DST_COLOR: 257 VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */ 258 VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */ 259 VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */ 260 break; 261 case PIPE_BLENDFACTOR_DST_ALPHA: 262 { 263 const float *alpha = dest[3]; 264 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 265 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 266 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 267 } 268 break; 269 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 270 { 271 const float *alpha = quadColor[3]; 272 float diff[4], temp[4]; 273 VEC4_SUB(diff, one, dest[3]); 274 VEC4_MIN(temp, alpha, diff); 275 VEC4_MUL(source[0], quadColor[0], temp); /* R */ 276 VEC4_MUL(source[1], quadColor[1], temp); /* G */ 277 VEC4_MUL(source[2], quadColor[2], temp); /* B */ 278 } 279 break; 280 case PIPE_BLENDFACTOR_CONST_COLOR: 281 { 282 float comp[4]; 283 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */ 284 VEC4_MUL(source[0], quadColor[0], comp); /* R */ 285 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */ 286 VEC4_MUL(source[1], quadColor[1], comp); /* G */ 287 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */ 288 VEC4_MUL(source[2], quadColor[2], comp); /* B */ 289 } 290 break; 291 case PIPE_BLENDFACTOR_CONST_ALPHA: 292 { 293 float alpha[4]; 294 VEC4_SCALAR(alpha, softpipe->blend_color.color[3]); 295 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 296 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 297 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 298 } 299 break; 300 case PIPE_BLENDFACTOR_SRC1_COLOR: 301 assert(0); /* to do */ 302 break; 303 case PIPE_BLENDFACTOR_SRC1_ALPHA: 304 assert(0); /* to do */ 305 break; 306 case PIPE_BLENDFACTOR_ZERO: 307 VEC4_COPY(source[0], zero); /* R */ 308 VEC4_COPY(source[1], zero); /* G */ 309 VEC4_COPY(source[2], zero); /* B */ 310 break; 311 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 312 { 313 float inv_comp[4]; 314 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 315 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 316 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 317 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 318 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 319 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 320 } 321 break; 322 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 323 { 324 float inv_alpha[4]; 325 VEC4_SUB(inv_alpha, one, quadColor[3]); 326 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 327 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 328 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 329 } 330 break; 331 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 332 { 333 float inv_alpha[4]; 334 VEC4_SUB(inv_alpha, one, dest[3]); 335 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 336 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 337 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 338 } 339 break; 340 case PIPE_BLENDFACTOR_INV_DST_COLOR: 341 { 342 float inv_comp[4]; 343 VEC4_SUB(inv_comp, one, dest[0]); /* R */ 344 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 345 VEC4_SUB(inv_comp, one, dest[1]); /* G */ 346 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 347 VEC4_SUB(inv_comp, one, dest[2]); /* B */ 348 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 349 } 350 break; 351 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 352 { 353 float inv_comp[4]; 354 /* R */ 355 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]); 356 VEC4_MUL(source[0], quadColor[0], inv_comp); 357 /* G */ 358 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]); 359 VEC4_MUL(source[1], quadColor[1], inv_comp); 360 /* B */ 361 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]); 362 VEC4_MUL(source[2], quadColor[2], inv_comp); 363 } 364 break; 365 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 366 { 367 float inv_alpha[4]; 368 VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]); 369 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 370 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 371 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 372 } 373 break; 374 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 375 assert(0); /* to do */ 376 break; 377 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 378 assert(0); /* to do */ 379 break; 380 default: 381 assert(0); 382 } 383 384 /* 385 * Compute src/first term A 386 */ 387 switch (softpipe->blend->alpha_src_factor) { 388 case PIPE_BLENDFACTOR_ONE: 389 VEC4_COPY(source[3], quadColor[3]); /* A */ 390 break; 391 case PIPE_BLENDFACTOR_SRC_COLOR: 392 /* fall-through */ 393 case PIPE_BLENDFACTOR_SRC_ALPHA: 394 { 395 const float *alpha = quadColor[3]; 396 VEC4_MUL(source[3], quadColor[3], alpha); /* A */ 397 } 398 break; 399 case PIPE_BLENDFACTOR_DST_COLOR: 400 /* fall-through */ 401 case PIPE_BLENDFACTOR_DST_ALPHA: 402 VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */ 403 break; 404 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 405 /* multiply alpha by 1.0 */ 406 VEC4_COPY(source[3], quadColor[3]); /* A */ 407 break; 408 case PIPE_BLENDFACTOR_CONST_COLOR: 409 /* fall-through */ 410 case PIPE_BLENDFACTOR_CONST_ALPHA: 411 { 412 float comp[4]; 413 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 414 VEC4_MUL(source[3], quadColor[3], comp); /* A */ 415 } 416 break; 417 case PIPE_BLENDFACTOR_ZERO: 418 VEC4_COPY(source[3], zero); /* A */ 419 break; 420 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 421 /* fall-through */ 422 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 423 { 424 float inv_alpha[4]; 425 VEC4_SUB(inv_alpha, one, quadColor[3]); 426 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 427 } 428 break; 429 case PIPE_BLENDFACTOR_INV_DST_COLOR: 430 /* fall-through */ 431 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 432 { 433 float inv_alpha[4]; 434 VEC4_SUB(inv_alpha, one, dest[3]); 435 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 436 } 437 break; 438 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 439 /* fall-through */ 440 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 441 { 442 float inv_comp[4]; 443 /* A */ 444 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 445 VEC4_MUL(source[3], quadColor[3], inv_comp); 446 } 447 break; 448 default: 449 assert(0); 450 } 451 452 453 /* 454 * Compute dest/second term RGB 455 */ 456 switch (softpipe->blend->rgb_dst_factor) { 457 case PIPE_BLENDFACTOR_ONE: 458 /* dest = dest * 1 NO-OP, leave dest as-is */ 459 break; 460 case PIPE_BLENDFACTOR_SRC_COLOR: 461 VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */ 462 VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */ 463 VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */ 464 break; 465 case PIPE_BLENDFACTOR_SRC_ALPHA: 466 VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */ 467 VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */ 468 VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */ 469 break; 470 case PIPE_BLENDFACTOR_DST_ALPHA: 471 VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */ 472 VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */ 473 VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */ 474 break; 475 case PIPE_BLENDFACTOR_DST_COLOR: 476 VEC4_MUL(dest[0], dest[0], dest[0]); /* R */ 477 VEC4_MUL(dest[1], dest[1], dest[1]); /* G */ 478 VEC4_MUL(dest[2], dest[2], dest[2]); /* B */ 479 break; 480 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 481 assert(0); /* illegal */ 482 break; 483 case PIPE_BLENDFACTOR_CONST_COLOR: 484 { 485 float comp[4]; 486 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */ 487 VEC4_MUL(dest[0], dest[0], comp); /* R */ 488 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */ 489 VEC4_MUL(dest[1], dest[1], comp); /* G */ 490 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */ 491 VEC4_MUL(dest[2], dest[2], comp); /* B */ 492 } 493 break; 494 case PIPE_BLENDFACTOR_CONST_ALPHA: 495 { 496 float comp[4]; 497 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 498 VEC4_MUL(dest[0], dest[0], comp); /* R */ 499 VEC4_MUL(dest[1], dest[1], comp); /* G */ 500 VEC4_MUL(dest[2], dest[2], comp); /* B */ 501 } 502 break; 503 case PIPE_BLENDFACTOR_ZERO: 504 VEC4_COPY(dest[0], zero); /* R */ 505 VEC4_COPY(dest[1], zero); /* G */ 506 VEC4_COPY(dest[2], zero); /* B */ 507 break; 508 case PIPE_BLENDFACTOR_SRC1_COLOR: 509 case PIPE_BLENDFACTOR_SRC1_ALPHA: 510 /* XXX what are these? */ 511 assert(0); 512 break; 513 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 514 { 515 float inv_comp[4]; 516 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 517 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ 518 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 519 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ 520 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 521 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ 522 } 523 break; 524 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 525 { 526 float one_minus_alpha[QUAD_SIZE]; 527 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 528 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */ 529 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */ 530 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */ 531 } 532 break; 533 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 534 { 535 float inv_comp[4]; 536 VEC4_SUB(inv_comp, one, dest[3]); /* A */ 537 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ 538 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ 539 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ 540 } 541 break; 542 case PIPE_BLENDFACTOR_INV_DST_COLOR: 543 { 544 float inv_comp[4]; 545 VEC4_SUB(inv_comp, one, dest[0]); /* R */ 546 VEC4_MUL(dest[0], dest[0], inv_comp); /* R */ 547 VEC4_SUB(inv_comp, one, dest[1]); /* G */ 548 VEC4_MUL(dest[1], dest[1], inv_comp); /* G */ 549 VEC4_SUB(inv_comp, one, dest[2]); /* B */ 550 VEC4_MUL(dest[2], dest[2], inv_comp); /* B */ 551 } 552 break; 553 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 554 { 555 float inv_comp[4]; 556 /* R */ 557 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]); 558 VEC4_MUL(dest[0], dest[0], inv_comp); 559 /* G */ 560 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]); 561 VEC4_MUL(dest[1], dest[1], inv_comp); 562 /* B */ 563 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]); 564 VEC4_MUL(dest[2], dest[2], inv_comp); 565 } 566 break; 567 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 568 { 569 float inv_comp[4]; 570 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 571 VEC4_MUL(dest[0], dest[0], inv_comp); 572 VEC4_MUL(dest[1], dest[1], inv_comp); 573 VEC4_MUL(dest[2], dest[2], inv_comp); 574 } 575 break; 576 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 577 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 578 /* XXX what are these? */ 579 assert(0); 580 break; 581 default: 582 assert(0); 583 } 584 585 /* 586 * Compute dest/second term A 587 */ 588 switch (softpipe->blend->alpha_dst_factor) { 589 case PIPE_BLENDFACTOR_ONE: 590 /* dest = dest * 1 NO-OP, leave dest as-is */ 591 break; 592 case PIPE_BLENDFACTOR_SRC_COLOR: 593 /* fall-through */ 594 case PIPE_BLENDFACTOR_SRC_ALPHA: 595 VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */ 596 break; 597 case PIPE_BLENDFACTOR_DST_COLOR: 598 /* fall-through */ 599 case PIPE_BLENDFACTOR_DST_ALPHA: 600 VEC4_MUL(dest[3], dest[3], dest[3]); /* A */ 601 break; 602 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 603 assert(0); /* illegal */ 604 break; 605 case PIPE_BLENDFACTOR_CONST_COLOR: 606 /* fall-through */ 607 case PIPE_BLENDFACTOR_CONST_ALPHA: 608 { 609 float comp[4]; 610 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */ 611 VEC4_MUL(dest[3], dest[3], comp); /* A */ 612 } 613 break; 614 case PIPE_BLENDFACTOR_ZERO: 615 VEC4_COPY(dest[3], zero); /* A */ 616 break; 617 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 618 /* fall-through */ 619 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 620 { 621 float one_minus_alpha[QUAD_SIZE]; 622 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 623 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */ 624 } 625 break; 626 case PIPE_BLENDFACTOR_INV_DST_COLOR: 627 /* fall-through */ 628 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 629 { 630 float inv_comp[4]; 631 VEC4_SUB(inv_comp, one, dest[3]); /* A */ 632 VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */ 633 } 634 break; 635 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 636 /* fall-through */ 637 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 638 { 639 float inv_comp[4]; 640 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]); 641 VEC4_MUL(dest[3], dest[3], inv_comp); 642 } 643 break; 644 default: 645 assert(0); 646 } 647 648 /* 649 * Combine RGB terms 650 */ 651 switch (softpipe->blend->rgb_func) { 652 case PIPE_BLEND_ADD: 653 VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */ 654 VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */ 655 VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */ 656 break; 657 case PIPE_BLEND_SUBTRACT: 658 VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */ 659 VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */ 660 VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */ 661 break; 662 case PIPE_BLEND_REVERSE_SUBTRACT: 663 VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */ 664 VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */ 665 VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */ 666 break; 667 case PIPE_BLEND_MIN: 668 VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */ 669 VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */ 670 VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */ 671 break; 672 case PIPE_BLEND_MAX: 673 VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */ 674 VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */ 675 VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */ 676 break; 677 default: 678 assert(0); 679 } 680 681 /* 682 * Combine A terms 683 */ 684 switch (softpipe->blend->alpha_func) { 685 case PIPE_BLEND_ADD: 686 VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */ 687 break; 688 case PIPE_BLEND_SUBTRACT: 689 VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */ 690 break; 691 case PIPE_BLEND_REVERSE_SUBTRACT: 692 VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */ 693 break; 694 case PIPE_BLEND_MIN: 695 VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */ 696 break; 697 case PIPE_BLEND_MAX: 698 VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */ 699 break; 700 default: 701 assert(0); 702 } 703} 704 705static void 706colormask_quad(struct quad_stage *qs, 707 float (*quadColor)[4], 708 float (*dest)[4]) 709{ 710 struct softpipe_context *softpipe = qs->softpipe; 711 712 /* R */ 713 if (!(softpipe->blend->colormask & PIPE_MASK_R)) 714 COPY_4V(quadColor[0], dest[0]); 715 716 /* G */ 717 if (!(softpipe->blend->colormask & PIPE_MASK_G)) 718 COPY_4V(quadColor[1], dest[1]); 719 720 /* B */ 721 if (!(softpipe->blend->colormask & PIPE_MASK_B)) 722 COPY_4V(quadColor[2], dest[2]); 723 724 /* A */ 725 if (!(softpipe->blend->colormask & PIPE_MASK_A)) 726 COPY_4V(quadColor[3], dest[3]); 727} 728 729 730static void 731blend_fallback(struct quad_stage *qs, 732 struct quad_header *quads[], 733 unsigned nr) 734{ 735 struct softpipe_context *softpipe = qs->softpipe; 736 const struct pipe_blend_state *blend = softpipe->blend; 737 unsigned cbuf; 738 739 for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) 740 { 741 float dest[4][QUAD_SIZE]; 742 struct softpipe_cached_tile *tile 743 = sp_get_cached_tile(softpipe->cbuf_cache[cbuf], 744 quads[0]->input.x0, 745 quads[0]->input.y0); 746 uint q, i, j; 747 748 for (q = 0; q < nr; q++) { 749 struct quad_header *quad = quads[q]; 750 float (*quadColor)[4] = quad->output.color[cbuf]; 751 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 752 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 753 754 /* get/swizzle dest colors 755 */ 756 for (j = 0; j < QUAD_SIZE; j++) { 757 int x = itx + (j & 1); 758 int y = ity + (j >> 1); 759 for (i = 0; i < 4; i++) { 760 dest[i][j] = tile->data.color[y][x][i]; 761 } 762 } 763 764 765 if (blend->logicop_enable) { 766 logicop_quad( qs, quadColor, dest ); 767 } 768 else if (blend->blend_enable) { 769 blend_quad( qs, quadColor, dest ); 770 } 771 772 if (blend->colormask != 0xf) 773 colormask_quad( qs, quadColor, dest ); 774 775 /* Output color values 776 */ 777 for (j = 0; j < QUAD_SIZE; j++) { 778 if (quad->inout.mask & (1 << j)) { 779 int x = itx + (j & 1); 780 int y = ity + (j >> 1); 781 for (i = 0; i < 4; i++) { /* loop over color chans */ 782 tile->data.color[y][x][i] = quadColor[i][j]; 783 } 784 } 785 } 786 } 787 } 788} 789 790 791static void 792blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs, 793 struct quad_header *quads[], 794 unsigned nr) 795{ 796 static const float one[4] = { 1, 1, 1, 1 }; 797 float one_minus_alpha[QUAD_SIZE]; 798 float dest[4][QUAD_SIZE]; 799 float source[4][QUAD_SIZE]; 800 uint i, j, q; 801 802 struct softpipe_cached_tile *tile 803 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 804 quads[0]->input.x0, 805 quads[0]->input.y0); 806 807 for (q = 0; q < nr; q++) { 808 struct quad_header *quad = quads[q]; 809 float (*quadColor)[4] = quad->output.color[0]; 810 const float *alpha = quadColor[3]; 811 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 812 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 813 814 /* get/swizzle dest colors */ 815 for (j = 0; j < QUAD_SIZE; j++) { 816 int x = itx + (j & 1); 817 int y = ity + (j >> 1); 818 for (i = 0; i < 4; i++) { 819 dest[i][j] = tile->data.color[y][x][i]; 820 } 821 } 822 823 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 824 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 825 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 826 VEC4_MUL(source[3], quadColor[3], alpha); /* A */ 827 828 VEC4_SUB(one_minus_alpha, one, alpha); 829 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */ 830 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */ 831 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */ 832 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* B */ 833 834 VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */ 835 VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */ 836 VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */ 837 VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */ 838 839 for (j = 0; j < QUAD_SIZE; j++) { 840 if (quad->inout.mask & (1 << j)) { 841 int x = itx + (j & 1); 842 int y = ity + (j >> 1); 843 for (i = 0; i < 4; i++) { /* loop over color chans */ 844 tile->data.color[y][x][i] = quadColor[i][j]; 845 } 846 } 847 } 848 } 849} 850 851static void 852blend_single_add_one_one(struct quad_stage *qs, 853 struct quad_header *quads[], 854 unsigned nr) 855{ 856 float dest[4][QUAD_SIZE]; 857 uint i, j, q; 858 859 struct softpipe_cached_tile *tile 860 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 861 quads[0]->input.x0, 862 quads[0]->input.y0); 863 864 for (q = 0; q < nr; q++) { 865 struct quad_header *quad = quads[q]; 866 float (*quadColor)[4] = quad->output.color[0]; 867 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 868 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 869 870 /* get/swizzle dest colors */ 871 for (j = 0; j < QUAD_SIZE; j++) { 872 int x = itx + (j & 1); 873 int y = ity + (j >> 1); 874 for (i = 0; i < 4; i++) { 875 dest[i][j] = tile->data.color[y][x][i]; 876 } 877 } 878 879 VEC4_ADD_SAT(quadColor[0], quadColor[0], dest[0]); /* R */ 880 VEC4_ADD_SAT(quadColor[1], quadColor[1], dest[1]); /* G */ 881 VEC4_ADD_SAT(quadColor[2], quadColor[2], dest[2]); /* B */ 882 VEC4_ADD_SAT(quadColor[3], quadColor[3], dest[3]); /* A */ 883 884 for (j = 0; j < QUAD_SIZE; j++) { 885 if (quad->inout.mask & (1 << j)) { 886 int x = itx + (j & 1); 887 int y = ity + (j >> 1); 888 for (i = 0; i < 4; i++) { /* loop over color chans */ 889 tile->data.color[y][x][i] = quadColor[i][j]; 890 } 891 } 892 } 893 } 894} 895 896 897static void 898single_output_color(struct quad_stage *qs, 899 struct quad_header *quads[], 900 unsigned nr) 901{ 902 uint i, j, q; 903 904 struct softpipe_cached_tile *tile 905 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 906 quads[0]->input.x0, 907 quads[0]->input.y0); 908 909 for (q = 0; q < nr; q++) { 910 struct quad_header *quad = quads[q]; 911 float (*quadColor)[4] = quad->output.color[0]; 912 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 913 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 914 915 for (j = 0; j < QUAD_SIZE; j++) { 916 if (quad->inout.mask & (1 << j)) { 917 int x = itx + (j & 1); 918 int y = ity + (j >> 1); 919 for (i = 0; i < 4; i++) { /* loop over color chans */ 920 tile->data.color[y][x][i] = quadColor[i][j]; 921 } 922 } 923 } 924 } 925} 926 927static void 928blend_noop(struct quad_stage *qs, 929 struct quad_header *quads[], 930 unsigned nr) 931{ 932} 933 934 935static void 936choose_blend_quad(struct quad_stage *qs, 937 struct quad_header *quads[], 938 unsigned nr) 939{ 940 struct softpipe_context *softpipe = qs->softpipe; 941 const struct pipe_blend_state *blend = softpipe->blend; 942 943 qs->run = blend_fallback; 944 945 if (softpipe->framebuffer.nr_cbufs == 0) { 946 qs->run = blend_noop; 947 } 948 else if (!softpipe->blend->logicop_enable && 949 softpipe->blend->colormask == 0xf) 950 { 951 if (!blend->blend_enable) { 952 qs->run = single_output_color; 953 } 954 else if (blend->rgb_src_factor == blend->alpha_src_factor && 955 blend->rgb_dst_factor == blend->alpha_dst_factor && 956 blend->rgb_func == blend->alpha_func && 957 softpipe->framebuffer.nr_cbufs == 1) 958 { 959 if (blend->alpha_func == PIPE_BLEND_ADD) { 960 if (blend->rgb_src_factor == PIPE_BLENDFACTOR_ONE && 961 blend->rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { 962 qs->run = blend_single_add_one_one; 963 } 964 else if (blend->rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && 965 blend->rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) 966 qs->run = blend_single_add_src_alpha_inv_src_alpha; 967 968 } 969 } 970 } 971 972 qs->run(qs, quads, nr); 973} 974 975 976static void blend_begin(struct quad_stage *qs) 977{ 978 qs->run = choose_blend_quad; 979} 980 981 982static void blend_destroy(struct quad_stage *qs) 983{ 984 FREE( qs ); 985} 986 987 988struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ) 989{ 990 struct quad_stage *stage = CALLOC_STRUCT(quad_stage); 991 992 stage->softpipe = softpipe; 993 stage->begin = blend_begin; 994 stage->run = choose_blend_quad; 995 stage->destroy = blend_destroy; 996 997 return stage; 998} 999