1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
33 #include "pipe/p_defines.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
36 #include "sp_context.h"
38 #include "sp_tile_cache.h"
39 #include "sp_quad_pipe.h"
42 #define VEC4_COPY(DST, SRC) \
50 #define VEC4_SCALAR(DST, SRC) \
58 #define VEC4_ADD(R, A, B) \
66 #define VEC4_SUB(R, A, B) \
74 /** Add and limit result to ceiling of 1.0 */
75 #define VEC4_ADD_SAT(R, A, B) \
77 R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
78 R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
79 R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
80 R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
83 /** Subtract and limit result to floor of 0.0 */
84 #define VEC4_SUB_SAT(R, A, B) \
86 R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
87 R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
88 R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
89 R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
92 #define VEC4_MUL(R, A, B) \
100 #define VEC4_MIN(R, A, B) \
102 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
103 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
104 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
105 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
108 #define VEC4_MAX(R, A, B) \
110 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
111 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
112 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
113 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
119 logicop_quad(struct quad_stage
*qs
,
120 float (*quadColor
)[4],
123 struct softpipe_context
*softpipe
= qs
->softpipe
;
124 ubyte src
[4][4], dst
[4][4], res
[4][4];
125 uint
*src4
= (uint
*) src
;
126 uint
*dst4
= (uint
*) dst
;
127 uint
*res4
= (uint
*) res
;
131 /* convert to ubyte */
132 for (j
= 0; j
< 4; j
++) { /* loop over R,G,B,A channels */
133 dst
[j
][0] = float_to_ubyte(dest
[j
][0]); /* P0 */
134 dst
[j
][1] = float_to_ubyte(dest
[j
][1]); /* P1 */
135 dst
[j
][2] = float_to_ubyte(dest
[j
][2]); /* P2 */
136 dst
[j
][3] = float_to_ubyte(dest
[j
][3]); /* P3 */
138 src
[j
][0] = float_to_ubyte(quadColor
[j
][0]); /* P0 */
139 src
[j
][1] = float_to_ubyte(quadColor
[j
][1]); /* P1 */
140 src
[j
][2] = float_to_ubyte(quadColor
[j
][2]); /* P2 */
141 src
[j
][3] = float_to_ubyte(quadColor
[j
][3]); /* P3 */
144 switch (softpipe
->blend
->logicop_func
) {
145 case PIPE_LOGICOP_CLEAR
:
146 for (j
= 0; j
< 4; j
++)
149 case PIPE_LOGICOP_NOR
:
150 for (j
= 0; j
< 4; j
++)
151 res4
[j
] = ~(src4
[j
] | dst4
[j
]);
153 case PIPE_LOGICOP_AND_INVERTED
:
154 for (j
= 0; j
< 4; j
++)
155 res4
[j
] = ~src4
[j
] & dst4
[j
];
157 case PIPE_LOGICOP_COPY_INVERTED
:
158 for (j
= 0; j
< 4; j
++)
161 case PIPE_LOGICOP_AND_REVERSE
:
162 for (j
= 0; j
< 4; j
++)
163 res4
[j
] = src4
[j
] & ~dst4
[j
];
165 case PIPE_LOGICOP_INVERT
:
166 for (j
= 0; j
< 4; j
++)
169 case PIPE_LOGICOP_XOR
:
170 for (j
= 0; j
< 4; j
++)
171 res4
[j
] = dst4
[j
] ^ src4
[j
];
173 case PIPE_LOGICOP_NAND
:
174 for (j
= 0; j
< 4; j
++)
175 res4
[j
] = ~(src4
[j
] & dst4
[j
]);
177 case PIPE_LOGICOP_AND
:
178 for (j
= 0; j
< 4; j
++)
179 res4
[j
] = src4
[j
] & dst4
[j
];
181 case PIPE_LOGICOP_EQUIV
:
182 for (j
= 0; j
< 4; j
++)
183 res4
[j
] = ~(src4
[j
] ^ dst4
[j
]);
185 case PIPE_LOGICOP_NOOP
:
186 for (j
= 0; j
< 4; j
++)
189 case PIPE_LOGICOP_OR_INVERTED
:
190 for (j
= 0; j
< 4; j
++)
191 res4
[j
] = ~src4
[j
] | dst4
[j
];
193 case PIPE_LOGICOP_COPY
:
194 for (j
= 0; j
< 4; j
++)
197 case PIPE_LOGICOP_OR_REVERSE
:
198 for (j
= 0; j
< 4; j
++)
199 res4
[j
] = src4
[j
] | ~dst4
[j
];
201 case PIPE_LOGICOP_OR
:
202 for (j
= 0; j
< 4; j
++)
203 res4
[j
] = src4
[j
] | dst4
[j
];
205 case PIPE_LOGICOP_SET
:
206 for (j
= 0; j
< 4; j
++)
213 for (j
= 0; j
< 4; j
++) {
214 quadColor
[j
][0] = ubyte_to_float(res
[j
][0]);
215 quadColor
[j
][1] = ubyte_to_float(res
[j
][1]);
216 quadColor
[j
][2] = ubyte_to_float(res
[j
][2]);
217 quadColor
[j
][3] = ubyte_to_float(res
[j
][3]);
224 blend_quad(struct quad_stage
*qs
,
225 float (*quadColor
)[4],
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
] = { { 0 } };
235 * Compute src/first term RGB
237 switch (softpipe
->blend
->rt
[cbuf
].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 */
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 */
248 case PIPE_BLENDFACTOR_SRC_ALPHA
:
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 */
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 */
261 case PIPE_BLENDFACTOR_DST_ALPHA
:
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 */
269 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
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 */
280 case PIPE_BLENDFACTOR_CONST_COLOR
:
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 */
291 case PIPE_BLENDFACTOR_CONST_ALPHA
:
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 */
300 case PIPE_BLENDFACTOR_SRC1_COLOR
:
301 assert(0); /* to do */
303 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
304 assert(0); /* to do */
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 */
311 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
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 */
322 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
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 */
331 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
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 */
340 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
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 */
351 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
355 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
356 VEC4_MUL(source
[0], quadColor
[0], inv_comp
);
358 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
359 VEC4_MUL(source
[1], quadColor
[1], inv_comp
);
361 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
362 VEC4_MUL(source
[2], quadColor
[2], inv_comp
);
365 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
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 */
374 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
375 assert(0); /* to do */
377 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
378 assert(0); /* to do */
385 * Compute src/first term A
387 switch (softpipe
->blend
->rt
[cbuf
].alpha_src_factor
) {
388 case PIPE_BLENDFACTOR_ONE
:
389 VEC4_COPY(source
[3], quadColor
[3]); /* A */
391 case PIPE_BLENDFACTOR_SRC_COLOR
:
393 case PIPE_BLENDFACTOR_SRC_ALPHA
:
395 const float *alpha
= quadColor
[3];
396 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
399 case PIPE_BLENDFACTOR_DST_COLOR
:
401 case PIPE_BLENDFACTOR_DST_ALPHA
:
402 VEC4_MUL(source
[3], quadColor
[3], dest
[3]); /* A */
404 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
405 /* multiply alpha by 1.0 */
406 VEC4_COPY(source
[3], quadColor
[3]); /* A */
408 case PIPE_BLENDFACTOR_CONST_COLOR
:
410 case PIPE_BLENDFACTOR_CONST_ALPHA
:
413 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
414 VEC4_MUL(source
[3], quadColor
[3], comp
); /* A */
417 case PIPE_BLENDFACTOR_ZERO
:
418 VEC4_COPY(source
[3], zero
); /* A */
420 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
422 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
425 VEC4_SUB(inv_alpha
, one
, quadColor
[3]);
426 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
429 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
431 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
434 VEC4_SUB(inv_alpha
, one
, dest
[3]);
435 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
438 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
440 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
444 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
445 VEC4_MUL(source
[3], quadColor
[3], inv_comp
);
454 * Compute dest/second term RGB
456 switch (softpipe
->blend
->rt
[cbuf
].rgb_dst_factor
) {
457 case PIPE_BLENDFACTOR_ONE
:
458 /* dest = dest * 1 NO-OP, leave dest as-is */
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 */
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 */
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 */
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 */
480 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
482 const float *alpha
= quadColor
[3];
483 float diff
[4], temp
[4];
484 VEC4_SUB(diff
, one
, dest
[3]);
485 VEC4_MIN(temp
, alpha
, diff
);
486 VEC4_MUL(dest
[0], quadColor
[0], temp
); /* R */
487 VEC4_MUL(dest
[1], quadColor
[1], temp
); /* G */
488 VEC4_MUL(dest
[2], quadColor
[2], temp
); /* B */
491 case PIPE_BLENDFACTOR_CONST_COLOR
:
494 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[0]); /* R */
495 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
496 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[1]); /* G */
497 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
498 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[2]); /* B */
499 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
502 case PIPE_BLENDFACTOR_CONST_ALPHA
:
505 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
506 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
507 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
508 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
511 case PIPE_BLENDFACTOR_ZERO
:
512 VEC4_COPY(dest
[0], zero
); /* R */
513 VEC4_COPY(dest
[1], zero
); /* G */
514 VEC4_COPY(dest
[2], zero
); /* B */
516 case PIPE_BLENDFACTOR_SRC1_COLOR
:
517 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
518 /* XXX what are these? */
521 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
524 VEC4_SUB(inv_comp
, one
, quadColor
[0]); /* R */
525 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
526 VEC4_SUB(inv_comp
, one
, quadColor
[1]); /* G */
527 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
528 VEC4_SUB(inv_comp
, one
, quadColor
[2]); /* B */
529 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
532 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
534 float one_minus_alpha
[QUAD_SIZE
];
535 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
536 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
537 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
538 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
541 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
544 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
545 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
546 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
547 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
550 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
553 VEC4_SUB(inv_comp
, one
, dest
[0]); /* R */
554 VEC4_MUL(dest
[0], dest
[0], inv_comp
); /* R */
555 VEC4_SUB(inv_comp
, one
, dest
[1]); /* G */
556 VEC4_MUL(dest
[1], dest
[1], inv_comp
); /* G */
557 VEC4_SUB(inv_comp
, one
, dest
[2]); /* B */
558 VEC4_MUL(dest
[2], dest
[2], inv_comp
); /* B */
561 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
565 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
566 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
568 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
569 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
571 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
572 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
575 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
578 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
579 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
580 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
581 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
584 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
585 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
586 /* XXX what are these? */
594 * Compute dest/second term A
596 switch (softpipe
->blend
->rt
[cbuf
].alpha_dst_factor
) {
597 case PIPE_BLENDFACTOR_ONE
:
598 /* dest = dest * 1 NO-OP, leave dest as-is */
600 case PIPE_BLENDFACTOR_SRC_COLOR
:
602 case PIPE_BLENDFACTOR_SRC_ALPHA
:
603 VEC4_MUL(dest
[3], dest
[3], quadColor
[3]); /* A * A */
605 case PIPE_BLENDFACTOR_DST_COLOR
:
607 case PIPE_BLENDFACTOR_DST_ALPHA
:
608 VEC4_MUL(dest
[3], dest
[3], dest
[3]); /* A */
610 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
611 /* dest = dest * 1 NO-OP, leave dest as-is */
613 case PIPE_BLENDFACTOR_CONST_COLOR
:
615 case PIPE_BLENDFACTOR_CONST_ALPHA
:
618 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
619 VEC4_MUL(dest
[3], dest
[3], comp
); /* A */
622 case PIPE_BLENDFACTOR_ZERO
:
623 VEC4_COPY(dest
[3], zero
); /* A */
625 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
627 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
629 float one_minus_alpha
[QUAD_SIZE
];
630 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
631 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* A */
634 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
636 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
639 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
640 VEC4_MUL(dest
[3], inv_comp
, dest
[3]); /* A */
643 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
645 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
648 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
649 VEC4_MUL(dest
[3], dest
[3], inv_comp
);
659 switch (softpipe
->blend
->rt
[cbuf
].rgb_func
) {
661 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
662 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
663 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
665 case PIPE_BLEND_SUBTRACT
:
666 VEC4_SUB_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
667 VEC4_SUB_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
668 VEC4_SUB_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
670 case PIPE_BLEND_REVERSE_SUBTRACT
:
671 VEC4_SUB_SAT(quadColor
[0], dest
[0], source
[0]); /* R */
672 VEC4_SUB_SAT(quadColor
[1], dest
[1], source
[1]); /* G */
673 VEC4_SUB_SAT(quadColor
[2], dest
[2], source
[2]); /* B */
676 VEC4_MIN(quadColor
[0], source
[0], dest
[0]); /* R */
677 VEC4_MIN(quadColor
[1], source
[1], dest
[1]); /* G */
678 VEC4_MIN(quadColor
[2], source
[2], dest
[2]); /* B */
681 VEC4_MAX(quadColor
[0], source
[0], dest
[0]); /* R */
682 VEC4_MAX(quadColor
[1], source
[1], dest
[1]); /* G */
683 VEC4_MAX(quadColor
[2], source
[2], dest
[2]); /* B */
692 switch (softpipe
->blend
->rt
[cbuf
].alpha_func
) {
694 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
696 case PIPE_BLEND_SUBTRACT
:
697 VEC4_SUB_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
699 case PIPE_BLEND_REVERSE_SUBTRACT
:
700 VEC4_SUB_SAT(quadColor
[3], dest
[3], source
[3]); /* A */
703 VEC4_MIN(quadColor
[3], source
[3], dest
[3]); /* A */
706 VEC4_MAX(quadColor
[3], source
[3], dest
[3]); /* A */
714 colormask_quad(unsigned colormask
,
715 float (*quadColor
)[4],
719 if (!(colormask
& PIPE_MASK_R
))
720 COPY_4V(quadColor
[0], dest
[0]);
723 if (!(colormask
& PIPE_MASK_G
))
724 COPY_4V(quadColor
[1], dest
[1]);
727 if (!(colormask
& PIPE_MASK_B
))
728 COPY_4V(quadColor
[2], dest
[2]);
731 if (!(colormask
& PIPE_MASK_A
))
732 COPY_4V(quadColor
[3], dest
[3]);
737 blend_fallback(struct quad_stage
*qs
,
738 struct quad_header
*quads
[],
741 struct softpipe_context
*softpipe
= qs
->softpipe
;
742 const struct pipe_blend_state
*blend
= softpipe
->blend
;
745 for (cbuf
= 0; cbuf
< softpipe
->framebuffer
.nr_cbufs
; cbuf
++)
747 float dest
[4][QUAD_SIZE
];
748 struct softpipe_cached_tile
*tile
749 = sp_get_cached_tile(softpipe
->cbuf_cache
[cbuf
],
754 for (q
= 0; q
< nr
; q
++) {
755 struct quad_header
*quad
= quads
[q
];
756 float (*quadColor
)[4] = quad
->output
.color
[cbuf
];
757 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
758 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
760 /* get/swizzle dest colors
762 for (j
= 0; j
< QUAD_SIZE
; j
++) {
763 int x
= itx
+ (j
& 1);
764 int y
= ity
+ (j
>> 1);
765 for (i
= 0; i
< 4; i
++) {
766 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
771 if (blend
->logicop_enable
) {
772 logicop_quad( qs
, quadColor
, dest
);
774 else if (blend
->rt
[cbuf
].blend_enable
) {
775 blend_quad( qs
, quadColor
, dest
, cbuf
);
778 if (blend
->rt
[cbuf
].colormask
!= 0xf)
779 colormask_quad( blend
->rt
[cbuf
].colormask
, quadColor
, dest
);
781 /* Output color values
783 for (j
= 0; j
< QUAD_SIZE
; j
++) {
784 if (quad
->inout
.mask
& (1 << j
)) {
785 int x
= itx
+ (j
& 1);
786 int y
= ity
+ (j
>> 1);
787 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
788 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
798 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage
*qs
,
799 struct quad_header
*quads
[],
802 static const float one
[4] = { 1, 1, 1, 1 };
803 float one_minus_alpha
[QUAD_SIZE
];
804 float dest
[4][QUAD_SIZE
];
805 float source
[4][QUAD_SIZE
];
808 struct softpipe_cached_tile
*tile
809 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
813 for (q
= 0; q
< nr
; q
++) {
814 struct quad_header
*quad
= quads
[q
];
815 float (*quadColor
)[4] = quad
->output
.color
[0];
816 const float *alpha
= quadColor
[3];
817 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
818 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
820 /* get/swizzle dest colors */
821 for (j
= 0; j
< QUAD_SIZE
; j
++) {
822 int x
= itx
+ (j
& 1);
823 int y
= ity
+ (j
>> 1);
824 for (i
= 0; i
< 4; i
++) {
825 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
829 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
830 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
831 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
832 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
834 VEC4_SUB(one_minus_alpha
, one
, alpha
);
835 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
836 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
837 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
838 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* B */
840 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
841 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
842 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
843 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
845 for (j
= 0; j
< QUAD_SIZE
; j
++) {
846 if (quad
->inout
.mask
& (1 << j
)) {
847 int x
= itx
+ (j
& 1);
848 int y
= ity
+ (j
>> 1);
849 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
850 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
858 blend_single_add_one_one(struct quad_stage
*qs
,
859 struct quad_header
*quads
[],
862 float dest
[4][QUAD_SIZE
];
865 struct softpipe_cached_tile
*tile
866 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
870 for (q
= 0; q
< nr
; q
++) {
871 struct quad_header
*quad
= quads
[q
];
872 float (*quadColor
)[4] = quad
->output
.color
[0];
873 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
874 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
876 /* get/swizzle dest colors */
877 for (j
= 0; j
< QUAD_SIZE
; j
++) {
878 int x
= itx
+ (j
& 1);
879 int y
= ity
+ (j
>> 1);
880 for (i
= 0; i
< 4; i
++) {
881 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
885 VEC4_ADD_SAT(quadColor
[0], quadColor
[0], dest
[0]); /* R */
886 VEC4_ADD_SAT(quadColor
[1], quadColor
[1], dest
[1]); /* G */
887 VEC4_ADD_SAT(quadColor
[2], quadColor
[2], dest
[2]); /* B */
888 VEC4_ADD_SAT(quadColor
[3], quadColor
[3], dest
[3]); /* A */
890 for (j
= 0; j
< QUAD_SIZE
; j
++) {
891 if (quad
->inout
.mask
& (1 << j
)) {
892 int x
= itx
+ (j
& 1);
893 int y
= ity
+ (j
>> 1);
894 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
895 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
904 single_output_color(struct quad_stage
*qs
,
905 struct quad_header
*quads
[],
910 struct softpipe_cached_tile
*tile
911 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
915 for (q
= 0; q
< nr
; q
++) {
916 struct quad_header
*quad
= quads
[q
];
917 float (*quadColor
)[4] = quad
->output
.color
[0];
918 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
919 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
921 for (j
= 0; j
< QUAD_SIZE
; j
++) {
922 if (quad
->inout
.mask
& (1 << j
)) {
923 int x
= itx
+ (j
& 1);
924 int y
= ity
+ (j
>> 1);
925 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
926 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
934 blend_noop(struct quad_stage
*qs
,
935 struct quad_header
*quads
[],
942 choose_blend_quad(struct quad_stage
*qs
,
943 struct quad_header
*quads
[],
946 struct softpipe_context
*softpipe
= qs
->softpipe
;
947 const struct pipe_blend_state
*blend
= softpipe
->blend
;
949 qs
->run
= blend_fallback
;
951 if (softpipe
->framebuffer
.nr_cbufs
== 0) {
952 qs
->run
= blend_noop
;
954 else if (!softpipe
->blend
->logicop_enable
&&
955 softpipe
->blend
->rt
[0].colormask
== 0xf &&
956 softpipe
->framebuffer
.nr_cbufs
== 1)
958 if (!blend
->rt
[0].blend_enable
) {
959 qs
->run
= single_output_color
;
961 else if (blend
->rt
[0].rgb_src_factor
== blend
->rt
[0].alpha_src_factor
&&
962 blend
->rt
[0].rgb_dst_factor
== blend
->rt
[0].alpha_dst_factor
&&
963 blend
->rt
[0].rgb_func
== blend
->rt
[0].alpha_func
)
965 if (blend
->rt
[0].alpha_func
== PIPE_BLEND_ADD
) {
966 if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_ONE
&&
967 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_ONE
) {
968 qs
->run
= blend_single_add_one_one
;
970 else if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_SRC_ALPHA
&&
971 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_INV_SRC_ALPHA
)
972 qs
->run
= blend_single_add_src_alpha_inv_src_alpha
;
978 qs
->run(qs
, quads
, nr
);
982 static void blend_begin(struct quad_stage
*qs
)
984 qs
->run
= choose_blend_quad
;
988 static void blend_destroy(struct quad_stage
*qs
)
994 struct quad_stage
*sp_quad_blend_stage( struct softpipe_context
*softpipe
)
996 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
998 stage
->softpipe
= softpipe
;
999 stage
->begin
= blend_begin
;
1000 stage
->run
= choose_blend_quad
;
1001 stage
->destroy
= blend_destroy
;