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