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 "util/u_format.h"
37 #include "sp_context.h"
39 #include "sp_tile_cache.h"
40 #include "sp_quad_pipe.h"
43 #define VEC4_COPY(DST, SRC) \
51 #define VEC4_SCALAR(DST, SRC) \
59 #define VEC4_ADD(R, A, B) \
67 #define VEC4_SUB(R, A, B) \
75 /** Add and limit result to ceiling of 1.0 */
76 #define VEC4_ADD_SAT(R, A, B) \
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; \
84 /** Subtract and limit result to floor of 0.0 */
85 #define VEC4_SUB_SAT(R, A, B) \
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; \
93 #define VEC4_MUL(R, A, B) \
101 #define VEC4_MIN(R, A, B) \
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]; \
109 #define VEC4_MAX(R, A, B) \
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]; \
120 logicop_quad(struct quad_stage
*qs
,
121 float (*quadColor
)[4],
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
;
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 */
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 */
145 switch (softpipe
->blend
->logicop_func
) {
146 case PIPE_LOGICOP_CLEAR
:
147 for (j
= 0; j
< 4; j
++)
150 case PIPE_LOGICOP_NOR
:
151 for (j
= 0; j
< 4; j
++)
152 res4
[j
] = ~(src4
[j
] | dst4
[j
]);
154 case PIPE_LOGICOP_AND_INVERTED
:
155 for (j
= 0; j
< 4; j
++)
156 res4
[j
] = ~src4
[j
] & dst4
[j
];
158 case PIPE_LOGICOP_COPY_INVERTED
:
159 for (j
= 0; j
< 4; j
++)
162 case PIPE_LOGICOP_AND_REVERSE
:
163 for (j
= 0; j
< 4; j
++)
164 res4
[j
] = src4
[j
] & ~dst4
[j
];
166 case PIPE_LOGICOP_INVERT
:
167 for (j
= 0; j
< 4; j
++)
170 case PIPE_LOGICOP_XOR
:
171 for (j
= 0; j
< 4; j
++)
172 res4
[j
] = dst4
[j
] ^ src4
[j
];
174 case PIPE_LOGICOP_NAND
:
175 for (j
= 0; j
< 4; j
++)
176 res4
[j
] = ~(src4
[j
] & dst4
[j
]);
178 case PIPE_LOGICOP_AND
:
179 for (j
= 0; j
< 4; j
++)
180 res4
[j
] = src4
[j
] & dst4
[j
];
182 case PIPE_LOGICOP_EQUIV
:
183 for (j
= 0; j
< 4; j
++)
184 res4
[j
] = ~(src4
[j
] ^ dst4
[j
]);
186 case PIPE_LOGICOP_NOOP
:
187 for (j
= 0; j
< 4; j
++)
190 case PIPE_LOGICOP_OR_INVERTED
:
191 for (j
= 0; j
< 4; j
++)
192 res4
[j
] = ~src4
[j
] | dst4
[j
];
194 case PIPE_LOGICOP_COPY
:
195 for (j
= 0; j
< 4; j
++)
198 case PIPE_LOGICOP_OR_REVERSE
:
199 for (j
= 0; j
< 4; j
++)
200 res4
[j
] = src4
[j
] | ~dst4
[j
];
202 case PIPE_LOGICOP_OR
:
203 for (j
= 0; j
< 4; j
++)
204 res4
[j
] = src4
[j
] | dst4
[j
];
206 case PIPE_LOGICOP_SET
:
207 for (j
= 0; j
< 4; j
++)
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]);
225 blend_quad(struct quad_stage
*qs
,
226 float (*quadColor
)[4],
229 boolean has_dst_alpha
)
231 static const float zero
[4] = { 0, 0, 0, 0 };
232 static const float one
[4] = { 1, 1, 1, 1 };
233 struct softpipe_context
*softpipe
= qs
->softpipe
;
234 float source
[4][QUAD_SIZE
] = { { 0 } };
237 * Compute src/first term RGB
239 switch (softpipe
->blend
->rt
[cbuf
].rgb_src_factor
) {
240 case PIPE_BLENDFACTOR_ONE
:
241 VEC4_COPY(source
[0], quadColor
[0]); /* R */
242 VEC4_COPY(source
[1], quadColor
[1]); /* G */
243 VEC4_COPY(source
[2], quadColor
[2]); /* B */
245 case PIPE_BLENDFACTOR_SRC_COLOR
:
246 VEC4_MUL(source
[0], quadColor
[0], quadColor
[0]); /* R */
247 VEC4_MUL(source
[1], quadColor
[1], quadColor
[1]); /* G */
248 VEC4_MUL(source
[2], quadColor
[2], quadColor
[2]); /* B */
250 case PIPE_BLENDFACTOR_SRC_ALPHA
:
252 const float *alpha
= quadColor
[3];
253 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
254 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
255 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
258 case PIPE_BLENDFACTOR_DST_COLOR
:
259 VEC4_MUL(source
[0], quadColor
[0], dest
[0]); /* R */
260 VEC4_MUL(source
[1], quadColor
[1], dest
[1]); /* G */
261 VEC4_MUL(source
[2], quadColor
[2], dest
[2]); /* B */
263 case PIPE_BLENDFACTOR_DST_ALPHA
:
265 const float *alpha
= dest
[3];
266 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
267 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
268 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
271 VEC4_COPY(source
[0], quadColor
[0]); /* R */
272 VEC4_COPY(source
[1], quadColor
[1]); /* G */
273 VEC4_COPY(source
[2], quadColor
[2]); /* B */
276 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
278 const float *alpha
= quadColor
[3];
279 float diff
[4], temp
[4];
280 VEC4_SUB(diff
, one
, dest
[3]);
281 VEC4_MIN(temp
, alpha
, diff
);
282 VEC4_MUL(source
[0], quadColor
[0], temp
); /* R */
283 VEC4_MUL(source
[1], quadColor
[1], temp
); /* G */
284 VEC4_MUL(source
[2], quadColor
[2], temp
); /* B */
287 VEC4_COPY(source
[0], zero
); /* R */
288 VEC4_COPY(source
[1], zero
); /* G */
289 VEC4_COPY(source
[2], zero
); /* B */
292 case PIPE_BLENDFACTOR_CONST_COLOR
:
295 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[0]); /* R */
296 VEC4_MUL(source
[0], quadColor
[0], comp
); /* R */
297 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[1]); /* G */
298 VEC4_MUL(source
[1], quadColor
[1], comp
); /* G */
299 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[2]); /* B */
300 VEC4_MUL(source
[2], quadColor
[2], comp
); /* B */
303 case PIPE_BLENDFACTOR_CONST_ALPHA
:
306 VEC4_SCALAR(alpha
, softpipe
->blend_color
.color
[3]);
307 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
308 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
309 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
312 case PIPE_BLENDFACTOR_SRC1_COLOR
:
313 assert(0); /* to do */
315 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
316 assert(0); /* to do */
318 case PIPE_BLENDFACTOR_ZERO
:
319 VEC4_COPY(source
[0], zero
); /* R */
320 VEC4_COPY(source
[1], zero
); /* G */
321 VEC4_COPY(source
[2], zero
); /* B */
323 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
326 VEC4_SUB(inv_comp
, one
, quadColor
[0]); /* R */
327 VEC4_MUL(source
[0], quadColor
[0], inv_comp
); /* R */
328 VEC4_SUB(inv_comp
, one
, quadColor
[1]); /* G */
329 VEC4_MUL(source
[1], quadColor
[1], inv_comp
); /* G */
330 VEC4_SUB(inv_comp
, one
, quadColor
[2]); /* B */
331 VEC4_MUL(source
[2], quadColor
[2], inv_comp
); /* B */
334 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
337 VEC4_SUB(inv_alpha
, one
, quadColor
[3]);
338 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
339 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
340 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
343 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
346 VEC4_SUB(inv_alpha
, one
, dest
[3]);
347 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
348 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
349 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
352 VEC4_COPY(source
[0], zero
); /* R */
353 VEC4_COPY(source
[1], zero
); /* G */
354 VEC4_COPY(source
[2], zero
); /* B */
357 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
360 VEC4_SUB(inv_comp
, one
, dest
[0]); /* R */
361 VEC4_MUL(source
[0], quadColor
[0], inv_comp
); /* R */
362 VEC4_SUB(inv_comp
, one
, dest
[1]); /* G */
363 VEC4_MUL(source
[1], quadColor
[1], inv_comp
); /* G */
364 VEC4_SUB(inv_comp
, one
, dest
[2]); /* B */
365 VEC4_MUL(source
[2], quadColor
[2], inv_comp
); /* B */
368 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
372 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
373 VEC4_MUL(source
[0], quadColor
[0], inv_comp
);
375 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
376 VEC4_MUL(source
[1], quadColor
[1], inv_comp
);
378 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
379 VEC4_MUL(source
[2], quadColor
[2], inv_comp
);
382 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
385 VEC4_SCALAR(inv_alpha
, 1.0f
- softpipe
->blend_color
.color
[3]);
386 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
387 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
388 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
391 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
392 assert(0); /* to do */
394 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
395 assert(0); /* to do */
402 * Compute src/first term A
404 switch (softpipe
->blend
->rt
[cbuf
].alpha_src_factor
) {
405 case PIPE_BLENDFACTOR_ONE
:
406 VEC4_COPY(source
[3], quadColor
[3]); /* A */
408 case PIPE_BLENDFACTOR_SRC_COLOR
:
410 case PIPE_BLENDFACTOR_SRC_ALPHA
:
412 const float *alpha
= quadColor
[3];
413 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
416 case PIPE_BLENDFACTOR_DST_COLOR
:
418 case PIPE_BLENDFACTOR_DST_ALPHA
:
420 VEC4_MUL(source
[3], quadColor
[3], dest
[3]); /* A */
422 VEC4_COPY(source
[3], quadColor
[3]); /* A */
424 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
425 /* multiply alpha by 1.0 */
426 VEC4_COPY(source
[3], quadColor
[3]); /* A */
428 case PIPE_BLENDFACTOR_CONST_COLOR
:
430 case PIPE_BLENDFACTOR_CONST_ALPHA
:
433 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
434 VEC4_MUL(source
[3], quadColor
[3], comp
); /* A */
437 case PIPE_BLENDFACTOR_ZERO
:
438 VEC4_COPY(source
[3], zero
); /* A */
440 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
442 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
445 VEC4_SUB(inv_alpha
, one
, quadColor
[3]);
446 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
449 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
451 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
454 VEC4_SUB(inv_alpha
, one
, dest
[3]);
455 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
458 VEC4_COPY(source
[3], zero
); /* A */
461 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
463 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
467 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
468 VEC4_MUL(source
[3], quadColor
[3], inv_comp
);
477 * Compute dest/second term RGB
479 switch (softpipe
->blend
->rt
[cbuf
].rgb_dst_factor
) {
480 case PIPE_BLENDFACTOR_ONE
:
481 /* dest = dest * 1 NO-OP, leave dest as-is */
483 case PIPE_BLENDFACTOR_SRC_COLOR
:
484 VEC4_MUL(dest
[0], dest
[0], quadColor
[0]); /* R */
485 VEC4_MUL(dest
[1], dest
[1], quadColor
[1]); /* G */
486 VEC4_MUL(dest
[2], dest
[2], quadColor
[2]); /* B */
488 case PIPE_BLENDFACTOR_SRC_ALPHA
:
489 VEC4_MUL(dest
[0], dest
[0], quadColor
[3]); /* R * A */
490 VEC4_MUL(dest
[1], dest
[1], quadColor
[3]); /* G * A */
491 VEC4_MUL(dest
[2], dest
[2], quadColor
[3]); /* B * A */
493 case PIPE_BLENDFACTOR_DST_ALPHA
:
495 VEC4_MUL(dest
[0], dest
[0], dest
[3]); /* R * A */
496 VEC4_MUL(dest
[1], dest
[1], dest
[3]); /* G * A */
497 VEC4_MUL(dest
[2], dest
[2], dest
[3]); /* B * A */
500 /* dest = dest * 1 NO-OP, leave dest as-is */
503 case PIPE_BLENDFACTOR_DST_COLOR
:
504 VEC4_MUL(dest
[0], dest
[0], dest
[0]); /* R */
505 VEC4_MUL(dest
[1], dest
[1], dest
[1]); /* G */
506 VEC4_MUL(dest
[2], dest
[2], dest
[2]); /* B */
508 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
510 const float *alpha
= quadColor
[3];
511 float diff
[4], temp
[4];
512 VEC4_SUB(diff
, one
, dest
[3]);
513 VEC4_MIN(temp
, alpha
, diff
);
514 VEC4_MUL(dest
[0], quadColor
[0], temp
); /* R */
515 VEC4_MUL(dest
[1], quadColor
[1], temp
); /* G */
516 VEC4_MUL(dest
[2], quadColor
[2], temp
); /* B */
519 VEC4_COPY(dest
[0], zero
); /* R */
520 VEC4_COPY(dest
[1], zero
); /* G */
521 VEC4_COPY(dest
[2], zero
); /* B */
524 case PIPE_BLENDFACTOR_CONST_COLOR
:
527 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[0]); /* R */
528 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
529 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[1]); /* G */
530 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
531 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[2]); /* B */
532 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
535 case PIPE_BLENDFACTOR_CONST_ALPHA
:
538 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
539 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
540 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
541 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
544 case PIPE_BLENDFACTOR_ZERO
:
545 VEC4_COPY(dest
[0], zero
); /* R */
546 VEC4_COPY(dest
[1], zero
); /* G */
547 VEC4_COPY(dest
[2], zero
); /* B */
549 case PIPE_BLENDFACTOR_SRC1_COLOR
:
550 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
551 /* XXX what are these? */
554 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
557 VEC4_SUB(inv_comp
, one
, quadColor
[0]); /* R */
558 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
559 VEC4_SUB(inv_comp
, one
, quadColor
[1]); /* G */
560 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
561 VEC4_SUB(inv_comp
, one
, quadColor
[2]); /* B */
562 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
565 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
567 float one_minus_alpha
[QUAD_SIZE
];
568 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
569 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
570 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
571 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
574 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
577 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
578 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
579 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
580 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
583 VEC4_COPY(dest
[0], zero
); /* R */
584 VEC4_COPY(dest
[1], zero
); /* G */
585 VEC4_COPY(dest
[2], zero
); /* B */
588 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
591 VEC4_SUB(inv_comp
, one
, dest
[0]); /* R */
592 VEC4_MUL(dest
[0], dest
[0], inv_comp
); /* R */
593 VEC4_SUB(inv_comp
, one
, dest
[1]); /* G */
594 VEC4_MUL(dest
[1], dest
[1], inv_comp
); /* G */
595 VEC4_SUB(inv_comp
, one
, dest
[2]); /* B */
596 VEC4_MUL(dest
[2], dest
[2], inv_comp
); /* B */
599 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
603 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
604 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
606 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
607 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
609 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
610 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
613 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
616 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
617 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
618 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
619 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
622 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
623 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
624 /* XXX what are these? */
632 * Compute dest/second term A
634 switch (softpipe
->blend
->rt
[cbuf
].alpha_dst_factor
) {
635 case PIPE_BLENDFACTOR_ONE
:
636 /* dest = dest * 1 NO-OP, leave dest as-is */
638 case PIPE_BLENDFACTOR_SRC_COLOR
:
640 case PIPE_BLENDFACTOR_SRC_ALPHA
:
641 VEC4_MUL(dest
[3], dest
[3], quadColor
[3]); /* A * A */
643 case PIPE_BLENDFACTOR_DST_COLOR
:
645 case PIPE_BLENDFACTOR_DST_ALPHA
:
647 VEC4_MUL(dest
[3], dest
[3], dest
[3]); /* A */
650 /* dest = dest * 1 NO-OP, leave dest as-is */
653 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
654 /* dest = dest * 1 NO-OP, leave dest as-is */
656 case PIPE_BLENDFACTOR_CONST_COLOR
:
658 case PIPE_BLENDFACTOR_CONST_ALPHA
:
661 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
662 VEC4_MUL(dest
[3], dest
[3], comp
); /* A */
665 case PIPE_BLENDFACTOR_ZERO
:
666 VEC4_COPY(dest
[3], zero
); /* A */
668 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
670 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
672 float one_minus_alpha
[QUAD_SIZE
];
673 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
674 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* A */
677 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
679 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
682 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
683 VEC4_MUL(dest
[3], inv_comp
, dest
[3]); /* A */
686 VEC4_COPY(dest
[3], zero
); /* A */
689 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
691 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
694 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
695 VEC4_MUL(dest
[3], dest
[3], inv_comp
);
705 switch (softpipe
->blend
->rt
[cbuf
].rgb_func
) {
707 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
708 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
709 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
711 case PIPE_BLEND_SUBTRACT
:
712 VEC4_SUB_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
713 VEC4_SUB_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
714 VEC4_SUB_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
716 case PIPE_BLEND_REVERSE_SUBTRACT
:
717 VEC4_SUB_SAT(quadColor
[0], dest
[0], source
[0]); /* R */
718 VEC4_SUB_SAT(quadColor
[1], dest
[1], source
[1]); /* G */
719 VEC4_SUB_SAT(quadColor
[2], dest
[2], source
[2]); /* B */
722 VEC4_MIN(quadColor
[0], source
[0], dest
[0]); /* R */
723 VEC4_MIN(quadColor
[1], source
[1], dest
[1]); /* G */
724 VEC4_MIN(quadColor
[2], source
[2], dest
[2]); /* B */
727 VEC4_MAX(quadColor
[0], source
[0], dest
[0]); /* R */
728 VEC4_MAX(quadColor
[1], source
[1], dest
[1]); /* G */
729 VEC4_MAX(quadColor
[2], source
[2], dest
[2]); /* B */
738 switch (softpipe
->blend
->rt
[cbuf
].alpha_func
) {
740 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
742 case PIPE_BLEND_SUBTRACT
:
743 VEC4_SUB_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
745 case PIPE_BLEND_REVERSE_SUBTRACT
:
746 VEC4_SUB_SAT(quadColor
[3], dest
[3], source
[3]); /* A */
749 VEC4_MIN(quadColor
[3], source
[3], dest
[3]); /* A */
752 VEC4_MAX(quadColor
[3], source
[3], dest
[3]); /* A */
760 colormask_quad(unsigned colormask
,
761 float (*quadColor
)[4],
765 if (!(colormask
& PIPE_MASK_R
))
766 COPY_4V(quadColor
[0], dest
[0]);
769 if (!(colormask
& PIPE_MASK_G
))
770 COPY_4V(quadColor
[1], dest
[1]);
773 if (!(colormask
& PIPE_MASK_B
))
774 COPY_4V(quadColor
[2], dest
[2]);
777 if (!(colormask
& PIPE_MASK_A
))
778 COPY_4V(quadColor
[3], dest
[3]);
783 blend_fallback(struct quad_stage
*qs
,
784 struct quad_header
*quads
[],
787 struct softpipe_context
*softpipe
= qs
->softpipe
;
788 const struct pipe_blend_state
*blend
= softpipe
->blend
;
791 for (cbuf
= 0; cbuf
< softpipe
->framebuffer
.nr_cbufs
; cbuf
++)
793 /* which blend/mask state index to use: */
794 const uint blend_buf
= blend
->independent_blend_enable
? cbuf
: 0;
795 float dest
[4][QUAD_SIZE
];
796 struct softpipe_cached_tile
*tile
797 = sp_get_cached_tile(softpipe
->cbuf_cache
[cbuf
],
800 boolean has_dst_alpha
801 = util_format_has_alpha(softpipe
->framebuffer
.cbufs
[cbuf
]->format
);
804 for (q
= 0; q
< nr
; q
++) {
805 struct quad_header
*quad
= quads
[q
];
806 float (*quadColor
)[4] = quad
->output
.color
[cbuf
];
807 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
808 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
810 /* get/swizzle dest colors
812 for (j
= 0; j
< QUAD_SIZE
; j
++) {
813 int x
= itx
+ (j
& 1);
814 int y
= ity
+ (j
>> 1);
815 for (i
= 0; i
< 4; i
++) {
816 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
821 if (blend
->logicop_enable
) {
822 logicop_quad( qs
, quadColor
, dest
);
824 else if (blend
->rt
[blend_buf
].blend_enable
) {
825 blend_quad( qs
, quadColor
, dest
, cbuf
, has_dst_alpha
);
828 if (blend
->rt
[blend_buf
].colormask
!= 0xf)
829 colormask_quad( blend
->rt
[cbuf
].colormask
, quadColor
, dest
);
831 /* Output color values
833 for (j
= 0; j
< QUAD_SIZE
; j
++) {
834 if (quad
->inout
.mask
& (1 << j
)) {
835 int x
= itx
+ (j
& 1);
836 int y
= ity
+ (j
>> 1);
837 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
838 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
848 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage
*qs
,
849 struct quad_header
*quads
[],
852 static const float one
[4] = { 1, 1, 1, 1 };
853 float one_minus_alpha
[QUAD_SIZE
];
854 float dest
[4][QUAD_SIZE
];
855 float source
[4][QUAD_SIZE
];
858 struct softpipe_cached_tile
*tile
859 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
863 for (q
= 0; q
< nr
; q
++) {
864 struct quad_header
*quad
= quads
[q
];
865 float (*quadColor
)[4] = quad
->output
.color
[0];
866 const float *alpha
= quadColor
[3];
867 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
868 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
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
];
879 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
880 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
881 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
882 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
884 VEC4_SUB(one_minus_alpha
, one
, alpha
);
885 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
886 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
887 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
888 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* B */
890 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
891 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
892 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
893 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
895 for (j
= 0; j
< QUAD_SIZE
; j
++) {
896 if (quad
->inout
.mask
& (1 << j
)) {
897 int x
= itx
+ (j
& 1);
898 int y
= ity
+ (j
>> 1);
899 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
900 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
908 blend_single_add_one_one(struct quad_stage
*qs
,
909 struct quad_header
*quads
[],
912 float dest
[4][QUAD_SIZE
];
915 struct softpipe_cached_tile
*tile
916 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
920 for (q
= 0; q
< nr
; q
++) {
921 struct quad_header
*quad
= quads
[q
];
922 float (*quadColor
)[4] = quad
->output
.color
[0];
923 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
924 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
926 /* get/swizzle dest colors */
927 for (j
= 0; j
< QUAD_SIZE
; j
++) {
928 int x
= itx
+ (j
& 1);
929 int y
= ity
+ (j
>> 1);
930 for (i
= 0; i
< 4; i
++) {
931 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
935 VEC4_ADD_SAT(quadColor
[0], quadColor
[0], dest
[0]); /* R */
936 VEC4_ADD_SAT(quadColor
[1], quadColor
[1], dest
[1]); /* G */
937 VEC4_ADD_SAT(quadColor
[2], quadColor
[2], dest
[2]); /* B */
938 VEC4_ADD_SAT(quadColor
[3], quadColor
[3], dest
[3]); /* A */
940 for (j
= 0; j
< QUAD_SIZE
; j
++) {
941 if (quad
->inout
.mask
& (1 << j
)) {
942 int x
= itx
+ (j
& 1);
943 int y
= ity
+ (j
>> 1);
944 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
945 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
954 single_output_color(struct quad_stage
*qs
,
955 struct quad_header
*quads
[],
960 struct softpipe_cached_tile
*tile
961 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
965 for (q
= 0; q
< nr
; q
++) {
966 struct quad_header
*quad
= quads
[q
];
967 float (*quadColor
)[4] = quad
->output
.color
[0];
968 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
969 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
971 for (j
= 0; j
< QUAD_SIZE
; j
++) {
972 if (quad
->inout
.mask
& (1 << j
)) {
973 int x
= itx
+ (j
& 1);
974 int y
= ity
+ (j
>> 1);
975 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
976 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
984 blend_noop(struct quad_stage
*qs
,
985 struct quad_header
*quads
[],
992 choose_blend_quad(struct quad_stage
*qs
,
993 struct quad_header
*quads
[],
996 struct softpipe_context
*softpipe
= qs
->softpipe
;
997 const struct pipe_blend_state
*blend
= softpipe
->blend
;
999 qs
->run
= blend_fallback
;
1001 if (softpipe
->framebuffer
.nr_cbufs
== 0) {
1002 qs
->run
= blend_noop
;
1004 else if (!softpipe
->blend
->logicop_enable
&&
1005 softpipe
->blend
->rt
[0].colormask
== 0xf &&
1006 softpipe
->framebuffer
.nr_cbufs
== 1)
1008 if (!blend
->rt
[0].blend_enable
) {
1009 qs
->run
= single_output_color
;
1011 else if (blend
->rt
[0].rgb_src_factor
== blend
->rt
[0].alpha_src_factor
&&
1012 blend
->rt
[0].rgb_dst_factor
== blend
->rt
[0].alpha_dst_factor
&&
1013 blend
->rt
[0].rgb_func
== blend
->rt
[0].alpha_func
)
1015 if (blend
->rt
[0].alpha_func
== PIPE_BLEND_ADD
) {
1016 if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_ONE
&&
1017 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_ONE
) {
1018 qs
->run
= blend_single_add_one_one
;
1020 else if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_SRC_ALPHA
&&
1021 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_INV_SRC_ALPHA
)
1022 qs
->run
= blend_single_add_src_alpha_inv_src_alpha
;
1028 qs
->run(qs
, quads
, nr
);
1032 static void blend_begin(struct quad_stage
*qs
)
1034 qs
->run
= choose_blend_quad
;
1038 static void blend_destroy(struct quad_stage
*qs
)
1044 struct quad_stage
*sp_quad_blend_stage( struct softpipe_context
*softpipe
)
1046 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
1048 stage
->softpipe
= softpipe
;
1049 stage
->begin
= blend_begin
;
1050 stage
->run
= choose_blend_quad
;
1051 stage
->destroy
= blend_destroy
;