sp_quad_blend.c revision f7e475280a0b98484a8c1a98f18b2733532486b4
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) \
43do { \
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) \
51do { \
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) \
59do { \
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) \
67do { \
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) \
75do { \
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) \
83do { \
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) \
91do { \
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
100static void
101logicop_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
226static void
227blend_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
739static void blend_begin(struct quad_stage *qs)
740{
741   qs->next->begin(qs->next);
742}
743
744
745static void blend_destroy(struct quad_stage *qs)
746{
747   FREE( qs );
748}
749
750
751struct 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}
762