vl: Subpicture/compositing fixes.
[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_surface.h"
39 #include "sp_tile_cache.h"
40 #include "sp_quad_pipe.h"
41
42
43 #define VEC4_COPY(DST, SRC) \
44 do { \
45 DST[0] = SRC[0]; \
46 DST[1] = SRC[1]; \
47 DST[2] = SRC[2]; \
48 DST[3] = SRC[3]; \
49 } while(0)
50
51 #define VEC4_SCALAR(DST, SRC) \
52 do { \
53 DST[0] = SRC; \
54 DST[1] = SRC; \
55 DST[2] = SRC; \
56 DST[3] = SRC; \
57 } while(0)
58
59 #define VEC4_ADD(R, A, B) \
60 do { \
61 R[0] = A[0] + B[0]; \
62 R[1] = A[1] + B[1]; \
63 R[2] = A[2] + B[2]; \
64 R[3] = A[3] + B[3]; \
65 } while (0)
66
67 #define VEC4_SUB(R, A, B) \
68 do { \
69 R[0] = A[0] - B[0]; \
70 R[1] = A[1] - B[1]; \
71 R[2] = A[2] - B[2]; \
72 R[3] = A[3] - B[3]; \
73 } while (0)
74
75 /** Add and limit result to ceiling of 1.0 */
76 #define VEC4_ADD_SAT(R, A, B) \
77 do { \
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; \
82 } while (0)
83
84 /** Subtract and limit result to floor of 0.0 */
85 #define VEC4_SUB_SAT(R, A, B) \
86 do { \
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; \
91 } while (0)
92
93 #define VEC4_MUL(R, A, B) \
94 do { \
95 R[0] = A[0] * B[0]; \
96 R[1] = A[1] * B[1]; \
97 R[2] = A[2] * B[2]; \
98 R[3] = A[3] * B[3]; \
99 } while (0)
100
101 #define VEC4_MIN(R, A, B) \
102 do { \
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]; \
107 } while (0)
108
109 #define VEC4_MAX(R, A, B) \
110 do { \
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]; \
115 } while (0)
116
117
118
119 static void
120 logicop_quad(struct quad_stage *qs,
121 float (*quadColor)[4],
122 float (*dest)[4])
123 {
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;
129 uint j;
130
131
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 */
138
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 */
143 }
144
145 switch (softpipe->blend->logicop_func) {
146 case PIPE_LOGICOP_CLEAR:
147 for (j = 0; j < 4; j++)
148 res4[j] = 0;
149 break;
150 case PIPE_LOGICOP_NOR:
151 for (j = 0; j < 4; j++)
152 res4[j] = ~(src4[j] | dst4[j]);
153 break;
154 case PIPE_LOGICOP_AND_INVERTED:
155 for (j = 0; j < 4; j++)
156 res4[j] = ~src4[j] & dst4[j];
157 break;
158 case PIPE_LOGICOP_COPY_INVERTED:
159 for (j = 0; j < 4; j++)
160 res4[j] = ~src4[j];
161 break;
162 case PIPE_LOGICOP_AND_REVERSE:
163 for (j = 0; j < 4; j++)
164 res4[j] = src4[j] & ~dst4[j];
165 break;
166 case PIPE_LOGICOP_INVERT:
167 for (j = 0; j < 4; j++)
168 res4[j] = ~dst4[j];
169 break;
170 case PIPE_LOGICOP_XOR:
171 for (j = 0; j < 4; j++)
172 res4[j] = dst4[j] ^ src4[j];
173 break;
174 case PIPE_LOGICOP_NAND:
175 for (j = 0; j < 4; j++)
176 res4[j] = ~(src4[j] & dst4[j]);
177 break;
178 case PIPE_LOGICOP_AND:
179 for (j = 0; j < 4; j++)
180 res4[j] = src4[j] & dst4[j];
181 break;
182 case PIPE_LOGICOP_EQUIV:
183 for (j = 0; j < 4; j++)
184 res4[j] = ~(src4[j] ^ dst4[j]);
185 break;
186 case PIPE_LOGICOP_NOOP:
187 for (j = 0; j < 4; j++)
188 res4[j] = dst4[j];
189 break;
190 case PIPE_LOGICOP_OR_INVERTED:
191 for (j = 0; j < 4; j++)
192 res4[j] = ~src4[j] | dst4[j];
193 break;
194 case PIPE_LOGICOP_COPY:
195 for (j = 0; j < 4; j++)
196 res4[j] = src4[j];
197 break;
198 case PIPE_LOGICOP_OR_REVERSE:
199 for (j = 0; j < 4; j++)
200 res4[j] = src4[j] | ~dst4[j];
201 break;
202 case PIPE_LOGICOP_OR:
203 for (j = 0; j < 4; j++)
204 res4[j] = src4[j] | dst4[j];
205 break;
206 case PIPE_LOGICOP_SET:
207 for (j = 0; j < 4; j++)
208 res4[j] = ~0;
209 break;
210 default:
211 assert(0);
212 }
213
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]);
219 }
220 }
221
222
223
224 static void
225 blend_quad(struct quad_stage *qs,
226 float (*quadColor)[4],
227 float (*dest)[4])
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];
233
234 /*
235 * Compute src/first term RGB
236 */
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 */
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->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->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->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->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->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(struct quad_stage *qs,
715 float (*quadColor)[4],
716 float (*dest)[4])
717 {
718 struct softpipe_context *softpipe = qs->softpipe;
719
720 /* R */
721 if (!(softpipe->blend->colormask & PIPE_MASK_R))
722 COPY_4V(quadColor[0], dest[0]);
723
724 /* G */
725 if (!(softpipe->blend->colormask & PIPE_MASK_G))
726 COPY_4V(quadColor[1], dest[1]);
727
728 /* B */
729 if (!(softpipe->blend->colormask & PIPE_MASK_B))
730 COPY_4V(quadColor[2], dest[2]);
731
732 /* A */
733 if (!(softpipe->blend->colormask & PIPE_MASK_A))
734 COPY_4V(quadColor[3], dest[3]);
735 }
736
737
738 static void
739 blend_fallback(struct quad_stage *qs,
740 struct quad_header *quads[],
741 unsigned nr)
742 {
743 struct softpipe_context *softpipe = qs->softpipe;
744 const struct pipe_blend_state *blend = softpipe->blend;
745 unsigned cbuf;
746
747 for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
748 {
749 float dest[4][QUAD_SIZE];
750 struct softpipe_cached_tile *tile
751 = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
752 quads[0]->input.x0,
753 quads[0]->input.y0);
754 uint q, i, j;
755
756 for (q = 0; q < nr; q++) {
757 struct quad_header *quad = quads[q];
758 float (*quadColor)[4] = quad->output.color[cbuf];
759 const int itx = (quad->input.x0 & (TILE_SIZE-1));
760 const int ity = (quad->input.y0 & (TILE_SIZE-1));
761
762 /* get/swizzle dest colors
763 */
764 for (j = 0; j < QUAD_SIZE; j++) {
765 int x = itx + (j & 1);
766 int y = ity + (j >> 1);
767 for (i = 0; i < 4; i++) {
768 dest[i][j] = tile->data.color[y][x][i];
769 }
770 }
771
772
773 if (blend->logicop_enable) {
774 logicop_quad( qs, quadColor, dest );
775 }
776 else if (blend->blend_enable) {
777 blend_quad( qs, quadColor, dest );
778 }
779
780 if (blend->colormask != 0xf)
781 colormask_quad( qs, quadColor, dest );
782
783 /* Output color values
784 */
785 for (j = 0; j < QUAD_SIZE; j++) {
786 if (quad->inout.mask & (1 << j)) {
787 int x = itx + (j & 1);
788 int y = ity + (j >> 1);
789 for (i = 0; i < 4; i++) { /* loop over color chans */
790 tile->data.color[y][x][i] = quadColor[i][j];
791 }
792 }
793 }
794 }
795 }
796 }
797
798
799 static void
800 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
801 struct quad_header *quads[],
802 unsigned nr)
803 {
804 static const float one[4] = { 1, 1, 1, 1 };
805 float one_minus_alpha[QUAD_SIZE];
806 float dest[4][QUAD_SIZE];
807 float source[4][QUAD_SIZE];
808 uint i, j, q;
809
810 struct softpipe_cached_tile *tile
811 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
812 quads[0]->input.x0,
813 quads[0]->input.y0);
814
815 for (q = 0; q < nr; q++) {
816 struct quad_header *quad = quads[q];
817 float (*quadColor)[4] = quad->output.color[0];
818 const float *alpha = quadColor[3];
819 const int itx = (quad->input.x0 & (TILE_SIZE-1));
820 const int ity = (quad->input.y0 & (TILE_SIZE-1));
821
822 /* get/swizzle dest colors */
823 for (j = 0; j < QUAD_SIZE; j++) {
824 int x = itx + (j & 1);
825 int y = ity + (j >> 1);
826 for (i = 0; i < 4; i++) {
827 dest[i][j] = tile->data.color[y][x][i];
828 }
829 }
830
831 VEC4_MUL(source[0], quadColor[0], alpha); /* R */
832 VEC4_MUL(source[1], quadColor[1], alpha); /* G */
833 VEC4_MUL(source[2], quadColor[2], alpha); /* B */
834 VEC4_MUL(source[3], quadColor[3], alpha); /* A */
835
836 VEC4_SUB(one_minus_alpha, one, alpha);
837 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
838 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
839 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
840 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* B */
841
842 VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
843 VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
844 VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
845 VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
846
847 for (j = 0; j < QUAD_SIZE; j++) {
848 if (quad->inout.mask & (1 << j)) {
849 int x = itx + (j & 1);
850 int y = ity + (j >> 1);
851 for (i = 0; i < 4; i++) { /* loop over color chans */
852 tile->data.color[y][x][i] = quadColor[i][j];
853 }
854 }
855 }
856 }
857 }
858
859 static void
860 blend_single_add_one_one(struct quad_stage *qs,
861 struct quad_header *quads[],
862 unsigned nr)
863 {
864 float dest[4][QUAD_SIZE];
865 uint i, j, q;
866
867 struct softpipe_cached_tile *tile
868 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
869 quads[0]->input.x0,
870 quads[0]->input.y0);
871
872 for (q = 0; q < nr; q++) {
873 struct quad_header *quad = quads[q];
874 float (*quadColor)[4] = quad->output.color[0];
875 const int itx = (quad->input.x0 & (TILE_SIZE-1));
876 const int ity = (quad->input.y0 & (TILE_SIZE-1));
877
878 /* get/swizzle dest colors */
879 for (j = 0; j < QUAD_SIZE; j++) {
880 int x = itx + (j & 1);
881 int y = ity + (j >> 1);
882 for (i = 0; i < 4; i++) {
883 dest[i][j] = tile->data.color[y][x][i];
884 }
885 }
886
887 VEC4_ADD_SAT(quadColor[0], quadColor[0], dest[0]); /* R */
888 VEC4_ADD_SAT(quadColor[1], quadColor[1], dest[1]); /* G */
889 VEC4_ADD_SAT(quadColor[2], quadColor[2], dest[2]); /* B */
890 VEC4_ADD_SAT(quadColor[3], quadColor[3], dest[3]); /* A */
891
892 for (j = 0; j < QUAD_SIZE; j++) {
893 if (quad->inout.mask & (1 << j)) {
894 int x = itx + (j & 1);
895 int y = ity + (j >> 1);
896 for (i = 0; i < 4; i++) { /* loop over color chans */
897 tile->data.color[y][x][i] = quadColor[i][j];
898 }
899 }
900 }
901 }
902 }
903
904
905 static void
906 single_output_color(struct quad_stage *qs,
907 struct quad_header *quads[],
908 unsigned nr)
909 {
910 uint i, j, q;
911
912 struct softpipe_cached_tile *tile
913 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
914 quads[0]->input.x0,
915 quads[0]->input.y0);
916
917 for (q = 0; q < nr; q++) {
918 struct quad_header *quad = quads[q];
919 float (*quadColor)[4] = quad->output.color[0];
920 const int itx = (quad->input.x0 & (TILE_SIZE-1));
921 const int ity = (quad->input.y0 & (TILE_SIZE-1));
922
923 for (j = 0; j < QUAD_SIZE; j++) {
924 if (quad->inout.mask & (1 << j)) {
925 int x = itx + (j & 1);
926 int y = ity + (j >> 1);
927 for (i = 0; i < 4; i++) { /* loop over color chans */
928 tile->data.color[y][x][i] = quadColor[i][j];
929 }
930 }
931 }
932 }
933 }
934
935 static void
936 blend_noop(struct quad_stage *qs,
937 struct quad_header *quads[],
938 unsigned nr)
939 {
940 }
941
942
943 static void
944 choose_blend_quad(struct quad_stage *qs,
945 struct quad_header *quads[],
946 unsigned nr)
947 {
948 struct softpipe_context *softpipe = qs->softpipe;
949 const struct pipe_blend_state *blend = softpipe->blend;
950
951 qs->run = blend_fallback;
952
953 if (softpipe->framebuffer.nr_cbufs == 0) {
954 qs->run = blend_noop;
955 }
956 else if (!softpipe->blend->logicop_enable &&
957 softpipe->blend->colormask == 0xf &&
958 softpipe->framebuffer.nr_cbufs == 1)
959 {
960 if (!blend->blend_enable) {
961 qs->run = single_output_color;
962 }
963 else if (blend->rgb_src_factor == blend->alpha_src_factor &&
964 blend->rgb_dst_factor == blend->alpha_dst_factor &&
965 blend->rgb_func == blend->alpha_func)
966 {
967 if (blend->alpha_func == PIPE_BLEND_ADD) {
968 if (blend->rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
969 blend->rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {
970 qs->run = blend_single_add_one_one;
971 }
972 else if (blend->rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&
973 blend->rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
974 qs->run = blend_single_add_src_alpha_inv_src_alpha;
975
976 }
977 }
978 }
979
980 qs->run(qs, quads, nr);
981 }
982
983
984 static void blend_begin(struct quad_stage *qs)
985 {
986 qs->run = choose_blend_quad;
987 }
988
989
990 static void blend_destroy(struct quad_stage *qs)
991 {
992 FREE( qs );
993 }
994
995
996 struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
997 {
998 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
999
1000 stage->softpipe = softpipe;
1001 stage->begin = blend_begin;
1002 stage->run = choose_blend_quad;
1003 stage->destroy = blend_destroy;
1004
1005 return stage;
1006 }