Merge branch 'master' into gallium-sampler-view
[mesa.git] / src / gallium / drivers / softpipe / sp_quad_blend.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * quad blending
30 * \author Brian Paul
31 */
32
33 #include "pipe/p_defines.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
36 #include "sp_context.h"
37 #include "sp_quad.h"
38 #include "sp_tile_cache.h"
39 #include "sp_quad_pipe.h"
40
41
42 #define VEC4_COPY(DST, SRC) \
43 do { \
44 DST[0] = SRC[0]; \
45 DST[1] = SRC[1]; \
46 DST[2] = SRC[2]; \
47 DST[3] = SRC[3]; \
48 } while(0)
49
50 #define VEC4_SCALAR(DST, SRC) \
51 do { \
52 DST[0] = SRC; \
53 DST[1] = SRC; \
54 DST[2] = SRC; \
55 DST[3] = SRC; \
56 } while(0)
57
58 #define VEC4_ADD(R, A, B) \
59 do { \
60 R[0] = A[0] + B[0]; \
61 R[1] = A[1] + B[1]; \
62 R[2] = A[2] + B[2]; \
63 R[3] = A[3] + B[3]; \
64 } while (0)
65
66 #define VEC4_SUB(R, A, B) \
67 do { \
68 R[0] = A[0] - B[0]; \
69 R[1] = A[1] - B[1]; \
70 R[2] = A[2] - B[2]; \
71 R[3] = A[3] - B[3]; \
72 } while (0)
73
74 /** Add and limit result to ceiling of 1.0 */
75 #define VEC4_ADD_SAT(R, A, B) \
76 do { \
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; \
81 } while (0)
82
83 /** Subtract and limit result to floor of 0.0 */
84 #define VEC4_SUB_SAT(R, A, B) \
85 do { \
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; \
90 } while (0)
91
92 #define VEC4_MUL(R, A, B) \
93 do { \
94 R[0] = A[0] * B[0]; \
95 R[1] = A[1] * B[1]; \
96 R[2] = A[2] * B[2]; \
97 R[3] = A[3] * B[3]; \
98 } while (0)
99
100 #define VEC4_MIN(R, A, B) \
101 do { \
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]; \
106 } while (0)
107
108 #define VEC4_MAX(R, A, B) \
109 do { \
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]; \
114 } while (0)
115
116
117
118 static void
119 logicop_quad(struct quad_stage *qs,
120 float (*quadColor)[4],
121 float (*dest)[4])
122 {
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;
128 uint j;
129
130
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 */
137
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 */
142 }
143
144 switch (softpipe->blend->logicop_func) {
145 case PIPE_LOGICOP_CLEAR:
146 for (j = 0; j < 4; j++)
147 res4[j] = 0;
148 break;
149 case PIPE_LOGICOP_NOR:
150 for (j = 0; j < 4; j++)
151 res4[j] = ~(src4[j] | dst4[j]);
152 break;
153 case PIPE_LOGICOP_AND_INVERTED:
154 for (j = 0; j < 4; j++)
155 res4[j] = ~src4[j] & dst4[j];
156 break;
157 case PIPE_LOGICOP_COPY_INVERTED:
158 for (j = 0; j < 4; j++)
159 res4[j] = ~src4[j];
160 break;
161 case PIPE_LOGICOP_AND_REVERSE:
162 for (j = 0; j < 4; j++)
163 res4[j] = src4[j] & ~dst4[j];
164 break;
165 case PIPE_LOGICOP_INVERT:
166 for (j = 0; j < 4; j++)
167 res4[j] = ~dst4[j];
168 break;
169 case PIPE_LOGICOP_XOR:
170 for (j = 0; j < 4; j++)
171 res4[j] = dst4[j] ^ src4[j];
172 break;
173 case PIPE_LOGICOP_NAND:
174 for (j = 0; j < 4; j++)
175 res4[j] = ~(src4[j] & dst4[j]);
176 break;
177 case PIPE_LOGICOP_AND:
178 for (j = 0; j < 4; j++)
179 res4[j] = src4[j] & dst4[j];
180 break;
181 case PIPE_LOGICOP_EQUIV:
182 for (j = 0; j < 4; j++)
183 res4[j] = ~(src4[j] ^ dst4[j]);
184 break;
185 case PIPE_LOGICOP_NOOP:
186 for (j = 0; j < 4; j++)
187 res4[j] = dst4[j];
188 break;
189 case PIPE_LOGICOP_OR_INVERTED:
190 for (j = 0; j < 4; j++)
191 res4[j] = ~src4[j] | dst4[j];
192 break;
193 case PIPE_LOGICOP_COPY:
194 for (j = 0; j < 4; j++)
195 res4[j] = src4[j];
196 break;
197 case PIPE_LOGICOP_OR_REVERSE:
198 for (j = 0; j < 4; j++)
199 res4[j] = src4[j] | ~dst4[j];
200 break;
201 case PIPE_LOGICOP_OR:
202 for (j = 0; j < 4; j++)
203 res4[j] = src4[j] | dst4[j];
204 break;
205 case PIPE_LOGICOP_SET:
206 for (j = 0; j < 4; j++)
207 res4[j] = ~0;
208 break;
209 default:
210 assert(0);
211 }
212
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]);
218 }
219 }
220
221
222
223 static void
224 blend_quad(struct quad_stage *qs,
225 float (*quadColor)[4],
226 float (*dest)[4],
227 unsigned cbuf)
228 {
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 } };
233
234 /*
235 * Compute src/first term RGB
236 */
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 */
242 break;
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 */
247 break;
248 case PIPE_BLENDFACTOR_SRC_ALPHA:
249 {
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 */
254 }
255 break;
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 */
260 break;
261 case PIPE_BLENDFACTOR_DST_ALPHA:
262 {
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 */
267 }
268 break;
269 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
270 {
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 */
278 }
279 break;
280 case PIPE_BLENDFACTOR_CONST_COLOR:
281 {
282 float comp[4];
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 */
289 }
290 break;
291 case PIPE_BLENDFACTOR_CONST_ALPHA:
292 {
293 float alpha[4];
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 */
298 }
299 break;
300 case PIPE_BLENDFACTOR_SRC1_COLOR:
301 assert(0); /* to do */
302 break;
303 case PIPE_BLENDFACTOR_SRC1_ALPHA:
304 assert(0); /* to do */
305 break;
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 */
310 break;
311 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
312 {
313 float inv_comp[4];
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 */
320 }
321 break;
322 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
323 {
324 float inv_alpha[4];
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 */
329 }
330 break;
331 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
332 {
333 float inv_alpha[4];
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 */
338 }
339 break;
340 case PIPE_BLENDFACTOR_INV_DST_COLOR:
341 {
342 float inv_comp[4];
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 */
349 }
350 break;
351 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
352 {
353 float inv_comp[4];
354 /* R */
355 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
356 VEC4_MUL(source[0], quadColor[0], inv_comp);
357 /* G */
358 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
359 VEC4_MUL(source[1], quadColor[1], inv_comp);
360 /* B */
361 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
362 VEC4_MUL(source[2], quadColor[2], inv_comp);
363 }
364 break;
365 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
366 {
367 float inv_alpha[4];
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 */
372 }
373 break;
374 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
375 assert(0); /* to do */
376 break;
377 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
378 assert(0); /* to do */
379 break;
380 default:
381 assert(0);
382 }
383
384 /*
385 * Compute src/first term A
386 */
387 switch (softpipe->blend->rt[cbuf].alpha_src_factor) {
388 case PIPE_BLENDFACTOR_ONE:
389 VEC4_COPY(source[3], quadColor[3]); /* A */
390 break;
391 case PIPE_BLENDFACTOR_SRC_COLOR:
392 /* fall-through */
393 case PIPE_BLENDFACTOR_SRC_ALPHA:
394 {
395 const float *alpha = quadColor[3];
396 VEC4_MUL(source[3], quadColor[3], alpha); /* A */
397 }
398 break;
399 case PIPE_BLENDFACTOR_DST_COLOR:
400 /* fall-through */
401 case PIPE_BLENDFACTOR_DST_ALPHA:
402 VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
403 break;
404 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
405 /* multiply alpha by 1.0 */
406 VEC4_COPY(source[3], quadColor[3]); /* A */
407 break;
408 case PIPE_BLENDFACTOR_CONST_COLOR:
409 /* fall-through */
410 case PIPE_BLENDFACTOR_CONST_ALPHA:
411 {
412 float comp[4];
413 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
414 VEC4_MUL(source[3], quadColor[3], comp); /* A */
415 }
416 break;
417 case PIPE_BLENDFACTOR_ZERO:
418 VEC4_COPY(source[3], zero); /* A */
419 break;
420 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
421 /* fall-through */
422 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
423 {
424 float inv_alpha[4];
425 VEC4_SUB(inv_alpha, one, quadColor[3]);
426 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
427 }
428 break;
429 case PIPE_BLENDFACTOR_INV_DST_COLOR:
430 /* fall-through */
431 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
432 {
433 float inv_alpha[4];
434 VEC4_SUB(inv_alpha, one, dest[3]);
435 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
436 }
437 break;
438 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
439 /* fall-through */
440 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
441 {
442 float inv_comp[4];
443 /* A */
444 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
445 VEC4_MUL(source[3], quadColor[3], inv_comp);
446 }
447 break;
448 default:
449 assert(0);
450 }
451
452
453 /*
454 * Compute dest/second term RGB
455 */
456 switch (softpipe->blend->rt[cbuf].rgb_dst_factor) {
457 case PIPE_BLENDFACTOR_ONE:
458 /* dest = dest * 1 NO-OP, leave dest as-is */
459 break;
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 */
464 break;
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 */
469 break;
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 */
474 break;
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 */
479 break;
480 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
481 {
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 */
489 }
490 break;
491 case PIPE_BLENDFACTOR_CONST_COLOR:
492 {
493 float comp[4];
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 */
500 }
501 break;
502 case PIPE_BLENDFACTOR_CONST_ALPHA:
503 {
504 float comp[4];
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 */
509 }
510 break;
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 */
515 break;
516 case PIPE_BLENDFACTOR_SRC1_COLOR:
517 case PIPE_BLENDFACTOR_SRC1_ALPHA:
518 /* XXX what are these? */
519 assert(0);
520 break;
521 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
522 {
523 float inv_comp[4];
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 */
530 }
531 break;
532 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
533 {
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 */
539 }
540 break;
541 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
542 {
543 float inv_comp[4];
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 */
548 }
549 break;
550 case PIPE_BLENDFACTOR_INV_DST_COLOR:
551 {
552 float inv_comp[4];
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 */
559 }
560 break;
561 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
562 {
563 float inv_comp[4];
564 /* R */
565 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
566 VEC4_MUL(dest[0], dest[0], inv_comp);
567 /* G */
568 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
569 VEC4_MUL(dest[1], dest[1], inv_comp);
570 /* B */
571 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
572 VEC4_MUL(dest[2], dest[2], inv_comp);
573 }
574 break;
575 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
576 {
577 float inv_comp[4];
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);
582 }
583 break;
584 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
585 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
586 /* XXX what are these? */
587 assert(0);
588 break;
589 default:
590 assert(0);
591 }
592
593 /*
594 * Compute dest/second term A
595 */
596 switch (softpipe->blend->rt[cbuf].alpha_dst_factor) {
597 case PIPE_BLENDFACTOR_ONE:
598 /* dest = dest * 1 NO-OP, leave dest as-is */
599 break;
600 case PIPE_BLENDFACTOR_SRC_COLOR:
601 /* fall-through */
602 case PIPE_BLENDFACTOR_SRC_ALPHA:
603 VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
604 break;
605 case PIPE_BLENDFACTOR_DST_COLOR:
606 /* fall-through */
607 case PIPE_BLENDFACTOR_DST_ALPHA:
608 VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
609 break;
610 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
611 /* dest = dest * 1 NO-OP, leave dest as-is */
612 break;
613 case PIPE_BLENDFACTOR_CONST_COLOR:
614 /* fall-through */
615 case PIPE_BLENDFACTOR_CONST_ALPHA:
616 {
617 float comp[4];
618 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
619 VEC4_MUL(dest[3], dest[3], comp); /* A */
620 }
621 break;
622 case PIPE_BLENDFACTOR_ZERO:
623 VEC4_COPY(dest[3], zero); /* A */
624 break;
625 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
626 /* fall-through */
627 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
628 {
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 */
632 }
633 break;
634 case PIPE_BLENDFACTOR_INV_DST_COLOR:
635 /* fall-through */
636 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
637 {
638 float inv_comp[4];
639 VEC4_SUB(inv_comp, one, dest[3]); /* A */
640 VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
641 }
642 break;
643 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
644 /* fall-through */
645 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
646 {
647 float inv_comp[4];
648 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
649 VEC4_MUL(dest[3], dest[3], inv_comp);
650 }
651 break;
652 default:
653 assert(0);
654 }
655
656 /*
657 * Combine RGB terms
658 */
659 switch (softpipe->blend->rt[cbuf].rgb_func) {
660 case PIPE_BLEND_ADD:
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 */
664 break;
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 */
669 break;
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 */
674 break;
675 case PIPE_BLEND_MIN:
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 */
679 break;
680 case PIPE_BLEND_MAX:
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 */
684 break;
685 default:
686 assert(0);
687 }
688
689 /*
690 * Combine A terms
691 */
692 switch (softpipe->blend->rt[cbuf].alpha_func) {
693 case PIPE_BLEND_ADD:
694 VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
695 break;
696 case PIPE_BLEND_SUBTRACT:
697 VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
698 break;
699 case PIPE_BLEND_REVERSE_SUBTRACT:
700 VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
701 break;
702 case PIPE_BLEND_MIN:
703 VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
704 break;
705 case PIPE_BLEND_MAX:
706 VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
707 break;
708 default:
709 assert(0);
710 }
711 }
712
713 static void
714 colormask_quad(unsigned colormask,
715 float (*quadColor)[4],
716 float (*dest)[4])
717 {
718 /* R */
719 if (!(colormask & PIPE_MASK_R))
720 COPY_4V(quadColor[0], dest[0]);
721
722 /* G */
723 if (!(colormask & PIPE_MASK_G))
724 COPY_4V(quadColor[1], dest[1]);
725
726 /* B */
727 if (!(colormask & PIPE_MASK_B))
728 COPY_4V(quadColor[2], dest[2]);
729
730 /* A */
731 if (!(colormask & PIPE_MASK_A))
732 COPY_4V(quadColor[3], dest[3]);
733 }
734
735
736 static void
737 blend_fallback(struct quad_stage *qs,
738 struct quad_header *quads[],
739 unsigned nr)
740 {
741 struct softpipe_context *softpipe = qs->softpipe;
742 const struct pipe_blend_state *blend = softpipe->blend;
743 unsigned cbuf;
744
745 for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
746 {
747 float dest[4][QUAD_SIZE];
748 struct softpipe_cached_tile *tile
749 = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
750 quads[0]->input.x0,
751 quads[0]->input.y0);
752 uint q, i, j;
753
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));
759
760 /* get/swizzle dest colors
761 */
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];
767 }
768 }
769
770
771 if (blend->logicop_enable) {
772 logicop_quad( qs, quadColor, dest );
773 }
774 else if (blend->rt[cbuf].blend_enable) {
775 blend_quad( qs, quadColor, dest, cbuf );
776 }
777
778 if (blend->rt[cbuf].colormask != 0xf)
779 colormask_quad( blend->rt[cbuf].colormask, quadColor, dest);
780
781 /* Output color values
782 */
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];
789 }
790 }
791 }
792 }
793 }
794 }
795
796
797 static void
798 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
799 struct quad_header *quads[],
800 unsigned nr)
801 {
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];
806 uint i, j, q;
807
808 struct softpipe_cached_tile *tile
809 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
810 quads[0]->input.x0,
811 quads[0]->input.y0);
812
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));
819
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];
826 }
827 }
828
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 */
833
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 */
839
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 */
844
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];
851 }
852 }
853 }
854 }
855 }
856
857 static void
858 blend_single_add_one_one(struct quad_stage *qs,
859 struct quad_header *quads[],
860 unsigned nr)
861 {
862 float dest[4][QUAD_SIZE];
863 uint i, j, q;
864
865 struct softpipe_cached_tile *tile
866 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
867 quads[0]->input.x0,
868 quads[0]->input.y0);
869
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));
875
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];
882 }
883 }
884
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 */
889
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];
896 }
897 }
898 }
899 }
900 }
901
902
903 static void
904 single_output_color(struct quad_stage *qs,
905 struct quad_header *quads[],
906 unsigned nr)
907 {
908 uint i, j, q;
909
910 struct softpipe_cached_tile *tile
911 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
912 quads[0]->input.x0,
913 quads[0]->input.y0);
914
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));
920
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];
927 }
928 }
929 }
930 }
931 }
932
933 static void
934 blend_noop(struct quad_stage *qs,
935 struct quad_header *quads[],
936 unsigned nr)
937 {
938 }
939
940
941 static void
942 choose_blend_quad(struct quad_stage *qs,
943 struct quad_header *quads[],
944 unsigned nr)
945 {
946 struct softpipe_context *softpipe = qs->softpipe;
947 const struct pipe_blend_state *blend = softpipe->blend;
948
949 qs->run = blend_fallback;
950
951 if (softpipe->framebuffer.nr_cbufs == 0) {
952 qs->run = blend_noop;
953 }
954 else if (!softpipe->blend->logicop_enable &&
955 softpipe->blend->rt[0].colormask == 0xf &&
956 softpipe->framebuffer.nr_cbufs == 1)
957 {
958 if (!blend->rt[0].blend_enable) {
959 qs->run = single_output_color;
960 }
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)
964 {
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;
969 }
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;
973
974 }
975 }
976 }
977
978 qs->run(qs, quads, nr);
979 }
980
981
982 static void blend_begin(struct quad_stage *qs)
983 {
984 qs->run = choose_blend_quad;
985 }
986
987
988 static void blend_destroy(struct quad_stage *qs)
989 {
990 FREE( qs );
991 }
992
993
994 struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
995 {
996 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
997
998 stage->softpipe = softpipe;
999 stage->begin = blend_begin;
1000 stage->run = choose_blend_quad;
1001 stage->destroy = blend_destroy;
1002
1003 return stage;
1004 }