Merge branch 'master' into r300-compiler
[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 assert(0); /* illegal */
482 break;
483 case PIPE_BLENDFACTOR_CONST_COLOR:
484 {
485 float comp[4];
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 */
492 }
493 break;
494 case PIPE_BLENDFACTOR_CONST_ALPHA:
495 {
496 float comp[4];
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 */
501 }
502 break;
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 */
507 break;
508 case PIPE_BLENDFACTOR_SRC1_COLOR:
509 case PIPE_BLENDFACTOR_SRC1_ALPHA:
510 /* XXX what are these? */
511 assert(0);
512 break;
513 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
514 {
515 float inv_comp[4];
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 */
522 }
523 break;
524 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
525 {
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 */
531 }
532 break;
533 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
534 {
535 float inv_comp[4];
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 */
540 }
541 break;
542 case PIPE_BLENDFACTOR_INV_DST_COLOR:
543 {
544 float inv_comp[4];
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 */
551 }
552 break;
553 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
554 {
555 float inv_comp[4];
556 /* R */
557 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
558 VEC4_MUL(dest[0], dest[0], inv_comp);
559 /* G */
560 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
561 VEC4_MUL(dest[1], dest[1], inv_comp);
562 /* B */
563 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
564 VEC4_MUL(dest[2], dest[2], inv_comp);
565 }
566 break;
567 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
568 {
569 float inv_comp[4];
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);
574 }
575 break;
576 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
577 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
578 /* XXX what are these? */
579 assert(0);
580 break;
581 default:
582 assert(0);
583 }
584
585 /*
586 * Compute dest/second term A
587 */
588 switch (softpipe->blend->alpha_dst_factor) {
589 case PIPE_BLENDFACTOR_ONE:
590 /* dest = dest * 1 NO-OP, leave dest as-is */
591 break;
592 case PIPE_BLENDFACTOR_SRC_COLOR:
593 /* fall-through */
594 case PIPE_BLENDFACTOR_SRC_ALPHA:
595 VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
596 break;
597 case PIPE_BLENDFACTOR_DST_COLOR:
598 /* fall-through */
599 case PIPE_BLENDFACTOR_DST_ALPHA:
600 VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
601 break;
602 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
603 assert(0); /* illegal */
604 break;
605 case PIPE_BLENDFACTOR_CONST_COLOR:
606 /* fall-through */
607 case PIPE_BLENDFACTOR_CONST_ALPHA:
608 {
609 float comp[4];
610 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
611 VEC4_MUL(dest[3], dest[3], comp); /* A */
612 }
613 break;
614 case PIPE_BLENDFACTOR_ZERO:
615 VEC4_COPY(dest[3], zero); /* A */
616 break;
617 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
618 /* fall-through */
619 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
620 {
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 */
624 }
625 break;
626 case PIPE_BLENDFACTOR_INV_DST_COLOR:
627 /* fall-through */
628 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
629 {
630 float inv_comp[4];
631 VEC4_SUB(inv_comp, one, dest[3]); /* A */
632 VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
633 }
634 break;
635 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
636 /* fall-through */
637 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
638 {
639 float inv_comp[4];
640 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
641 VEC4_MUL(dest[3], dest[3], inv_comp);
642 }
643 break;
644 default:
645 assert(0);
646 }
647
648 /*
649 * Combine RGB terms
650 */
651 switch (softpipe->blend->rgb_func) {
652 case PIPE_BLEND_ADD:
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 */
656 break;
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 */
661 break;
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 */
666 break;
667 case PIPE_BLEND_MIN:
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 */
671 break;
672 case PIPE_BLEND_MAX:
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 */
676 break;
677 default:
678 assert(0);
679 }
680
681 /*
682 * Combine A terms
683 */
684 switch (softpipe->blend->alpha_func) {
685 case PIPE_BLEND_ADD:
686 VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
687 break;
688 case PIPE_BLEND_SUBTRACT:
689 VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
690 break;
691 case PIPE_BLEND_REVERSE_SUBTRACT:
692 VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
693 break;
694 case PIPE_BLEND_MIN:
695 VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
696 break;
697 case PIPE_BLEND_MAX:
698 VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
699 break;
700 default:
701 assert(0);
702 }
703 }
704
705 static void
706 colormask_quad(struct quad_stage *qs,
707 float (*quadColor)[4],
708 float (*dest)[4])
709 {
710 struct softpipe_context *softpipe = qs->softpipe;
711
712 /* R */
713 if (!(softpipe->blend->colormask & PIPE_MASK_R))
714 COPY_4V(quadColor[0], dest[0]);
715
716 /* G */
717 if (!(softpipe->blend->colormask & PIPE_MASK_G))
718 COPY_4V(quadColor[1], dest[1]);
719
720 /* B */
721 if (!(softpipe->blend->colormask & PIPE_MASK_B))
722 COPY_4V(quadColor[2], dest[2]);
723
724 /* A */
725 if (!(softpipe->blend->colormask & PIPE_MASK_A))
726 COPY_4V(quadColor[3], dest[3]);
727 }
728
729
730 static void
731 blend_fallback(struct quad_stage *qs,
732 struct quad_header *quads[],
733 unsigned nr)
734 {
735 struct softpipe_context *softpipe = qs->softpipe;
736 const struct pipe_blend_state *blend = softpipe->blend;
737 unsigned cbuf;
738
739 for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
740 {
741 float dest[4][QUAD_SIZE];
742 struct softpipe_cached_tile *tile
743 = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
744 quads[0]->input.x0,
745 quads[0]->input.y0);
746 uint q, i, j;
747
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));
753
754 /* get/swizzle dest colors
755 */
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];
761 }
762 }
763
764
765 if (blend->logicop_enable) {
766 logicop_quad( qs, quadColor, dest );
767 }
768 else if (blend->blend_enable) {
769 blend_quad( qs, quadColor, dest );
770 }
771
772 if (blend->colormask != 0xf)
773 colormask_quad( qs, quadColor, dest );
774
775 /* Output color values
776 */
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];
783 }
784 }
785 }
786 }
787 }
788 }
789
790
791 static void
792 blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
793 struct quad_header *quads[],
794 unsigned nr)
795 {
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];
800 uint i, j, q;
801
802 struct softpipe_cached_tile *tile
803 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
804 quads[0]->input.x0,
805 quads[0]->input.y0);
806
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));
813
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];
820 }
821 }
822
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 */
827
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 */
833
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 */
838
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];
845 }
846 }
847 }
848 }
849 }
850
851 static void
852 blend_single_add_one_one(struct quad_stage *qs,
853 struct quad_header *quads[],
854 unsigned nr)
855 {
856 float dest[4][QUAD_SIZE];
857 uint i, j, q;
858
859 struct softpipe_cached_tile *tile
860 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
861 quads[0]->input.x0,
862 quads[0]->input.y0);
863
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));
869
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];
876 }
877 }
878
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 */
883
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];
890 }
891 }
892 }
893 }
894 }
895
896
897 static void
898 single_output_color(struct quad_stage *qs,
899 struct quad_header *quads[],
900 unsigned nr)
901 {
902 uint i, j, q;
903
904 struct softpipe_cached_tile *tile
905 = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
906 quads[0]->input.x0,
907 quads[0]->input.y0);
908
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));
914
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];
921 }
922 }
923 }
924 }
925 }
926
927 static void
928 blend_noop(struct quad_stage *qs,
929 struct quad_header *quads[],
930 unsigned nr)
931 {
932 }
933
934
935 static void
936 choose_blend_quad(struct quad_stage *qs,
937 struct quad_header *quads[],
938 unsigned nr)
939 {
940 struct softpipe_context *softpipe = qs->softpipe;
941 const struct pipe_blend_state *blend = softpipe->blend;
942
943 qs->run = blend_fallback;
944
945 if (softpipe->framebuffer.nr_cbufs == 0) {
946 qs->run = blend_noop;
947 }
948 else if (!softpipe->blend->logicop_enable &&
949 softpipe->blend->colormask == 0xf)
950 {
951 if (!blend->blend_enable) {
952 qs->run = single_output_color;
953 }
954 else if (blend->rgb_src_factor == blend->alpha_src_factor &&
955 blend->rgb_dst_factor == blend->alpha_dst_factor &&
956 blend->rgb_func == blend->alpha_func &&
957 softpipe->framebuffer.nr_cbufs == 1)
958 {
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;
963 }
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;
967
968 }
969 }
970 }
971
972 qs->run(qs, quads, nr);
973 }
974
975
976 static void blend_begin(struct quad_stage *qs)
977 {
978 qs->run = choose_blend_quad;
979 }
980
981
982 static void blend_destroy(struct quad_stage *qs)
983 {
984 FREE( qs );
985 }
986
987
988 struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
989 {
990 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
991
992 stage->softpipe = softpipe;
993 stage->begin = blend_begin;
994 stage->run = choose_blend_quad;
995 stage->destroy = blend_destroy;
996
997 return stage;
998 }