sp_quad_blend.c revision b642730be93149baa7556e5791393168ab396175
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   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
221static void
222blend_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      abort();
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      abort();
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      abort();
720   }
721
722   /* pass blended quad to next stage */
723   qs->next->run(qs->next, quad);
724}
725
726
727static void blend_begin(struct quad_stage *qs)
728{
729   qs->next->begin(qs->next);
730}
731
732
733static void blend_destroy(struct quad_stage *qs)
734{
735   FREE( qs );
736}
737
738
739struct 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}
750