Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[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 "pipe/p_util.h"
35 #include "sp_context.h"
36 #include "sp_headers.h"
37 #include "sp_surface.h"
38 #include "sp_tile_cache.h"
39 #include "sp_quad.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 #define VEC4_MUL(R, A, B) \
75 do { \
76 R[0] = A[0] * B[0]; \
77 R[1] = A[1] * B[1]; \
78 R[2] = A[2] * B[2]; \
79 R[3] = A[3] * B[3]; \
80 } while (0)
81
82 #define VEC4_MIN(R, A, B) \
83 do { \
84 R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
85 R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
86 R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
87 R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
88 } while (0)
89
90 #define VEC4_MAX(R, A, B) \
91 do { \
92 R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
93 R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
94 R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
95 R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
96 } while (0)
97
98
99
100 static void
101 logicop_quad(struct quad_stage *qs, struct quad_header *quad)
102 {
103 struct softpipe_context *softpipe = qs->softpipe;
104 uint cbuf;
105
106 /* loop over colorbuffer outputs */
107 for (cbuf = 0; cbuf < softpipe->framebuffer.num_cbufs; cbuf++) {
108 float dest[4][QUAD_SIZE];
109 ubyte src[4][4], dst[4][4], res[4][4];
110 uint *src4 = (uint *) src;
111 uint *dst4 = (uint *) dst;
112 uint *res4 = (uint *) res;
113 struct softpipe_cached_tile *
114 tile = sp_get_cached_tile(softpipe,
115 softpipe->cbuf_cache[cbuf],
116 quad->x0, quad->y0);
117 float (*quadColor)[4] = quad->outputs.color[cbuf];
118 uint i, j;
119
120 /* get/swizzle dest colors */
121 for (j = 0; j < QUAD_SIZE; j++) {
122 int x = (quad->x0 & (TILE_SIZE-1)) + (j & 1);
123 int y = (quad->y0 & (TILE_SIZE-1)) + (j >> 1);
124 for (i = 0; i < 4; i++) {
125 dest[i][j] = tile->data.color[y][x][i];
126 }
127 }
128
129 /* convert to ubyte */
130 for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
131 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][0], dest[j][0]); /* P0 */
132 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][1], dest[j][1]); /* P1 */
133 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][2], dest[j][2]); /* P2 */
134 UNCLAMPED_FLOAT_TO_UBYTE(dst[j][3], dest[j][3]); /* P3 */
135
136 UNCLAMPED_FLOAT_TO_UBYTE(src[j][0], quadColor[j][0]); /* P0 */
137 UNCLAMPED_FLOAT_TO_UBYTE(src[j][1], quadColor[j][1]); /* P1 */
138 UNCLAMPED_FLOAT_TO_UBYTE(src[j][2], quadColor[j][2]); /* P2 */
139 UNCLAMPED_FLOAT_TO_UBYTE(src[j][3], quadColor[j][3]); /* P3 */
140 }
141
142 switch (softpipe->blend->logicop_func) {
143 case PIPE_LOGICOP_CLEAR:
144 for (j = 0; j < 4; j++)
145 res4[j] = 0;
146 break;
147 case PIPE_LOGICOP_NOR:
148 for (j = 0; j < 4; j++)
149 res4[j] = ~(src4[j] | dst4[j]);
150 break;
151 case PIPE_LOGICOP_AND_INVERTED:
152 for (j = 0; j < 4; j++)
153 res4[j] = ~src4[j] & dst4[j];
154 break;
155 case PIPE_LOGICOP_COPY_INVERTED:
156 for (j = 0; j < 4; j++)
157 res4[j] = ~src4[j];
158 break;
159 case PIPE_LOGICOP_AND_REVERSE:
160 for (j = 0; j < 4; j++)
161 res4[j] = src4[j] & ~dst4[j];
162 break;
163 case PIPE_LOGICOP_INVERT:
164 for (j = 0; j < 4; j++)
165 res4[j] = ~dst4[j];
166 break;
167 case PIPE_LOGICOP_XOR:
168 for (j = 0; j < 4; j++)
169 res4[j] = dst4[j] ^ src4[j];
170 break;
171 case PIPE_LOGICOP_NAND:
172 for (j = 0; j < 4; j++)
173 res4[j] = ~(src4[j] & dst4[j]);
174 break;
175 case PIPE_LOGICOP_AND:
176 for (j = 0; j < 4; j++)
177 res4[j] = src4[j] & dst4[j];
178 break;
179 case PIPE_LOGICOP_EQUIV:
180 for (j = 0; j < 4; j++)
181 res4[j] = ~(src4[j] ^ dst4[j]);
182 break;
183 case PIPE_LOGICOP_NOOP:
184 for (j = 0; j < 4; j++)
185 res4[j] = dst4[j];
186 break;
187 case PIPE_LOGICOP_OR_INVERTED:
188 for (j = 0; j < 4; j++)
189 res4[j] = ~src4[j] | dst4[j];
190 break;
191 case PIPE_LOGICOP_COPY:
192 for (j = 0; j < 4; j++)
193 res4[j] = src4[j];
194 break;
195 case PIPE_LOGICOP_OR_REVERSE:
196 for (j = 0; j < 4; j++)
197 res4[j] = src4[j] | ~dst4[j];
198 break;
199 case PIPE_LOGICOP_OR:
200 for (j = 0; j < 4; j++)
201 res4[j] = src4[j] | dst4[j];
202 break;
203 case PIPE_LOGICOP_SET:
204 for (j = 0; j < 4; j++)
205 res4[j] = ~0;
206 break;
207 default:
208 assert(0);
209 }
210
211 for (j = 0; j < 4; j++) {
212 quadColor[j][0] = UBYTE_TO_FLOAT(res[j][0]);
213 quadColor[j][1] = UBYTE_TO_FLOAT(res[j][1]);
214 quadColor[j][2] = UBYTE_TO_FLOAT(res[j][2]);
215 quadColor[j][3] = UBYTE_TO_FLOAT(res[j][3]);
216 }
217 }
218
219 /* pass quad to next stage */
220 qs->next->run(qs->next, quad);
221 }
222
223
224
225
226 static void
227 blend_quad(struct quad_stage *qs, struct quad_header *quad)
228 {
229 static const float zero[4] = { 0, 0, 0, 0 };
230 static const float one[4] = { 1, 1, 1, 1 };
231
232 struct softpipe_context *softpipe = qs->softpipe;
233 uint cbuf;
234
235 /* loop over colorbuffer outputs */
236 for (cbuf = 0; cbuf < softpipe->framebuffer.num_cbufs; cbuf++) {
237 float source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
238 struct softpipe_cached_tile *tile
239 = sp_get_cached_tile(softpipe,
240 softpipe->cbuf_cache[cbuf],
241 quad->x0, quad->y0);
242 float (*quadColor)[4] = quad->outputs.color[cbuf];
243 uint i, j;
244
245 if (softpipe->blend->logicop_enable) {
246 logicop_quad(qs, quad);
247 return;
248 }
249
250 /* get/swizzle dest colors */
251 for (j = 0; j < QUAD_SIZE; j++) {
252 int x = (quad->x0 & (TILE_SIZE-1)) + (j & 1);
253 int y = (quad->y0 & (TILE_SIZE-1)) + (j >> 1);
254 for (i = 0; i < 4; i++) {
255 dest[i][j] = tile->data.color[y][x][i];
256 }
257 }
258
259 /*
260 * Compute src/first term RGB
261 */
262 switch (softpipe->blend->rgb_src_factor) {
263 case PIPE_BLENDFACTOR_ONE:
264 VEC4_COPY(source[0], quadColor[0]); /* R */
265 VEC4_COPY(source[1], quadColor[1]); /* G */
266 VEC4_COPY(source[2], quadColor[2]); /* B */
267 break;
268 case PIPE_BLENDFACTOR_SRC_COLOR:
269 VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
270 VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
271 VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
272 break;
273 case PIPE_BLENDFACTOR_SRC_ALPHA:
274 {
275 const float *alpha = quadColor[3];
276 VEC4_MUL(source[0], quadColor[0], alpha); /* R */
277 VEC4_MUL(source[1], quadColor[1], alpha); /* G */
278 VEC4_MUL(source[2], quadColor[2], alpha); /* B */
279 }
280 break;
281 case PIPE_BLENDFACTOR_DST_COLOR:
282 VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
283 VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
284 VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
285 break;
286 case PIPE_BLENDFACTOR_DST_ALPHA:
287 {
288 const float *alpha = dest[3];
289 VEC4_MUL(source[0], quadColor[0], alpha); /* R */
290 VEC4_MUL(source[1], quadColor[1], alpha); /* G */
291 VEC4_MUL(source[2], quadColor[2], alpha); /* B */
292 }
293 break;
294 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
295 {
296 const float *alpha = quadColor[3];
297 float diff[4];
298 VEC4_SUB(diff, one, dest[3]);
299 VEC4_MIN(source[0], alpha, diff); /* R */
300 VEC4_MIN(source[1], alpha, diff); /* G */
301 VEC4_MIN(source[2], alpha, diff); /* B */
302 }
303 break;
304 case PIPE_BLENDFACTOR_CONST_COLOR:
305 {
306 float comp[4];
307 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
308 VEC4_MUL(source[0], quadColor[0], comp); /* R */
309 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
310 VEC4_MUL(source[1], quadColor[1], comp); /* G */
311 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
312 VEC4_MUL(source[2], quadColor[2], comp); /* B */
313 }
314 break;
315 case PIPE_BLENDFACTOR_CONST_ALPHA:
316 {
317 float alpha[4];
318 VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
319 VEC4_MUL(source[0], quadColor[0], alpha); /* R */
320 VEC4_MUL(source[1], quadColor[1], alpha); /* G */
321 VEC4_MUL(source[2], quadColor[2], alpha); /* B */
322 }
323 break;
324 case PIPE_BLENDFACTOR_SRC1_COLOR:
325 assert(0); /* to do */
326 break;
327 case PIPE_BLENDFACTOR_SRC1_ALPHA:
328 assert(0); /* to do */
329 break;
330 case PIPE_BLENDFACTOR_ZERO:
331 VEC4_COPY(source[0], zero); /* R */
332 VEC4_COPY(source[1], zero); /* G */
333 VEC4_COPY(source[2], zero); /* B */
334 break;
335 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
336 {
337 float inv_comp[4];
338 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
339 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
340 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
341 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
342 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
343 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
344 }
345 break;
346 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
347 {
348 float inv_alpha[4];
349 VEC4_SUB(inv_alpha, one, quadColor[3]);
350 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
351 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
352 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
353 }
354 break;
355 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
356 {
357 float inv_alpha[4];
358 VEC4_SUB(inv_alpha, one, dest[3]);
359 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
360 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
361 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
362 }
363 break;
364 case PIPE_BLENDFACTOR_INV_DST_COLOR:
365 {
366 float inv_comp[4];
367 VEC4_SUB(inv_comp, one, dest[0]); /* R */
368 VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
369 VEC4_SUB(inv_comp, one, dest[1]); /* G */
370 VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
371 VEC4_SUB(inv_comp, one, dest[2]); /* B */
372 VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
373 }
374 break;
375 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
376 {
377 float inv_comp[4];
378 /* R */
379 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
380 VEC4_MUL(source[0], quadColor[0], inv_comp);
381 /* G */
382 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
383 VEC4_MUL(source[1], quadColor[1], inv_comp);
384 /* B */
385 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
386 VEC4_MUL(source[2], quadColor[2], inv_comp);
387 }
388 break;
389 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
390 {
391 float inv_alpha[4];
392 VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]);
393 VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
394 VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
395 VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
396 }
397 break;
398 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
399 assert(0); /* to do */
400 break;
401 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
402 assert(0); /* to do */
403 break;
404 default:
405 assert(0);
406 }
407
408 /*
409 * Compute src/first term A
410 */
411 switch (softpipe->blend->alpha_src_factor) {
412 case PIPE_BLENDFACTOR_ONE:
413 VEC4_COPY(source[3], quadColor[3]); /* A */
414 break;
415 case PIPE_BLENDFACTOR_SRC_COLOR:
416 /* fall-through */
417 case PIPE_BLENDFACTOR_SRC_ALPHA:
418 {
419 const float *alpha = quadColor[3];
420 VEC4_MUL(source[3], quadColor[3], alpha); /* A */
421 }
422 break;
423 case PIPE_BLENDFACTOR_DST_COLOR:
424 /* fall-through */
425 case PIPE_BLENDFACTOR_DST_ALPHA:
426 VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
427 break;
428 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
429 {
430 const float *alpha = quadColor[3];
431 float diff[4];
432 VEC4_SUB(diff, one, dest[3]);
433 VEC4_MIN(source[3], alpha, diff); /* A */
434 }
435 break;
436 case PIPE_BLENDFACTOR_CONST_COLOR:
437 /* fall-through */
438 case PIPE_BLENDFACTOR_CONST_ALPHA:
439 {
440 float comp[4];
441 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
442 VEC4_MUL(source[3], quadColor[3], comp); /* A */
443 }
444 break;
445 case PIPE_BLENDFACTOR_ZERO:
446 VEC4_COPY(source[3], zero); /* A */
447 break;
448 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
449 /* fall-through */
450 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
451 {
452 float inv_alpha[4];
453 VEC4_SUB(inv_alpha, one, quadColor[3]);
454 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
455 }
456 break;
457 case PIPE_BLENDFACTOR_INV_DST_COLOR:
458 /* fall-through */
459 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
460 {
461 float inv_alpha[4];
462 VEC4_SUB(inv_alpha, one, dest[3]);
463 VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
464 }
465 break;
466 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
467 /* fall-through */
468 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
469 {
470 float inv_comp[4];
471 /* A */
472 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
473 VEC4_MUL(source[3], quadColor[3], inv_comp);
474 }
475 break;
476 default:
477 assert(0);
478 }
479
480
481 /*
482 * Compute dest/second term RGB
483 */
484 switch (softpipe->blend->rgb_dst_factor) {
485 case PIPE_BLENDFACTOR_ONE:
486 /* dest = dest * 1 NO-OP, leave dest as-is */
487 break;
488 case PIPE_BLENDFACTOR_SRC_COLOR:
489 VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
490 VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
491 VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
492 break;
493 case PIPE_BLENDFACTOR_SRC_ALPHA:
494 VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
495 VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
496 VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
497 break;
498 case PIPE_BLENDFACTOR_DST_ALPHA:
499 VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
500 VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
501 VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
502 break;
503 case PIPE_BLENDFACTOR_DST_COLOR:
504 VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
505 VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
506 VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
507 break;
508 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
509 assert(0); /* illegal */
510 break;
511 case PIPE_BLENDFACTOR_CONST_COLOR:
512 {
513 float comp[4];
514 VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
515 VEC4_MUL(dest[0], dest[0], comp); /* R */
516 VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
517 VEC4_MUL(dest[1], dest[1], comp); /* G */
518 VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
519 VEC4_MUL(dest[2], dest[2], comp); /* B */
520 }
521 break;
522 case PIPE_BLENDFACTOR_CONST_ALPHA:
523 {
524 float comp[4];
525 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
526 VEC4_MUL(dest[0], dest[0], comp); /* R */
527 VEC4_MUL(dest[1], dest[1], comp); /* G */
528 VEC4_MUL(dest[2], dest[2], comp); /* B */
529 }
530 break;
531 case PIPE_BLENDFACTOR_ZERO:
532 VEC4_COPY(dest[0], zero); /* R */
533 VEC4_COPY(dest[1], zero); /* G */
534 VEC4_COPY(dest[2], zero); /* B */
535 break;
536 case PIPE_BLENDFACTOR_SRC1_COLOR:
537 case PIPE_BLENDFACTOR_SRC1_ALPHA:
538 /* XXX what are these? */
539 assert(0);
540 break;
541 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
542 {
543 float inv_comp[4];
544 VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
545 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
546 VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
547 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
548 VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
549 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
550 }
551 break;
552 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
553 {
554 float one_minus_alpha[QUAD_SIZE];
555 VEC4_SUB(one_minus_alpha, one, quadColor[3]);
556 VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
557 VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
558 VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
559 }
560 break;
561 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
562 {
563 float inv_comp[4];
564 VEC4_SUB(inv_comp, one, dest[3]); /* A */
565 VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
566 VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
567 VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
568 }
569 break;
570 case PIPE_BLENDFACTOR_INV_DST_COLOR:
571 {
572 float inv_comp[4];
573 VEC4_SUB(inv_comp, one, dest[0]); /* R */
574 VEC4_MUL(dest[0], dest[0], inv_comp); /* R */
575 VEC4_SUB(inv_comp, one, dest[1]); /* G */
576 VEC4_MUL(dest[1], dest[1], inv_comp); /* G */
577 VEC4_SUB(inv_comp, one, dest[2]); /* B */
578 VEC4_MUL(dest[2], dest[2], inv_comp); /* B */
579 }
580 break;
581 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
582 {
583 float inv_comp[4];
584 /* R */
585 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
586 VEC4_MUL(dest[0], dest[0], inv_comp);
587 /* G */
588 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
589 VEC4_MUL(dest[1], dest[1], inv_comp);
590 /* B */
591 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
592 VEC4_MUL(dest[2], dest[2], inv_comp);
593 }
594 break;
595 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
596 {
597 float inv_comp[4];
598 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
599 VEC4_MUL(dest[0], dest[0], inv_comp);
600 VEC4_MUL(dest[1], dest[1], inv_comp);
601 VEC4_MUL(dest[2], dest[2], inv_comp);
602 }
603 break;
604 case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
605 case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
606 /* XXX what are these? */
607 assert(0);
608 break;
609 default:
610 assert(0);
611 }
612
613 /*
614 * Compute dest/second term A
615 */
616 switch (softpipe->blend->alpha_dst_factor) {
617 case PIPE_BLENDFACTOR_ONE:
618 /* dest = dest * 1 NO-OP, leave dest as-is */
619 break;
620 case PIPE_BLENDFACTOR_SRC_COLOR:
621 /* fall-through */
622 case PIPE_BLENDFACTOR_SRC_ALPHA:
623 VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
624 break;
625 case PIPE_BLENDFACTOR_DST_COLOR:
626 /* fall-through */
627 case PIPE_BLENDFACTOR_DST_ALPHA:
628 VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
629 break;
630 case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
631 assert(0); /* illegal */
632 break;
633 case PIPE_BLENDFACTOR_CONST_COLOR:
634 /* fall-through */
635 case PIPE_BLENDFACTOR_CONST_ALPHA:
636 {
637 float comp[4];
638 VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
639 VEC4_MUL(dest[3], dest[3], comp); /* A */
640 }
641 break;
642 case PIPE_BLENDFACTOR_ZERO:
643 VEC4_COPY(dest[3], zero); /* A */
644 break;
645 case PIPE_BLENDFACTOR_INV_SRC_COLOR:
646 /* fall-through */
647 case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
648 {
649 float one_minus_alpha[QUAD_SIZE];
650 VEC4_SUB(one_minus_alpha, one, quadColor[3]);
651 VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
652 }
653 break;
654 case PIPE_BLENDFACTOR_INV_DST_COLOR:
655 /* fall-through */
656 case PIPE_BLENDFACTOR_INV_DST_ALPHA:
657 {
658 float inv_comp[4];
659 VEC4_SUB(inv_comp, one, dest[3]); /* A */
660 VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
661 }
662 break;
663 case PIPE_BLENDFACTOR_INV_CONST_COLOR:
664 /* fall-through */
665 case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
666 {
667 float inv_comp[4];
668 VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
669 VEC4_MUL(dest[3], dest[3], inv_comp);
670 }
671 break;
672 default:
673 assert(0);
674 }
675
676 /*
677 * Combine RGB terms
678 */
679 switch (softpipe->blend->rgb_func) {
680 case PIPE_BLEND_ADD:
681 VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */
682 VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */
683 VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */
684 break;
685 case PIPE_BLEND_SUBTRACT:
686 VEC4_SUB(quadColor[0], source[0], dest[0]); /* R */
687 VEC4_SUB(quadColor[1], source[1], dest[1]); /* G */
688 VEC4_SUB(quadColor[2], source[2], dest[2]); /* B */
689 break;
690 case PIPE_BLEND_REVERSE_SUBTRACT:
691 VEC4_SUB(quadColor[0], dest[0], source[0]); /* R */
692 VEC4_SUB(quadColor[1], dest[1], source[1]); /* G */
693 VEC4_SUB(quadColor[2], dest[2], source[2]); /* B */
694 break;
695 case PIPE_BLEND_MIN:
696 VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
697 VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
698 VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
699 break;
700 case PIPE_BLEND_MAX:
701 VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
702 VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
703 VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
704 break;
705 default:
706 assert(0);
707 }
708
709 /*
710 * Combine A terms
711 */
712 switch (softpipe->blend->alpha_func) {
713 case PIPE_BLEND_ADD:
714 VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */
715 break;
716 case PIPE_BLEND_SUBTRACT:
717 VEC4_SUB(quadColor[3], source[3], dest[3]); /* A */
718 break;
719 case PIPE_BLEND_REVERSE_SUBTRACT:
720 VEC4_SUB(quadColor[3], dest[3], source[3]); /* A */
721 break;
722 case PIPE_BLEND_MIN:
723 VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
724 break;
725 case PIPE_BLEND_MAX:
726 VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
727 break;
728 default:
729 assert(0);
730 }
731
732 } /* cbuf loop */
733
734 /* pass blended quad to next stage */
735 qs->next->run(qs->next, quad);
736 }
737
738
739 static void blend_begin(struct quad_stage *qs)
740 {
741 qs->next->begin(qs->next);
742 }
743
744
745 static void blend_destroy(struct quad_stage *qs)
746 {
747 FREE( qs );
748 }
749
750
751 struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
752 {
753 struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
754
755 stage->softpipe = softpipe;
756 stage->begin = blend_begin;
757 stage->run = blend_quad;
758 stage->destroy = blend_destroy;
759
760 return stage;
761 }