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