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"
40 #include "sp_tile_cache.h"
41 #include "sp_quad_pipe.h"
44 #define VEC4_COPY(DST, SRC) \
52 #define VEC4_SCALAR(DST, SRC) \
60 #define VEC4_ADD(R, A, B) \
68 #define VEC4_SUB(R, A, B) \
76 /** Add and limit result to ceiling of 1.0 */
77 #define VEC4_ADD_SAT(R, A, B) \
79 R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
80 R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
81 R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
82 R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
85 /** Subtract and limit result to floor of 0.0 */
86 #define VEC4_SUB_SAT(R, A, B) \
88 R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
89 R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
90 R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
91 R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
94 #define VEC4_MUL(R, A, B) \
102 #define VEC4_MIN(R, A, B) \
104 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
105 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
106 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
107 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
110 #define VEC4_MAX(R, A, B) \
112 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
113 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
114 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
115 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
121 logicop_quad(struct quad_stage
*qs
,
122 float (*quadColor
)[4],
125 struct softpipe_context
*softpipe
= qs
->softpipe
;
126 ubyte src
[4][4], dst
[4][4], res
[4][4];
127 uint
*src4
= (uint
*) src
;
128 uint
*dst4
= (uint
*) dst
;
129 uint
*res4
= (uint
*) res
;
133 /* convert to ubyte */
134 for (j
= 0; j
< 4; j
++) { /* loop over R,G,B,A channels */
135 dst
[j
][0] = float_to_ubyte(dest
[j
][0]); /* P0 */
136 dst
[j
][1] = float_to_ubyte(dest
[j
][1]); /* P1 */
137 dst
[j
][2] = float_to_ubyte(dest
[j
][2]); /* P2 */
138 dst
[j
][3] = float_to_ubyte(dest
[j
][3]); /* P3 */
140 src
[j
][0] = float_to_ubyte(quadColor
[j
][0]); /* P0 */
141 src
[j
][1] = float_to_ubyte(quadColor
[j
][1]); /* P1 */
142 src
[j
][2] = float_to_ubyte(quadColor
[j
][2]); /* P2 */
143 src
[j
][3] = float_to_ubyte(quadColor
[j
][3]); /* P3 */
146 switch (softpipe
->blend
->logicop_func
) {
147 case PIPE_LOGICOP_CLEAR
:
148 for (j
= 0; j
< 4; j
++)
151 case PIPE_LOGICOP_NOR
:
152 for (j
= 0; j
< 4; j
++)
153 res4
[j
] = ~(src4
[j
] | dst4
[j
]);
155 case PIPE_LOGICOP_AND_INVERTED
:
156 for (j
= 0; j
< 4; j
++)
157 res4
[j
] = ~src4
[j
] & dst4
[j
];
159 case PIPE_LOGICOP_COPY_INVERTED
:
160 for (j
= 0; j
< 4; j
++)
163 case PIPE_LOGICOP_AND_REVERSE
:
164 for (j
= 0; j
< 4; j
++)
165 res4
[j
] = src4
[j
] & ~dst4
[j
];
167 case PIPE_LOGICOP_INVERT
:
168 for (j
= 0; j
< 4; j
++)
171 case PIPE_LOGICOP_XOR
:
172 for (j
= 0; j
< 4; j
++)
173 res4
[j
] = dst4
[j
] ^ src4
[j
];
175 case PIPE_LOGICOP_NAND
:
176 for (j
= 0; j
< 4; j
++)
177 res4
[j
] = ~(src4
[j
] & dst4
[j
]);
179 case PIPE_LOGICOP_AND
:
180 for (j
= 0; j
< 4; j
++)
181 res4
[j
] = src4
[j
] & dst4
[j
];
183 case PIPE_LOGICOP_EQUIV
:
184 for (j
= 0; j
< 4; j
++)
185 res4
[j
] = ~(src4
[j
] ^ dst4
[j
]);
187 case PIPE_LOGICOP_NOOP
:
188 for (j
= 0; j
< 4; j
++)
191 case PIPE_LOGICOP_OR_INVERTED
:
192 for (j
= 0; j
< 4; j
++)
193 res4
[j
] = ~src4
[j
] | dst4
[j
];
195 case PIPE_LOGICOP_COPY
:
196 for (j
= 0; j
< 4; j
++)
199 case PIPE_LOGICOP_OR_REVERSE
:
200 for (j
= 0; j
< 4; j
++)
201 res4
[j
] = src4
[j
] | ~dst4
[j
];
203 case PIPE_LOGICOP_OR
:
204 for (j
= 0; j
< 4; j
++)
205 res4
[j
] = src4
[j
] | dst4
[j
];
207 case PIPE_LOGICOP_SET
:
208 for (j
= 0; j
< 4; j
++)
212 assert(0 && "invalid logicop mode");
215 for (j
= 0; j
< 4; j
++) {
216 quadColor
[j
][0] = ubyte_to_float(res
[j
][0]);
217 quadColor
[j
][1] = ubyte_to_float(res
[j
][1]);
218 quadColor
[j
][2] = ubyte_to_float(res
[j
][2]);
219 quadColor
[j
][3] = ubyte_to_float(res
[j
][3]);
226 * Do blending for a 2x2 quad for one color buffer.
227 * \param quadColor the incoming quad colors
228 * \param dest the destination/framebuffer quad colors
229 * \param blend_index which set of blending terms to use
230 * \param has_dst_alpha does the dest color buffer have an alpha channel?
233 blend_quad(struct quad_stage
*qs
,
234 float (*quadColor
)[4],
236 unsigned blend_index
,
237 boolean has_dst_alpha
)
239 static const float zero
[4] = { 0, 0, 0, 0 };
240 static const float one
[4] = { 1, 1, 1, 1 };
241 struct softpipe_context
*softpipe
= qs
->softpipe
;
242 float source
[4][QUAD_SIZE
] = { { 0 } };
245 * Compute src/first term RGB
247 switch (softpipe
->blend
->rt
[blend_index
].rgb_src_factor
) {
248 case PIPE_BLENDFACTOR_ONE
:
249 VEC4_COPY(source
[0], quadColor
[0]); /* R */
250 VEC4_COPY(source
[1], quadColor
[1]); /* G */
251 VEC4_COPY(source
[2], quadColor
[2]); /* B */
253 case PIPE_BLENDFACTOR_SRC_COLOR
:
254 VEC4_MUL(source
[0], quadColor
[0], quadColor
[0]); /* R */
255 VEC4_MUL(source
[1], quadColor
[1], quadColor
[1]); /* G */
256 VEC4_MUL(source
[2], quadColor
[2], quadColor
[2]); /* B */
258 case PIPE_BLENDFACTOR_SRC_ALPHA
:
260 const float *alpha
= quadColor
[3];
261 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
262 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
263 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
266 case PIPE_BLENDFACTOR_DST_COLOR
:
267 VEC4_MUL(source
[0], quadColor
[0], dest
[0]); /* R */
268 VEC4_MUL(source
[1], quadColor
[1], dest
[1]); /* G */
269 VEC4_MUL(source
[2], quadColor
[2], dest
[2]); /* B */
271 case PIPE_BLENDFACTOR_DST_ALPHA
:
273 const float *alpha
= dest
[3];
274 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
275 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
276 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
279 VEC4_COPY(source
[0], quadColor
[0]); /* R */
280 VEC4_COPY(source
[1], quadColor
[1]); /* G */
281 VEC4_COPY(source
[2], quadColor
[2]); /* B */
284 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
286 const float *alpha
= quadColor
[3];
287 float diff
[4], temp
[4];
288 VEC4_SUB(diff
, one
, dest
[3]);
289 VEC4_MIN(temp
, alpha
, diff
);
290 VEC4_MUL(source
[0], quadColor
[0], temp
); /* R */
291 VEC4_MUL(source
[1], quadColor
[1], temp
); /* G */
292 VEC4_MUL(source
[2], quadColor
[2], temp
); /* B */
295 VEC4_COPY(source
[0], zero
); /* R */
296 VEC4_COPY(source
[1], zero
); /* G */
297 VEC4_COPY(source
[2], zero
); /* B */
300 case PIPE_BLENDFACTOR_CONST_COLOR
:
303 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[0]); /* R */
304 VEC4_MUL(source
[0], quadColor
[0], comp
); /* R */
305 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[1]); /* G */
306 VEC4_MUL(source
[1], quadColor
[1], comp
); /* G */
307 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[2]); /* B */
308 VEC4_MUL(source
[2], quadColor
[2], comp
); /* B */
311 case PIPE_BLENDFACTOR_CONST_ALPHA
:
314 VEC4_SCALAR(alpha
, softpipe
->blend_color
.color
[3]);
315 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
316 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
317 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
320 case PIPE_BLENDFACTOR_SRC1_COLOR
:
321 assert(0); /* to do */
323 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
324 assert(0); /* to do */
326 case PIPE_BLENDFACTOR_ZERO
:
327 VEC4_COPY(source
[0], zero
); /* R */
328 VEC4_COPY(source
[1], zero
); /* G */
329 VEC4_COPY(source
[2], zero
); /* B */
331 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
334 VEC4_SUB(inv_comp
, one
, quadColor
[0]); /* R */
335 VEC4_MUL(source
[0], quadColor
[0], inv_comp
); /* R */
336 VEC4_SUB(inv_comp
, one
, quadColor
[1]); /* G */
337 VEC4_MUL(source
[1], quadColor
[1], inv_comp
); /* G */
338 VEC4_SUB(inv_comp
, one
, quadColor
[2]); /* B */
339 VEC4_MUL(source
[2], quadColor
[2], inv_comp
); /* B */
342 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
345 VEC4_SUB(inv_alpha
, one
, quadColor
[3]);
346 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
347 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
348 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
351 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
354 VEC4_SUB(inv_alpha
, one
, dest
[3]);
355 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
356 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
357 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
360 VEC4_COPY(source
[0], zero
); /* R */
361 VEC4_COPY(source
[1], zero
); /* G */
362 VEC4_COPY(source
[2], zero
); /* B */
365 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
368 VEC4_SUB(inv_comp
, one
, dest
[0]); /* R */
369 VEC4_MUL(source
[0], quadColor
[0], inv_comp
); /* R */
370 VEC4_SUB(inv_comp
, one
, dest
[1]); /* G */
371 VEC4_MUL(source
[1], quadColor
[1], inv_comp
); /* G */
372 VEC4_SUB(inv_comp
, one
, dest
[2]); /* B */
373 VEC4_MUL(source
[2], quadColor
[2], inv_comp
); /* B */
376 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
380 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
381 VEC4_MUL(source
[0], quadColor
[0], inv_comp
);
383 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
384 VEC4_MUL(source
[1], quadColor
[1], inv_comp
);
386 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
387 VEC4_MUL(source
[2], quadColor
[2], inv_comp
);
390 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
393 VEC4_SCALAR(inv_alpha
, 1.0f
- softpipe
->blend_color
.color
[3]);
394 VEC4_MUL(source
[0], quadColor
[0], inv_alpha
); /* R */
395 VEC4_MUL(source
[1], quadColor
[1], inv_alpha
); /* G */
396 VEC4_MUL(source
[2], quadColor
[2], inv_alpha
); /* B */
399 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
400 assert(0); /* to do */
402 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
403 assert(0); /* to do */
406 assert(0 && "invalid rgb src factor");
410 * Compute src/first term A
412 switch (softpipe
->blend
->rt
[blend_index
].alpha_src_factor
) {
413 case PIPE_BLENDFACTOR_ONE
:
414 VEC4_COPY(source
[3], quadColor
[3]); /* A */
416 case PIPE_BLENDFACTOR_SRC_COLOR
:
418 case PIPE_BLENDFACTOR_SRC_ALPHA
:
420 const float *alpha
= quadColor
[3];
421 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
424 case PIPE_BLENDFACTOR_DST_COLOR
:
426 case PIPE_BLENDFACTOR_DST_ALPHA
:
428 VEC4_MUL(source
[3], quadColor
[3], dest
[3]); /* A */
430 VEC4_COPY(source
[3], quadColor
[3]); /* A */
432 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
433 /* multiply alpha by 1.0 */
434 VEC4_COPY(source
[3], quadColor
[3]); /* A */
436 case PIPE_BLENDFACTOR_CONST_COLOR
:
438 case PIPE_BLENDFACTOR_CONST_ALPHA
:
441 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
442 VEC4_MUL(source
[3], quadColor
[3], comp
); /* A */
445 case PIPE_BLENDFACTOR_ZERO
:
446 VEC4_COPY(source
[3], zero
); /* A */
448 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
450 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
453 VEC4_SUB(inv_alpha
, one
, quadColor
[3]);
454 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
457 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
459 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
462 VEC4_SUB(inv_alpha
, one
, dest
[3]);
463 VEC4_MUL(source
[3], quadColor
[3], inv_alpha
); /* A */
466 VEC4_COPY(source
[3], zero
); /* A */
469 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
471 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
475 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
476 VEC4_MUL(source
[3], quadColor
[3], inv_comp
);
480 assert(0 && "invalid alpha src factor");
485 * Compute dest/second term RGB
487 switch (softpipe
->blend
->rt
[blend_index
].rgb_dst_factor
) {
488 case PIPE_BLENDFACTOR_ONE
:
489 /* dest = dest * 1 NO-OP, leave dest as-is */
491 case PIPE_BLENDFACTOR_SRC_COLOR
:
492 VEC4_MUL(dest
[0], dest
[0], quadColor
[0]); /* R */
493 VEC4_MUL(dest
[1], dest
[1], quadColor
[1]); /* G */
494 VEC4_MUL(dest
[2], dest
[2], quadColor
[2]); /* B */
496 case PIPE_BLENDFACTOR_SRC_ALPHA
:
497 VEC4_MUL(dest
[0], dest
[0], quadColor
[3]); /* R * A */
498 VEC4_MUL(dest
[1], dest
[1], quadColor
[3]); /* G * A */
499 VEC4_MUL(dest
[2], dest
[2], quadColor
[3]); /* B * A */
501 case PIPE_BLENDFACTOR_DST_ALPHA
:
503 VEC4_MUL(dest
[0], dest
[0], dest
[3]); /* R * A */
504 VEC4_MUL(dest
[1], dest
[1], dest
[3]); /* G * A */
505 VEC4_MUL(dest
[2], dest
[2], dest
[3]); /* B * A */
508 /* dest = dest * 1 NO-OP, leave dest as-is */
511 case PIPE_BLENDFACTOR_DST_COLOR
:
512 VEC4_MUL(dest
[0], dest
[0], dest
[0]); /* R */
513 VEC4_MUL(dest
[1], dest
[1], dest
[1]); /* G */
514 VEC4_MUL(dest
[2], dest
[2], dest
[2]); /* B */
516 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
518 const float *alpha
= quadColor
[3];
519 float diff
[4], temp
[4];
520 VEC4_SUB(diff
, one
, dest
[3]);
521 VEC4_MIN(temp
, alpha
, diff
);
522 VEC4_MUL(dest
[0], quadColor
[0], temp
); /* R */
523 VEC4_MUL(dest
[1], quadColor
[1], temp
); /* G */
524 VEC4_MUL(dest
[2], quadColor
[2], temp
); /* B */
527 VEC4_COPY(dest
[0], zero
); /* R */
528 VEC4_COPY(dest
[1], zero
); /* G */
529 VEC4_COPY(dest
[2], zero
); /* B */
532 case PIPE_BLENDFACTOR_CONST_COLOR
:
535 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[0]); /* R */
536 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
537 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[1]); /* G */
538 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
539 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[2]); /* B */
540 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
543 case PIPE_BLENDFACTOR_CONST_ALPHA
:
546 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
547 VEC4_MUL(dest
[0], dest
[0], comp
); /* R */
548 VEC4_MUL(dest
[1], dest
[1], comp
); /* G */
549 VEC4_MUL(dest
[2], dest
[2], comp
); /* B */
552 case PIPE_BLENDFACTOR_ZERO
:
553 VEC4_COPY(dest
[0], zero
); /* R */
554 VEC4_COPY(dest
[1], zero
); /* G */
555 VEC4_COPY(dest
[2], zero
); /* B */
557 case PIPE_BLENDFACTOR_SRC1_COLOR
:
558 case PIPE_BLENDFACTOR_SRC1_ALPHA
:
559 /* XXX what are these? */
562 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
565 VEC4_SUB(inv_comp
, one
, quadColor
[0]); /* R */
566 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
567 VEC4_SUB(inv_comp
, one
, quadColor
[1]); /* G */
568 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
569 VEC4_SUB(inv_comp
, one
, quadColor
[2]); /* B */
570 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
573 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
575 float one_minus_alpha
[QUAD_SIZE
];
576 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
577 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
578 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
579 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
582 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
585 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
586 VEC4_MUL(dest
[0], inv_comp
, dest
[0]); /* R */
587 VEC4_MUL(dest
[1], inv_comp
, dest
[1]); /* G */
588 VEC4_MUL(dest
[2], inv_comp
, dest
[2]); /* B */
591 VEC4_COPY(dest
[0], zero
); /* R */
592 VEC4_COPY(dest
[1], zero
); /* G */
593 VEC4_COPY(dest
[2], zero
); /* B */
596 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
599 VEC4_SUB(inv_comp
, one
, dest
[0]); /* R */
600 VEC4_MUL(dest
[0], dest
[0], inv_comp
); /* R */
601 VEC4_SUB(inv_comp
, one
, dest
[1]); /* G */
602 VEC4_MUL(dest
[1], dest
[1], inv_comp
); /* G */
603 VEC4_SUB(inv_comp
, one
, dest
[2]); /* B */
604 VEC4_MUL(dest
[2], dest
[2], inv_comp
); /* B */
607 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
611 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[0]);
612 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
614 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[1]);
615 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
617 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[2]);
618 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
621 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
624 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
625 VEC4_MUL(dest
[0], dest
[0], inv_comp
);
626 VEC4_MUL(dest
[1], dest
[1], inv_comp
);
627 VEC4_MUL(dest
[2], dest
[2], inv_comp
);
630 case PIPE_BLENDFACTOR_INV_SRC1_COLOR
:
631 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA
:
632 /* XXX what are these? */
636 assert(0 && "invalid rgb dst factor");
640 * Compute dest/second term A
642 switch (softpipe
->blend
->rt
[blend_index
].alpha_dst_factor
) {
643 case PIPE_BLENDFACTOR_ONE
:
644 /* dest = dest * 1 NO-OP, leave dest as-is */
646 case PIPE_BLENDFACTOR_SRC_COLOR
:
648 case PIPE_BLENDFACTOR_SRC_ALPHA
:
649 VEC4_MUL(dest
[3], dest
[3], quadColor
[3]); /* A * A */
651 case PIPE_BLENDFACTOR_DST_COLOR
:
653 case PIPE_BLENDFACTOR_DST_ALPHA
:
655 VEC4_MUL(dest
[3], dest
[3], dest
[3]); /* A */
658 /* dest = dest * 1 NO-OP, leave dest as-is */
661 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
:
662 /* dest = dest * 1 NO-OP, leave dest as-is */
664 case PIPE_BLENDFACTOR_CONST_COLOR
:
666 case PIPE_BLENDFACTOR_CONST_ALPHA
:
669 VEC4_SCALAR(comp
, softpipe
->blend_color
.color
[3]); /* A */
670 VEC4_MUL(dest
[3], dest
[3], comp
); /* A */
673 case PIPE_BLENDFACTOR_ZERO
:
674 VEC4_COPY(dest
[3], zero
); /* A */
676 case PIPE_BLENDFACTOR_INV_SRC_COLOR
:
678 case PIPE_BLENDFACTOR_INV_SRC_ALPHA
:
680 float one_minus_alpha
[QUAD_SIZE
];
681 VEC4_SUB(one_minus_alpha
, one
, quadColor
[3]);
682 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* A */
685 case PIPE_BLENDFACTOR_INV_DST_COLOR
:
687 case PIPE_BLENDFACTOR_INV_DST_ALPHA
:
690 VEC4_SUB(inv_comp
, one
, dest
[3]); /* A */
691 VEC4_MUL(dest
[3], inv_comp
, dest
[3]); /* A */
694 VEC4_COPY(dest
[3], zero
); /* A */
697 case PIPE_BLENDFACTOR_INV_CONST_COLOR
:
699 case PIPE_BLENDFACTOR_INV_CONST_ALPHA
:
702 VEC4_SCALAR(inv_comp
, 1.0f
- softpipe
->blend_color
.color
[3]);
703 VEC4_MUL(dest
[3], dest
[3], inv_comp
);
707 assert(0 && "invalid alpha dst factor");
713 switch (softpipe
->blend
->rt
[blend_index
].rgb_func
) {
715 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
716 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
717 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
719 case PIPE_BLEND_SUBTRACT
:
720 VEC4_SUB_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
721 VEC4_SUB_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
722 VEC4_SUB_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
724 case PIPE_BLEND_REVERSE_SUBTRACT
:
725 VEC4_SUB_SAT(quadColor
[0], dest
[0], source
[0]); /* R */
726 VEC4_SUB_SAT(quadColor
[1], dest
[1], source
[1]); /* G */
727 VEC4_SUB_SAT(quadColor
[2], dest
[2], source
[2]); /* B */
730 VEC4_MIN(quadColor
[0], source
[0], dest
[0]); /* R */
731 VEC4_MIN(quadColor
[1], source
[1], dest
[1]); /* G */
732 VEC4_MIN(quadColor
[2], source
[2], dest
[2]); /* B */
735 VEC4_MAX(quadColor
[0], source
[0], dest
[0]); /* R */
736 VEC4_MAX(quadColor
[1], source
[1], dest
[1]); /* G */
737 VEC4_MAX(quadColor
[2], source
[2], dest
[2]); /* B */
740 assert(0 && "invalid rgb blend func");
746 switch (softpipe
->blend
->rt
[blend_index
].alpha_func
) {
748 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
750 case PIPE_BLEND_SUBTRACT
:
751 VEC4_SUB_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
753 case PIPE_BLEND_REVERSE_SUBTRACT
:
754 VEC4_SUB_SAT(quadColor
[3], dest
[3], source
[3]); /* A */
757 VEC4_MIN(quadColor
[3], source
[3], dest
[3]); /* A */
760 VEC4_MAX(quadColor
[3], source
[3], dest
[3]); /* A */
763 assert(0 && "invalid alpha blend func");
768 colormask_quad(unsigned colormask
,
769 float (*quadColor
)[4],
773 if (!(colormask
& PIPE_MASK_R
))
774 COPY_4V(quadColor
[0], dest
[0]);
777 if (!(colormask
& PIPE_MASK_G
))
778 COPY_4V(quadColor
[1], dest
[1]);
781 if (!(colormask
& PIPE_MASK_B
))
782 COPY_4V(quadColor
[2], dest
[2]);
785 if (!(colormask
& PIPE_MASK_A
))
786 COPY_4V(quadColor
[3], dest
[3]);
791 blend_fallback(struct quad_stage
*qs
,
792 struct quad_header
*quads
[],
795 struct softpipe_context
*softpipe
= qs
->softpipe
;
796 const struct pipe_blend_state
*blend
= softpipe
->blend
;
800 write_all
= softpipe
->fs
->color0_writes_all_cbufs
;
802 for (cbuf
= 0; cbuf
< softpipe
->framebuffer
.nr_cbufs
; cbuf
++)
804 /* which blend/mask state index to use: */
805 const uint blend_buf
= blend
->independent_blend_enable
? cbuf
: 0;
806 float dest
[4][QUAD_SIZE
];
807 struct softpipe_cached_tile
*tile
808 = sp_get_cached_tile(softpipe
->cbuf_cache
[cbuf
],
811 boolean has_dst_alpha
812 = util_format_has_alpha(softpipe
->framebuffer
.cbufs
[cbuf
]->format
);
815 qbuf
= write_all
? 0 : cbuf
;
817 for (q
= 0; q
< nr
; q
++) {
818 struct quad_header
*quad
= quads
[q
];
819 float (*quadColor
)[4];
820 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
821 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
823 quadColor
= quad
->output
.color
[qbuf
];
825 /* get/swizzle dest colors
827 for (j
= 0; j
< QUAD_SIZE
; j
++) {
828 int x
= itx
+ (j
& 1);
829 int y
= ity
+ (j
>> 1);
830 for (i
= 0; i
< 4; i
++) {
831 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
836 if (blend
->logicop_enable
) {
837 logicop_quad( qs
, quadColor
, dest
);
839 else if (blend
->rt
[blend_buf
].blend_enable
) {
840 blend_quad( qs
, quadColor
, dest
, blend_buf
, has_dst_alpha
);
843 if (blend
->rt
[blend_buf
].colormask
!= 0xf)
844 colormask_quad( blend
->rt
[cbuf
].colormask
, quadColor
, dest
);
846 /* Output color values
848 for (j
= 0; j
< QUAD_SIZE
; j
++) {
849 if (quad
->inout
.mask
& (1 << j
)) {
850 int x
= itx
+ (j
& 1);
851 int y
= ity
+ (j
>> 1);
852 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
853 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
863 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage
*qs
,
864 struct quad_header
*quads
[],
867 static const float one
[4] = { 1, 1, 1, 1 };
868 float one_minus_alpha
[QUAD_SIZE
];
869 float dest
[4][QUAD_SIZE
];
870 float source
[4][QUAD_SIZE
];
873 struct softpipe_cached_tile
*tile
874 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
878 for (q
= 0; q
< nr
; q
++) {
879 struct quad_header
*quad
= quads
[q
];
880 float (*quadColor
)[4] = quad
->output
.color
[0];
881 const float *alpha
= quadColor
[3];
882 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
883 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
885 /* get/swizzle dest colors */
886 for (j
= 0; j
< QUAD_SIZE
; j
++) {
887 int x
= itx
+ (j
& 1);
888 int y
= ity
+ (j
>> 1);
889 for (i
= 0; i
< 4; i
++) {
890 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
894 VEC4_MUL(source
[0], quadColor
[0], alpha
); /* R */
895 VEC4_MUL(source
[1], quadColor
[1], alpha
); /* G */
896 VEC4_MUL(source
[2], quadColor
[2], alpha
); /* B */
897 VEC4_MUL(source
[3], quadColor
[3], alpha
); /* A */
899 VEC4_SUB(one_minus_alpha
, one
, alpha
);
900 VEC4_MUL(dest
[0], dest
[0], one_minus_alpha
); /* R */
901 VEC4_MUL(dest
[1], dest
[1], one_minus_alpha
); /* G */
902 VEC4_MUL(dest
[2], dest
[2], one_minus_alpha
); /* B */
903 VEC4_MUL(dest
[3], dest
[3], one_minus_alpha
); /* B */
905 VEC4_ADD_SAT(quadColor
[0], source
[0], dest
[0]); /* R */
906 VEC4_ADD_SAT(quadColor
[1], source
[1], dest
[1]); /* G */
907 VEC4_ADD_SAT(quadColor
[2], source
[2], dest
[2]); /* B */
908 VEC4_ADD_SAT(quadColor
[3], source
[3], dest
[3]); /* A */
910 for (j
= 0; j
< QUAD_SIZE
; j
++) {
911 if (quad
->inout
.mask
& (1 << j
)) {
912 int x
= itx
+ (j
& 1);
913 int y
= ity
+ (j
>> 1);
914 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
915 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
923 blend_single_add_one_one(struct quad_stage
*qs
,
924 struct quad_header
*quads
[],
927 float dest
[4][QUAD_SIZE
];
930 struct softpipe_cached_tile
*tile
931 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
935 for (q
= 0; q
< nr
; q
++) {
936 struct quad_header
*quad
= quads
[q
];
937 float (*quadColor
)[4] = quad
->output
.color
[0];
938 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
939 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
941 /* get/swizzle dest colors */
942 for (j
= 0; j
< QUAD_SIZE
; j
++) {
943 int x
= itx
+ (j
& 1);
944 int y
= ity
+ (j
>> 1);
945 for (i
= 0; i
< 4; i
++) {
946 dest
[i
][j
] = tile
->data
.color
[y
][x
][i
];
950 VEC4_ADD_SAT(quadColor
[0], quadColor
[0], dest
[0]); /* R */
951 VEC4_ADD_SAT(quadColor
[1], quadColor
[1], dest
[1]); /* G */
952 VEC4_ADD_SAT(quadColor
[2], quadColor
[2], dest
[2]); /* B */
953 VEC4_ADD_SAT(quadColor
[3], quadColor
[3], dest
[3]); /* A */
955 for (j
= 0; j
< QUAD_SIZE
; j
++) {
956 if (quad
->inout
.mask
& (1 << j
)) {
957 int x
= itx
+ (j
& 1);
958 int y
= ity
+ (j
>> 1);
959 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
960 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
969 single_output_color(struct quad_stage
*qs
,
970 struct quad_header
*quads
[],
975 struct softpipe_cached_tile
*tile
976 = sp_get_cached_tile(qs
->softpipe
->cbuf_cache
[0],
980 for (q
= 0; q
< nr
; q
++) {
981 struct quad_header
*quad
= quads
[q
];
982 float (*quadColor
)[4] = quad
->output
.color
[0];
983 const int itx
= (quad
->input
.x0
& (TILE_SIZE
-1));
984 const int ity
= (quad
->input
.y0
& (TILE_SIZE
-1));
986 for (j
= 0; j
< QUAD_SIZE
; j
++) {
987 if (quad
->inout
.mask
& (1 << j
)) {
988 int x
= itx
+ (j
& 1);
989 int y
= ity
+ (j
>> 1);
990 for (i
= 0; i
< 4; i
++) { /* loop over color chans */
991 tile
->data
.color
[y
][x
][i
] = quadColor
[i
][j
];
999 blend_noop(struct quad_stage
*qs
,
1000 struct quad_header
*quads
[],
1007 choose_blend_quad(struct quad_stage
*qs
,
1008 struct quad_header
*quads
[],
1011 struct softpipe_context
*softpipe
= qs
->softpipe
;
1012 const struct pipe_blend_state
*blend
= softpipe
->blend
;
1014 qs
->run
= blend_fallback
;
1016 if (softpipe
->framebuffer
.nr_cbufs
== 0) {
1017 qs
->run
= blend_noop
;
1019 else if (!softpipe
->blend
->logicop_enable
&&
1020 softpipe
->blend
->rt
[0].colormask
== 0xf &&
1021 softpipe
->framebuffer
.nr_cbufs
== 1)
1023 if (!blend
->rt
[0].blend_enable
) {
1024 qs
->run
= single_output_color
;
1026 else if (blend
->rt
[0].rgb_src_factor
== blend
->rt
[0].alpha_src_factor
&&
1027 blend
->rt
[0].rgb_dst_factor
== blend
->rt
[0].alpha_dst_factor
&&
1028 blend
->rt
[0].rgb_func
== blend
->rt
[0].alpha_func
)
1030 if (blend
->rt
[0].alpha_func
== PIPE_BLEND_ADD
) {
1031 if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_ONE
&&
1032 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_ONE
) {
1033 qs
->run
= blend_single_add_one_one
;
1035 else if (blend
->rt
[0].rgb_src_factor
== PIPE_BLENDFACTOR_SRC_ALPHA
&&
1036 blend
->rt
[0].rgb_dst_factor
== PIPE_BLENDFACTOR_INV_SRC_ALPHA
)
1037 qs
->run
= blend_single_add_src_alpha_inv_src_alpha
;
1043 qs
->run(qs
, quads
, nr
);
1047 static void blend_begin(struct quad_stage
*qs
)
1049 qs
->run
= choose_blend_quad
;
1053 static void blend_destroy(struct quad_stage
*qs
)
1059 struct quad_stage
*sp_quad_blend_stage( struct softpipe_context
*softpipe
)
1061 struct quad_stage
*stage
= CALLOC_STRUCT(quad_stage
);
1063 stage
->softpipe
= softpipe
;
1064 stage
->begin
= blend_begin
;
1065 stage
->run
= choose_blend_quad
;
1066 stage
->destroy
= blend_destroy
;