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