sp_quad_blend.c revision 0fe2b397bbee346f72f48f364a78459e5a54c534
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 "util/u_format.h" 37#include "sp_context.h" 38#include "sp_state.h" 39#include "sp_quad.h" 40#include "sp_tile_cache.h" 41#include "sp_quad_pipe.h" 42 43 44enum format 45{ 46 RGBA, 47 RGB, 48 LUMINANCE, 49 LUMINANCE_ALPHA, 50 INTENSITY 51}; 52 53 54/** Subclass of quad_stage */ 55struct blend_quad_stage 56{ 57 struct quad_stage base; 58 boolean clamp[PIPE_MAX_COLOR_BUFS]; /**< clamp colors to [0,1]? */ 59 enum format base_format[PIPE_MAX_COLOR_BUFS]; 60 enum util_format_type format_type[PIPE_MAX_COLOR_BUFS]; 61}; 62 63 64/** cast wrapper */ 65static INLINE struct blend_quad_stage * 66blend_quad_stage(struct quad_stage *stage) 67{ 68 return (struct blend_quad_stage *) stage; 69} 70 71 72#define VEC4_COPY(DST, SRC) \ 73do { \ 74 DST[0] = SRC[0]; \ 75 DST[1] = SRC[1]; \ 76 DST[2] = SRC[2]; \ 77 DST[3] = SRC[3]; \ 78} while(0) 79 80#define VEC4_SCALAR(DST, SRC) \ 81do { \ 82 DST[0] = SRC; \ 83 DST[1] = SRC; \ 84 DST[2] = SRC; \ 85 DST[3] = SRC; \ 86} while(0) 87 88#define VEC4_ADD(R, A, B) \ 89do { \ 90 R[0] = A[0] + B[0]; \ 91 R[1] = A[1] + B[1]; \ 92 R[2] = A[2] + B[2]; \ 93 R[3] = A[3] + B[3]; \ 94} while (0) 95 96#define VEC4_SUB(R, A, B) \ 97do { \ 98 R[0] = A[0] - B[0]; \ 99 R[1] = A[1] - B[1]; \ 100 R[2] = A[2] - B[2]; \ 101 R[3] = A[3] - B[3]; \ 102} while (0) 103 104/** Add and limit result to ceiling of 1.0 */ 105#define VEC4_ADD_SAT(R, A, B) \ 106do { \ 107 R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \ 108 R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \ 109 R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \ 110 R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \ 111} while (0) 112 113/** Subtract and limit result to floor of 0.0 */ 114#define VEC4_SUB_SAT(R, A, B) \ 115do { \ 116 R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \ 117 R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \ 118 R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \ 119 R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \ 120} while (0) 121 122#define VEC4_MUL(R, A, B) \ 123do { \ 124 R[0] = A[0] * B[0]; \ 125 R[1] = A[1] * B[1]; \ 126 R[2] = A[2] * B[2]; \ 127 R[3] = A[3] * B[3]; \ 128} while (0) 129 130#define VEC4_MIN(R, A, B) \ 131do { \ 132 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \ 133 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \ 134 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \ 135 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \ 136} while (0) 137 138#define VEC4_MAX(R, A, B) \ 139do { \ 140 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \ 141 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \ 142 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \ 143 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \ 144} while (0) 145 146 147 148static void 149logicop_quad(struct quad_stage *qs, 150 float (*quadColor)[4], 151 float (*dest)[4]) 152{ 153 struct softpipe_context *softpipe = qs->softpipe; 154 ubyte src[4][4], dst[4][4], res[4][4]; 155 uint *src4 = (uint *) src; 156 uint *dst4 = (uint *) dst; 157 uint *res4 = (uint *) res; 158 uint j; 159 160 161 /* convert to ubyte */ 162 for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */ 163 dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */ 164 dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */ 165 dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */ 166 dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */ 167 168 src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */ 169 src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */ 170 src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */ 171 src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */ 172 } 173 174 switch (softpipe->blend->logicop_func) { 175 case PIPE_LOGICOP_CLEAR: 176 for (j = 0; j < 4; j++) 177 res4[j] = 0; 178 break; 179 case PIPE_LOGICOP_NOR: 180 for (j = 0; j < 4; j++) 181 res4[j] = ~(src4[j] | dst4[j]); 182 break; 183 case PIPE_LOGICOP_AND_INVERTED: 184 for (j = 0; j < 4; j++) 185 res4[j] = ~src4[j] & dst4[j]; 186 break; 187 case PIPE_LOGICOP_COPY_INVERTED: 188 for (j = 0; j < 4; j++) 189 res4[j] = ~src4[j]; 190 break; 191 case PIPE_LOGICOP_AND_REVERSE: 192 for (j = 0; j < 4; j++) 193 res4[j] = src4[j] & ~dst4[j]; 194 break; 195 case PIPE_LOGICOP_INVERT: 196 for (j = 0; j < 4; j++) 197 res4[j] = ~dst4[j]; 198 break; 199 case PIPE_LOGICOP_XOR: 200 for (j = 0; j < 4; j++) 201 res4[j] = dst4[j] ^ src4[j]; 202 break; 203 case PIPE_LOGICOP_NAND: 204 for (j = 0; j < 4; j++) 205 res4[j] = ~(src4[j] & dst4[j]); 206 break; 207 case PIPE_LOGICOP_AND: 208 for (j = 0; j < 4; j++) 209 res4[j] = src4[j] & dst4[j]; 210 break; 211 case PIPE_LOGICOP_EQUIV: 212 for (j = 0; j < 4; j++) 213 res4[j] = ~(src4[j] ^ dst4[j]); 214 break; 215 case PIPE_LOGICOP_NOOP: 216 for (j = 0; j < 4; j++) 217 res4[j] = dst4[j]; 218 break; 219 case PIPE_LOGICOP_OR_INVERTED: 220 for (j = 0; j < 4; j++) 221 res4[j] = ~src4[j] | dst4[j]; 222 break; 223 case PIPE_LOGICOP_COPY: 224 for (j = 0; j < 4; j++) 225 res4[j] = src4[j]; 226 break; 227 case PIPE_LOGICOP_OR_REVERSE: 228 for (j = 0; j < 4; j++) 229 res4[j] = src4[j] | ~dst4[j]; 230 break; 231 case PIPE_LOGICOP_OR: 232 for (j = 0; j < 4; j++) 233 res4[j] = src4[j] | dst4[j]; 234 break; 235 case PIPE_LOGICOP_SET: 236 for (j = 0; j < 4; j++) 237 res4[j] = ~0; 238 break; 239 default: 240 assert(0 && "invalid logicop mode"); 241 } 242 243 for (j = 0; j < 4; j++) { 244 quadColor[j][0] = ubyte_to_float(res[j][0]); 245 quadColor[j][1] = ubyte_to_float(res[j][1]); 246 quadColor[j][2] = ubyte_to_float(res[j][2]); 247 quadColor[j][3] = ubyte_to_float(res[j][3]); 248 } 249} 250 251 252 253/** 254 * Do blending for a 2x2 quad for one color buffer. 255 * \param quadColor the incoming quad colors 256 * \param dest the destination/framebuffer quad colors 257 * \param const_blend_color the constant blend color 258 * \param blend_index which set of blending terms to use 259 */ 260static void 261blend_quad(struct quad_stage *qs, 262 float (*quadColor)[4], 263 float (*dest)[4], 264 const float const_blend_color[4], 265 unsigned blend_index) 266{ 267 static const float zero[4] = { 0, 0, 0, 0 }; 268 static const float one[4] = { 1, 1, 1, 1 }; 269 struct softpipe_context *softpipe = qs->softpipe; 270 float source[4][QUAD_SIZE] = { { 0 } }; 271 float blend_dest[4][QUAD_SIZE]; 272 273 /* 274 * Compute src/first term RGB 275 */ 276 switch (softpipe->blend->rt[blend_index].rgb_src_factor) { 277 case PIPE_BLENDFACTOR_ONE: 278 VEC4_COPY(source[0], quadColor[0]); /* R */ 279 VEC4_COPY(source[1], quadColor[1]); /* G */ 280 VEC4_COPY(source[2], quadColor[2]); /* B */ 281 break; 282 case PIPE_BLENDFACTOR_SRC_COLOR: 283 VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */ 284 VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */ 285 VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */ 286 break; 287 case PIPE_BLENDFACTOR_SRC_ALPHA: 288 { 289 const float *alpha = quadColor[3]; 290 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 291 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 292 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 293 } 294 break; 295 case PIPE_BLENDFACTOR_DST_COLOR: 296 VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */ 297 VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */ 298 VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */ 299 break; 300 case PIPE_BLENDFACTOR_DST_ALPHA: 301 { 302 const float *alpha = dest[3]; 303 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 304 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 305 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 306 } 307 break; 308 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 309 { 310 const float *alpha = quadColor[3]; 311 float diff[4], temp[4]; 312 VEC4_SUB(diff, one, dest[3]); 313 VEC4_MIN(temp, alpha, diff); 314 VEC4_MUL(source[0], quadColor[0], temp); /* R */ 315 VEC4_MUL(source[1], quadColor[1], temp); /* G */ 316 VEC4_MUL(source[2], quadColor[2], temp); /* B */ 317 } 318 break; 319 case PIPE_BLENDFACTOR_CONST_COLOR: 320 { 321 float comp[4]; 322 VEC4_SCALAR(comp, const_blend_color[0]); /* R */ 323 VEC4_MUL(source[0], quadColor[0], comp); /* R */ 324 VEC4_SCALAR(comp, const_blend_color[1]); /* G */ 325 VEC4_MUL(source[1], quadColor[1], comp); /* G */ 326 VEC4_SCALAR(comp, const_blend_color[2]); /* B */ 327 VEC4_MUL(source[2], quadColor[2], comp); /* B */ 328 } 329 break; 330 case PIPE_BLENDFACTOR_CONST_ALPHA: 331 { 332 float alpha[4]; 333 VEC4_SCALAR(alpha, const_blend_color[3]); 334 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 335 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 336 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 337 } 338 break; 339 case PIPE_BLENDFACTOR_SRC1_COLOR: 340 assert(0); /* to do */ 341 break; 342 case PIPE_BLENDFACTOR_SRC1_ALPHA: 343 assert(0); /* to do */ 344 break; 345 case PIPE_BLENDFACTOR_ZERO: 346 VEC4_COPY(source[0], zero); /* R */ 347 VEC4_COPY(source[1], zero); /* G */ 348 VEC4_COPY(source[2], zero); /* B */ 349 break; 350 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 351 { 352 float inv_comp[4]; 353 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 354 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 355 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 356 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 357 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 358 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 359 } 360 break; 361 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 362 { 363 float inv_alpha[4]; 364 VEC4_SUB(inv_alpha, one, quadColor[3]); 365 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 366 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 367 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 368 } 369 break; 370 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 371 { 372 float inv_alpha[4]; 373 VEC4_SUB(inv_alpha, one, dest[3]); 374 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 375 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 376 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 377 } 378 break; 379 case PIPE_BLENDFACTOR_INV_DST_COLOR: 380 { 381 float inv_comp[4]; 382 VEC4_SUB(inv_comp, one, dest[0]); /* R */ 383 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */ 384 VEC4_SUB(inv_comp, one, dest[1]); /* G */ 385 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */ 386 VEC4_SUB(inv_comp, one, dest[2]); /* B */ 387 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */ 388 } 389 break; 390 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 391 { 392 float inv_comp[4]; 393 /* R */ 394 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]); 395 VEC4_MUL(source[0], quadColor[0], inv_comp); 396 /* G */ 397 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]); 398 VEC4_MUL(source[1], quadColor[1], inv_comp); 399 /* B */ 400 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]); 401 VEC4_MUL(source[2], quadColor[2], inv_comp); 402 } 403 break; 404 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 405 { 406 float inv_alpha[4]; 407 VEC4_SCALAR(inv_alpha, 1.0f - const_blend_color[3]); 408 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ 409 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ 410 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ 411 } 412 break; 413 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 414 assert(0); /* to do */ 415 break; 416 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 417 assert(0); /* to do */ 418 break; 419 default: 420 assert(0 && "invalid rgb src factor"); 421 } 422 423 /* 424 * Compute src/first term A 425 */ 426 switch (softpipe->blend->rt[blend_index].alpha_src_factor) { 427 case PIPE_BLENDFACTOR_ONE: 428 VEC4_COPY(source[3], quadColor[3]); /* A */ 429 break; 430 case PIPE_BLENDFACTOR_SRC_COLOR: 431 /* fall-through */ 432 case PIPE_BLENDFACTOR_SRC_ALPHA: 433 { 434 const float *alpha = quadColor[3]; 435 VEC4_MUL(source[3], quadColor[3], alpha); /* A */ 436 } 437 break; 438 case PIPE_BLENDFACTOR_DST_COLOR: 439 /* fall-through */ 440 case PIPE_BLENDFACTOR_DST_ALPHA: 441 VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */ 442 break; 443 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 444 /* multiply alpha by 1.0 */ 445 VEC4_COPY(source[3], quadColor[3]); /* A */ 446 break; 447 case PIPE_BLENDFACTOR_CONST_COLOR: 448 /* fall-through */ 449 case PIPE_BLENDFACTOR_CONST_ALPHA: 450 { 451 float comp[4]; 452 VEC4_SCALAR(comp, const_blend_color[3]); /* A */ 453 VEC4_MUL(source[3], quadColor[3], comp); /* A */ 454 } 455 break; 456 case PIPE_BLENDFACTOR_ZERO: 457 VEC4_COPY(source[3], zero); /* A */ 458 break; 459 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 460 /* fall-through */ 461 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 462 { 463 float inv_alpha[4]; 464 VEC4_SUB(inv_alpha, one, quadColor[3]); 465 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 466 } 467 break; 468 case PIPE_BLENDFACTOR_INV_DST_COLOR: 469 /* fall-through */ 470 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 471 { 472 float inv_alpha[4]; 473 VEC4_SUB(inv_alpha, one, dest[3]); 474 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ 475 } 476 break; 477 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 478 /* fall-through */ 479 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 480 { 481 float inv_comp[4]; 482 /* A */ 483 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]); 484 VEC4_MUL(source[3], quadColor[3], inv_comp); 485 } 486 break; 487 default: 488 assert(0 && "invalid alpha src factor"); 489 } 490 491 /* Save the original dest for use in masking */ 492 VEC4_COPY(blend_dest[0], dest[0]); 493 VEC4_COPY(blend_dest[1], dest[1]); 494 VEC4_COPY(blend_dest[2], dest[2]); 495 VEC4_COPY(blend_dest[3], dest[3]); 496 497 498 /* 499 * Compute blend_dest/second term RGB 500 */ 501 switch (softpipe->blend->rt[blend_index].rgb_dst_factor) { 502 case PIPE_BLENDFACTOR_ONE: 503 /* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */ 504 break; 505 case PIPE_BLENDFACTOR_SRC_COLOR: 506 VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[0]); /* R */ 507 VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[1]); /* G */ 508 VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[2]); /* B */ 509 break; 510 case PIPE_BLENDFACTOR_SRC_ALPHA: 511 VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[3]); /* R * A */ 512 VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[3]); /* G * A */ 513 VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[3]); /* B * A */ 514 break; 515 case PIPE_BLENDFACTOR_DST_ALPHA: 516 VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[3]); /* R * A */ 517 VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[3]); /* G * A */ 518 VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[3]); /* B * A */ 519 break; 520 case PIPE_BLENDFACTOR_DST_COLOR: 521 VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[0]); /* R */ 522 VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[1]); /* G */ 523 VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[2]); /* B */ 524 break; 525 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 526 { 527 const float *alpha = quadColor[3]; 528 float diff[4], temp[4]; 529 VEC4_SUB(diff, one, blend_dest[3]); 530 VEC4_MIN(temp, alpha, diff); 531 VEC4_MUL(blend_dest[0], quadColor[0], temp); /* R */ 532 VEC4_MUL(blend_dest[1], quadColor[1], temp); /* G */ 533 VEC4_MUL(blend_dest[2], quadColor[2], temp); /* B */ 534 } 535 break; 536 case PIPE_BLENDFACTOR_CONST_COLOR: 537 { 538 float comp[4]; 539 VEC4_SCALAR(comp, const_blend_color[0]); /* R */ 540 VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */ 541 VEC4_SCALAR(comp, const_blend_color[1]); /* G */ 542 VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */ 543 VEC4_SCALAR(comp, const_blend_color[2]); /* B */ 544 VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */ 545 } 546 break; 547 case PIPE_BLENDFACTOR_CONST_ALPHA: 548 { 549 float comp[4]; 550 VEC4_SCALAR(comp, const_blend_color[3]); /* A */ 551 VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */ 552 VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */ 553 VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */ 554 } 555 break; 556 case PIPE_BLENDFACTOR_ZERO: 557 VEC4_COPY(blend_dest[0], zero); /* R */ 558 VEC4_COPY(blend_dest[1], zero); /* G */ 559 VEC4_COPY(blend_dest[2], zero); /* B */ 560 break; 561 case PIPE_BLENDFACTOR_SRC1_COLOR: 562 case PIPE_BLENDFACTOR_SRC1_ALPHA: 563 /* XXX what are these? */ 564 assert(0); 565 break; 566 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 567 { 568 float inv_comp[4]; 569 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */ 570 VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */ 571 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */ 572 VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */ 573 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */ 574 VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */ 575 } 576 break; 577 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 578 { 579 float one_minus_alpha[QUAD_SIZE]; 580 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 581 VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */ 582 VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */ 583 VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */ 584 } 585 break; 586 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 587 { 588 float inv_comp[4]; 589 VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */ 590 VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */ 591 VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */ 592 VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */ 593 } 594 break; 595 case PIPE_BLENDFACTOR_INV_DST_COLOR: 596 { 597 float inv_comp[4]; 598 VEC4_SUB(inv_comp, one, blend_dest[0]); /* R */ 599 VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); /* R */ 600 VEC4_SUB(inv_comp, one, blend_dest[1]); /* G */ 601 VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); /* G */ 602 VEC4_SUB(inv_comp, one, blend_dest[2]); /* B */ 603 VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); /* B */ 604 } 605 break; 606 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 607 { 608 float inv_comp[4]; 609 /* R */ 610 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]); 611 VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); 612 /* G */ 613 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]); 614 VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); 615 /* B */ 616 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]); 617 VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); 618 } 619 break; 620 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 621 { 622 float inv_comp[4]; 623 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]); 624 VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); 625 VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); 626 VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); 627 } 628 break; 629 case PIPE_BLENDFACTOR_INV_SRC1_COLOR: 630 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: 631 /* XXX what are these? */ 632 assert(0); 633 break; 634 default: 635 assert(0 && "invalid rgb dst factor"); 636 } 637 638 /* 639 * Compute blend_dest/second term A 640 */ 641 switch (softpipe->blend->rt[blend_index].alpha_dst_factor) { 642 case PIPE_BLENDFACTOR_ONE: 643 /* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */ 644 break; 645 case PIPE_BLENDFACTOR_SRC_COLOR: 646 /* fall-through */ 647 case PIPE_BLENDFACTOR_SRC_ALPHA: 648 VEC4_MUL(blend_dest[3], blend_dest[3], quadColor[3]); /* A * A */ 649 break; 650 case PIPE_BLENDFACTOR_DST_COLOR: 651 /* fall-through */ 652 case PIPE_BLENDFACTOR_DST_ALPHA: 653 VEC4_MUL(blend_dest[3], blend_dest[3], blend_dest[3]); /* A */ 654 break; 655 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 656 /* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */ 657 break; 658 case PIPE_BLENDFACTOR_CONST_COLOR: 659 /* fall-through */ 660 case PIPE_BLENDFACTOR_CONST_ALPHA: 661 { 662 float comp[4]; 663 VEC4_SCALAR(comp, const_blend_color[3]); /* A */ 664 VEC4_MUL(blend_dest[3], blend_dest[3], comp); /* A */ 665 } 666 break; 667 case PIPE_BLENDFACTOR_ZERO: 668 VEC4_COPY(blend_dest[3], zero); /* A */ 669 break; 670 case PIPE_BLENDFACTOR_INV_SRC_COLOR: 671 /* fall-through */ 672 case PIPE_BLENDFACTOR_INV_SRC_ALPHA: 673 { 674 float one_minus_alpha[QUAD_SIZE]; 675 VEC4_SUB(one_minus_alpha, one, quadColor[3]); 676 VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */ 677 } 678 break; 679 case PIPE_BLENDFACTOR_INV_DST_COLOR: 680 /* fall-through */ 681 case PIPE_BLENDFACTOR_INV_DST_ALPHA: 682 { 683 float inv_comp[4]; 684 VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */ 685 VEC4_MUL(blend_dest[3], inv_comp, blend_dest[3]); /* A */ 686 } 687 break; 688 case PIPE_BLENDFACTOR_INV_CONST_COLOR: 689 /* fall-through */ 690 case PIPE_BLENDFACTOR_INV_CONST_ALPHA: 691 { 692 float inv_comp[4]; 693 VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]); 694 VEC4_MUL(blend_dest[3], blend_dest[3], inv_comp); 695 } 696 break; 697 default: 698 assert(0 && "invalid alpha dst factor"); 699 } 700 701 /* 702 * Combine RGB terms 703 */ 704 switch (softpipe->blend->rt[blend_index].rgb_func) { 705 case PIPE_BLEND_ADD: 706 VEC4_ADD(quadColor[0], source[0], blend_dest[0]); /* R */ 707 VEC4_ADD(quadColor[1], source[1], blend_dest[1]); /* G */ 708 VEC4_ADD(quadColor[2], source[2], blend_dest[2]); /* B */ 709 break; 710 case PIPE_BLEND_SUBTRACT: 711 VEC4_SUB(quadColor[0], source[0], blend_dest[0]); /* R */ 712 VEC4_SUB(quadColor[1], source[1], blend_dest[1]); /* G */ 713 VEC4_SUB(quadColor[2], source[2], blend_dest[2]); /* B */ 714 break; 715 case PIPE_BLEND_REVERSE_SUBTRACT: 716 VEC4_SUB(quadColor[0], blend_dest[0], source[0]); /* R */ 717 VEC4_SUB(quadColor[1], blend_dest[1], source[1]); /* G */ 718 VEC4_SUB(quadColor[2], blend_dest[2], source[2]); /* B */ 719 break; 720 case PIPE_BLEND_MIN: 721 VEC4_MIN(quadColor[0], source[0], blend_dest[0]); /* R */ 722 VEC4_MIN(quadColor[1], source[1], blend_dest[1]); /* G */ 723 VEC4_MIN(quadColor[2], source[2], blend_dest[2]); /* B */ 724 break; 725 case PIPE_BLEND_MAX: 726 VEC4_MAX(quadColor[0], source[0], blend_dest[0]); /* R */ 727 VEC4_MAX(quadColor[1], source[1], blend_dest[1]); /* G */ 728 VEC4_MAX(quadColor[2], source[2], blend_dest[2]); /* B */ 729 break; 730 default: 731 assert(0 && "invalid rgb blend func"); 732 } 733 734 /* 735 * Combine A terms 736 */ 737 switch (softpipe->blend->rt[blend_index].alpha_func) { 738 case PIPE_BLEND_ADD: 739 VEC4_ADD(quadColor[3], source[3], blend_dest[3]); /* A */ 740 break; 741 case PIPE_BLEND_SUBTRACT: 742 VEC4_SUB(quadColor[3], source[3], blend_dest[3]); /* A */ 743 break; 744 case PIPE_BLEND_REVERSE_SUBTRACT: 745 VEC4_SUB(quadColor[3], blend_dest[3], source[3]); /* A */ 746 break; 747 case PIPE_BLEND_MIN: 748 VEC4_MIN(quadColor[3], source[3], blend_dest[3]); /* A */ 749 break; 750 case PIPE_BLEND_MAX: 751 VEC4_MAX(quadColor[3], source[3], blend_dest[3]); /* A */ 752 break; 753 default: 754 assert(0 && "invalid alpha blend func"); 755 } 756} 757 758static void 759colormask_quad(unsigned colormask, 760 float (*quadColor)[4], 761 float (*dest)[4]) 762{ 763 /* R */ 764 if (!(colormask & PIPE_MASK_R)) 765 COPY_4V(quadColor[0], dest[0]); 766 767 /* G */ 768 if (!(colormask & PIPE_MASK_G)) 769 COPY_4V(quadColor[1], dest[1]); 770 771 /* B */ 772 if (!(colormask & PIPE_MASK_B)) 773 COPY_4V(quadColor[2], dest[2]); 774 775 /* A */ 776 if (!(colormask & PIPE_MASK_A)) 777 COPY_4V(quadColor[3], dest[3]); 778} 779 780 781/** 782 * Clamp all colors in a quad to [0, 1] 783 */ 784static void 785clamp_colors(float (*quadColor)[4]) 786{ 787 unsigned i, j; 788 789 for (j = 0; j < QUAD_SIZE; j++) { 790 for (i = 0; i < 4; i++) { 791 quadColor[i][j] = CLAMP(quadColor[i][j], 0.0F, 1.0F); 792 } 793 } 794} 795 796 797/** 798 * If we're drawing to a luminance, luminance/alpha or intensity surface 799 * we have to adjust (rebase) the fragment/quad colors before writing them 800 * to the tile cache. The tile cache always stores RGBA colors but if 801 * we're caching a L/A surface (for example) we need to be sure that R=G=B 802 * so that subsequent reads from the surface cache appear to return L/A 803 * values. 804 * The piglit fbo-blending-formats test will exercise this. 805 */ 806static void 807rebase_colors(enum format base_format, float (*quadColor)[4]) 808{ 809 unsigned i; 810 811 switch (base_format) { 812 case RGB: 813 for (i = 0; i < 4; i++) { 814 /* A = 1 */ 815 quadColor[3][i] = 1.0F; 816 } 817 break; 818 case LUMINANCE: 819 for (i = 0; i < 4; i++) { 820 /* B = G = R */ 821 quadColor[2][i] = quadColor[1][i] = quadColor[0][i]; 822 /* A = 1 */ 823 quadColor[3][i] = 1.0F; 824 } 825 break; 826 case LUMINANCE_ALPHA: 827 for (i = 0; i < 4; i++) { 828 /* B = G = R */ 829 quadColor[2][i] = quadColor[1][i] = quadColor[0][i]; 830 } 831 break; 832 case INTENSITY: 833 for (i = 0; i < 4; i++) { 834 /* A = B = G = R */ 835 quadColor[3][i] = quadColor[2][i] = quadColor[1][i] = quadColor[0][i]; 836 } 837 break; 838 default: 839 ; /* nothing */ 840 } 841} 842 843 844 845static void 846blend_fallback(struct quad_stage *qs, 847 struct quad_header *quads[], 848 unsigned nr) 849{ 850 const struct blend_quad_stage *bqs = blend_quad_stage(qs); 851 struct softpipe_context *softpipe = qs->softpipe; 852 const struct pipe_blend_state *blend = softpipe->blend; 853 unsigned cbuf; 854 boolean write_all; 855 856 write_all = softpipe->fs_variant->info.color0_writes_all_cbufs; 857 858 for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) 859 { 860 /* which blend/mask state index to use: */ 861 const uint blend_buf = blend->independent_blend_enable ? cbuf : 0; 862 float dest[4][QUAD_SIZE]; 863 struct softpipe_cached_tile *tile 864 = sp_get_cached_tile(softpipe->cbuf_cache[cbuf], 865 quads[0]->input.x0, 866 quads[0]->input.y0); 867 const boolean clamp = bqs->clamp[cbuf]; 868 const float *blend_color; 869 uint q, i, j; 870 871 if (clamp) 872 blend_color = softpipe->blend_color_clamped.color; 873 else 874 blend_color = softpipe->blend_color.color; 875 876 for (q = 0; q < nr; q++) { 877 struct quad_header *quad = quads[q]; 878 float (*quadColor)[4]; 879 float temp_quad_color[QUAD_SIZE][4]; 880 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 881 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 882 883 if (write_all) { 884 for (j = 0; j < QUAD_SIZE; j++) { 885 for (i = 0; i < 4; i++) { 886 temp_quad_color[i][j] = quad->output.color[0][i][j]; 887 } 888 } 889 quadColor = temp_quad_color; 890 } else { 891 quadColor = quad->output.color[cbuf]; 892 } 893 894 /* If fixed-point dest color buffer, need to clamp the incoming 895 * fragment colors now. 896 */ 897 if (clamp || softpipe->rasterizer->clamp_fragment_color) { 898 clamp_colors(quadColor); 899 } 900 901 /* get/swizzle dest colors 902 */ 903 for (j = 0; j < QUAD_SIZE; j++) { 904 int x = itx + (j & 1); 905 int y = ity + (j >> 1); 906 for (i = 0; i < 4; i++) { 907 dest[i][j] = tile->data.color[y][x][i]; 908 } 909 } 910 911 912 if (blend->logicop_enable) { 913 if (bqs->format_type[cbuf] != UTIL_FORMAT_TYPE_FLOAT) { 914 logicop_quad( qs, quadColor, dest ); 915 } 916 } 917 else if (blend->rt[blend_buf].blend_enable) { 918 blend_quad(qs, quadColor, dest, blend_color, blend_buf); 919 920 /* If fixed-point dest color buffer, need to clamp the outgoing 921 * fragment colors now. 922 */ 923 if (clamp) { 924 clamp_colors(quadColor); 925 } 926 } 927 928 rebase_colors(bqs->base_format[cbuf], quadColor); 929 930 if (blend->rt[blend_buf].colormask != 0xf) 931 colormask_quad( blend->rt[cbuf].colormask, quadColor, dest); 932 933 /* Output color values 934 */ 935 for (j = 0; j < QUAD_SIZE; j++) { 936 if (quad->inout.mask & (1 << j)) { 937 int x = itx + (j & 1); 938 int y = ity + (j >> 1); 939 for (i = 0; i < 4; i++) { /* loop over color chans */ 940 tile->data.color[y][x][i] = quadColor[i][j]; 941 } 942 } 943 } 944 } 945 } 946} 947 948 949static void 950blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs, 951 struct quad_header *quads[], 952 unsigned nr) 953{ 954 const struct blend_quad_stage *bqs = blend_quad_stage(qs); 955 static const float one[4] = { 1, 1, 1, 1 }; 956 float one_minus_alpha[QUAD_SIZE]; 957 float dest[4][QUAD_SIZE]; 958 float source[4][QUAD_SIZE]; 959 uint i, j, q; 960 961 struct softpipe_cached_tile *tile 962 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 963 quads[0]->input.x0, 964 quads[0]->input.y0); 965 966 for (q = 0; q < nr; q++) { 967 struct quad_header *quad = quads[q]; 968 float (*quadColor)[4] = quad->output.color[0]; 969 const float *alpha = quadColor[3]; 970 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 971 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 972 973 /* get/swizzle dest colors */ 974 for (j = 0; j < QUAD_SIZE; j++) { 975 int x = itx + (j & 1); 976 int y = ity + (j >> 1); 977 for (i = 0; i < 4; i++) { 978 dest[i][j] = tile->data.color[y][x][i]; 979 } 980 } 981 982 /* If fixed-point dest color buffer, need to clamp the incoming 983 * fragment colors now. 984 */ 985 if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) { 986 clamp_colors(quadColor); 987 } 988 989 VEC4_MUL(source[0], quadColor[0], alpha); /* R */ 990 VEC4_MUL(source[1], quadColor[1], alpha); /* G */ 991 VEC4_MUL(source[2], quadColor[2], alpha); /* B */ 992 VEC4_MUL(source[3], quadColor[3], alpha); /* A */ 993 994 VEC4_SUB(one_minus_alpha, one, alpha); 995 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */ 996 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */ 997 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */ 998 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */ 999 1000 VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */ 1001 VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */ 1002 VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */ 1003 VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */ 1004 1005 /* If fixed-point dest color buffer, need to clamp the outgoing 1006 * fragment colors now. 1007 */ 1008 if (bqs->clamp[0]) { 1009 clamp_colors(quadColor); 1010 } 1011 1012 rebase_colors(bqs->base_format[0], quadColor); 1013 1014 for (j = 0; j < QUAD_SIZE; j++) { 1015 if (quad->inout.mask & (1 << j)) { 1016 int x = itx + (j & 1); 1017 int y = ity + (j >> 1); 1018 for (i = 0; i < 4; i++) { /* loop over color chans */ 1019 tile->data.color[y][x][i] = quadColor[i][j]; 1020 } 1021 } 1022 } 1023 } 1024} 1025 1026static void 1027blend_single_add_one_one(struct quad_stage *qs, 1028 struct quad_header *quads[], 1029 unsigned nr) 1030{ 1031 const struct blend_quad_stage *bqs = blend_quad_stage(qs); 1032 float dest[4][QUAD_SIZE]; 1033 uint i, j, q; 1034 1035 struct softpipe_cached_tile *tile 1036 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 1037 quads[0]->input.x0, 1038 quads[0]->input.y0); 1039 1040 for (q = 0; q < nr; q++) { 1041 struct quad_header *quad = quads[q]; 1042 float (*quadColor)[4] = quad->output.color[0]; 1043 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 1044 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 1045 1046 /* get/swizzle dest colors */ 1047 for (j = 0; j < QUAD_SIZE; j++) { 1048 int x = itx + (j & 1); 1049 int y = ity + (j >> 1); 1050 for (i = 0; i < 4; i++) { 1051 dest[i][j] = tile->data.color[y][x][i]; 1052 } 1053 } 1054 1055 /* If fixed-point dest color buffer, need to clamp the incoming 1056 * fragment colors now. 1057 */ 1058 if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) { 1059 clamp_colors(quadColor); 1060 } 1061 1062 VEC4_ADD(quadColor[0], quadColor[0], dest[0]); /* R */ 1063 VEC4_ADD(quadColor[1], quadColor[1], dest[1]); /* G */ 1064 VEC4_ADD(quadColor[2], quadColor[2], dest[2]); /* B */ 1065 VEC4_ADD(quadColor[3], quadColor[3], dest[3]); /* A */ 1066 1067 /* If fixed-point dest color buffer, need to clamp the outgoing 1068 * fragment colors now. 1069 */ 1070 if (bqs->clamp[0]) { 1071 clamp_colors(quadColor); 1072 } 1073 1074 rebase_colors(bqs->base_format[0], quadColor); 1075 1076 for (j = 0; j < QUAD_SIZE; j++) { 1077 if (quad->inout.mask & (1 << j)) { 1078 int x = itx + (j & 1); 1079 int y = ity + (j >> 1); 1080 for (i = 0; i < 4; i++) { /* loop over color chans */ 1081 tile->data.color[y][x][i] = quadColor[i][j]; 1082 } 1083 } 1084 } 1085 } 1086} 1087 1088 1089/** 1090 * Just copy the quad color to the framebuffer tile (respecting the writemask), 1091 * for one color buffer. 1092 * Clamping will be done, if needed (depending on the color buffer's 1093 * datatype) when we write/pack the colors later. 1094 */ 1095static void 1096single_output_color(struct quad_stage *qs, 1097 struct quad_header *quads[], 1098 unsigned nr) 1099{ 1100 const struct blend_quad_stage *bqs = blend_quad_stage(qs); 1101 uint i, j, q; 1102 1103 struct softpipe_cached_tile *tile 1104 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0], 1105 quads[0]->input.x0, 1106 quads[0]->input.y0); 1107 1108 for (q = 0; q < nr; q++) { 1109 struct quad_header *quad = quads[q]; 1110 float (*quadColor)[4] = quad->output.color[0]; 1111 const int itx = (quad->input.x0 & (TILE_SIZE-1)); 1112 const int ity = (quad->input.y0 & (TILE_SIZE-1)); 1113 1114 if (qs->softpipe->rasterizer->clamp_fragment_color) 1115 clamp_colors(quadColor); 1116 1117 rebase_colors(bqs->base_format[0], quadColor); 1118 1119 for (j = 0; j < QUAD_SIZE; j++) { 1120 if (quad->inout.mask & (1 << j)) { 1121 int x = itx + (j & 1); 1122 int y = ity + (j >> 1); 1123 for (i = 0; i < 4; i++) { /* loop over color chans */ 1124 tile->data.color[y][x][i] = quadColor[i][j]; 1125 } 1126 } 1127 } 1128 } 1129} 1130 1131static void 1132blend_noop(struct quad_stage *qs, 1133 struct quad_header *quads[], 1134 unsigned nr) 1135{ 1136} 1137 1138 1139static void 1140choose_blend_quad(struct quad_stage *qs, 1141 struct quad_header *quads[], 1142 unsigned nr) 1143{ 1144 struct blend_quad_stage *bqs = blend_quad_stage(qs); 1145 struct softpipe_context *softpipe = qs->softpipe; 1146 const struct pipe_blend_state *blend = softpipe->blend; 1147 unsigned i; 1148 1149 qs->run = blend_fallback; 1150 1151 if (softpipe->framebuffer.nr_cbufs == 0) { 1152 qs->run = blend_noop; 1153 } 1154 else if (!softpipe->blend->logicop_enable && 1155 softpipe->blend->rt[0].colormask == 0xf && 1156 softpipe->framebuffer.nr_cbufs == 1) 1157 { 1158 if (!blend->rt[0].blend_enable) { 1159 qs->run = single_output_color; 1160 } 1161 else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor && 1162 blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor && 1163 blend->rt[0].rgb_func == blend->rt[0].alpha_func) 1164 { 1165 if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) { 1166 if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE && 1167 blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { 1168 qs->run = blend_single_add_one_one; 1169 } 1170 else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && 1171 blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) 1172 qs->run = blend_single_add_src_alpha_inv_src_alpha; 1173 1174 } 1175 } 1176 } 1177 1178 /* For each color buffer, determine if the buffer has destination alpha and 1179 * whether color clamping is needed. 1180 */ 1181 for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { 1182 const enum pipe_format format = softpipe->framebuffer.cbufs[i]->format; 1183 const struct util_format_description *desc = 1184 util_format_description(format); 1185 /* assuming all or no color channels are normalized: */ 1186 bqs->clamp[i] = desc->channel[0].normalized; 1187 bqs->format_type[i] = desc->channel[0].type; 1188 1189 if (util_format_is_intensity(format)) 1190 bqs->base_format[i] = INTENSITY; 1191 else if (util_format_is_luminance(format)) 1192 bqs->base_format[i] = LUMINANCE; 1193 else if (util_format_is_luminance_alpha(format)) 1194 bqs->base_format[i] = LUMINANCE_ALPHA; 1195 else if (util_format_is_rgb_no_alpha(format)) 1196 bqs->base_format[i] = RGB; 1197 else 1198 bqs->base_format[i] = RGBA; 1199 } 1200 1201 qs->run(qs, quads, nr); 1202} 1203 1204 1205static void blend_begin(struct quad_stage *qs) 1206{ 1207 qs->run = choose_blend_quad; 1208} 1209 1210 1211static void blend_destroy(struct quad_stage *qs) 1212{ 1213 FREE( qs ); 1214} 1215 1216 1217struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ) 1218{ 1219 struct blend_quad_stage *stage = CALLOC_STRUCT(blend_quad_stage); 1220 1221 if (!stage) 1222 return NULL; 1223 1224 stage->base.softpipe = softpipe; 1225 stage->base.begin = blend_begin; 1226 stage->base.run = choose_blend_quad; 1227 stage->base.destroy = blend_destroy; 1228 1229 return &stage->base; 1230} 1231