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_surface.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 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
];
235 * Compute src/first term RGB
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 */
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
->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
->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
:
481 assert(0); /* illegal */
483 case PIPE_BLENDFACTOR_CONST_COLOR
:
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 */
494 case PIPE_BLENDFACTOR_CONST_ALPHA
:
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 */
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 */
508 case PIPE_BLENDFACTOR_SRC1_COLOR
:
509 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
510 /* XXX what are these? */
513 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
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 */
524 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
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 */
533 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
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 */
542 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
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 */
553 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
557 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
558 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
560 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
561 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
563 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
564 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
567 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
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
);
576 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
577 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
578 /* XXX what are these? */
586 * Compute dest/second term A
588 switch (softpipe
->blend
->alpha_dst_factor
) {
589 case PIPE_BLENDFACTOR_ONE
:
590 /* dest = dest * 1 NO-OP, leave dest as-is */
592 case PIPE_BLENDFACTOR_SRC_COLOR
:
594 case PIPE_BLENDFACTOR_SRC_ALPHA
:
595 VEC4_MUL(dest
[3], dest
[3], quadColor
[3]); /* A * A */
597 case PIPE_BLENDFACTOR_DST_COLOR
:
599 case PIPE_BLENDFACTOR_DST_ALPHA
:
600 VEC4_MUL(dest
[3], dest
[3], dest
[3]); /* A */
602 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
603 assert(0); /* illegal */
605 case PIPE_BLENDFACTOR_CONST_COLOR
:
607 case PIPE_BLENDFACTOR_CONST_ALPHA
:
610 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
611 VEC4_MUL(dest
[3], dest
[3], comp
); /* A */
614 case PIPE_BLENDFACTOR_ZERO
:
615 VEC4_COPY(dest
[3], zero
); /* A */
617 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
619 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
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 */
626 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
628 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
631 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
632 VEC4_MUL(dest
[3], inv_comp
, dest
[3]); /* A */
635 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
637 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
640 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
641 VEC4_MUL(dest
[3], dest
[3], inv_comp
);
651 switch (softpipe
->blend
->rgb_func
) {
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 */
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 */
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 */
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 */
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 */
684 switch (softpipe
->blend
->alpha_func
) {
686 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
688 case PIPE_BLEND_SUBTRACT
:
689 VEC4_SUB_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
691 case PIPE_BLEND_REVERSE_SUBTRACT
:
692 VEC4_SUB_SAT(quadColor
[3], dest
[3], source
[3]); /* A */
695 VEC4_MIN(quadColor
[3], source
[3], dest
[3]); /* A */
698 VEC4_MAX(quadColor
[3], source
[3], dest
[3]); /* A */
706 colormask_quad(struct quad_stage
*qs
,
707 float (*quadColor
)[4],
710 struct softpipe_context
*softpipe
= qs
->softpipe
;
713 if (!(softpipe
->blend
->colormask
& PIPE_MASK_R
))
714 COPY_4V(quadColor
[0], dest
[0]);
717 if (!(softpipe
->blend
->colormask
& PIPE_MASK_G
))
718 COPY_4V(quadColor
[1], dest
[1]);
721 if (!(softpipe
->blend
->colormask
& PIPE_MASK_B
))
722 COPY_4V(quadColor
[2], dest
[2]);
725 if (!(softpipe
->blend
->colormask
& PIPE_MASK_A
))
726 COPY_4V(quadColor
[3], dest
[3]);
731 blend_fallback(struct quad_stage
*qs
,
732 struct quad_header
*quads
[],
735 struct softpipe_context
*softpipe
= qs
->softpipe
;
736 const struct pipe_blend_state
*blend
= softpipe
->blend
;
739 for (cbuf
= 0; cbuf
< softpipe
->framebuffer
.nr_cbufs
; cbuf
++)
741 float dest
[4][QUAD_SIZE
];
742 struct softpipe_cached_tile
*tile
743 = sp_get_cached_tile(softpipe
->cbuf_cache
[cbuf
],
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));
754 /* get/swizzle dest colors
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
];
765 if (blend
->logicop_enable
) {
766 logicop_quad( qs
, quadColor
, dest
);
768 else if (blend
->blend_enable
) {
769 blend_quad( qs
, quadColor
, dest
);
772 if (blend
->colormask
!= 0xf)
773 colormask_quad( qs
, quadColor
, dest
);
775 /* Output color values
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
];
792 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage
*qs
,
793 struct quad_header
*quads
[],
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
];
802 struct softpipe_cached_tile
*tile
803 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
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));
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
];
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 */
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 */
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 */
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
];
852 blend_single_add_one_one(struct quad_stage
*qs
,
853 struct quad_header
*quads
[],
856 float dest
[4][QUAD_SIZE
];
859 struct softpipe_cached_tile
*tile
860 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
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));
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_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 */
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
];
898 single_output_color(struct quad_stage
*qs
,
899 struct quad_header
*quads
[],
904 struct softpipe_cached_tile
*tile
905 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
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));
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
];
928 blend_noop(struct quad_stage
*qs
,
929 struct quad_header
*quads
[],
936 choose_blend_quad(struct quad_stage
*qs
,
937 struct quad_header
*quads
[],
940 struct softpipe_context
*softpipe
= qs
->softpipe
;
941 const struct pipe_blend_state
*blend
= softpipe
->blend
;
943 qs
->run
= blend_fallback
;
945 if (softpipe
->framebuffer
.nr_cbufs
== 0) {
946 qs
->run
= blend_noop
;
948 else if (!softpipe
->blend
->logicop_enable
&&
949 softpipe
->blend
->colormask
== 0xf &&
950 softpipe
->framebuffer
.nr_cbufs
== 1)
952 if (!blend
->blend_enable
) {
953 qs
->run
= single_output_color
;
955 else if (blend
->rgb_src_factor
== blend
->alpha_src_factor
&&
956 blend
->rgb_dst_factor
== blend
->alpha_dst_factor
&&
957 blend
->rgb_func
== blend
->alpha_func
)
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
;
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
;
972 qs
->run(qs
, quads
, nr
);
976 static void blend_begin(struct quad_stage
*qs
)
978 qs
->run
= choose_blend_quad
;
982 static void blend_destroy(struct quad_stage
*qs
)
988 struct quad_stage
*sp_quad_blend_stage( struct softpipe_context
*softpipe
)
990 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
992 stage
->softpipe
= softpipe
;
993 stage
->begin
= blend_begin
;
994 stage
->run
= choose_blend_quad
;
995 stage
->destroy
= blend_destroy
;