sp_quad_blend.c revision 0fe2b397bbee346f72f48f364a78459e5a54c534
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 "util/u_format.h"
37#include "sp_context.h"
38#include "sp_state.h"
39#include "sp_quad.h"
40#include "sp_tile_cache.h"
41#include "sp_quad_pipe.h"
42
43
44enum format
45{
46   RGBA,
47   RGB,
48   LUMINANCE,
49   LUMINANCE_ALPHA,
50   INTENSITY
51};
52
53
54/** Subclass of quad_stage */
55struct blend_quad_stage
56{
57   struct quad_stage base;
58   boolean clamp[PIPE_MAX_COLOR_BUFS];  /**< clamp colors to [0,1]? */
59   enum format base_format[PIPE_MAX_COLOR_BUFS];
60   enum util_format_type format_type[PIPE_MAX_COLOR_BUFS];
61};
62
63
64/** cast wrapper */
65static INLINE struct blend_quad_stage *
66blend_quad_stage(struct quad_stage *stage)
67{
68   return (struct blend_quad_stage *) stage;
69}
70
71
72#define VEC4_COPY(DST, SRC) \
73do { \
74    DST[0] = SRC[0]; \
75    DST[1] = SRC[1]; \
76    DST[2] = SRC[2]; \
77    DST[3] = SRC[3]; \
78} while(0)
79
80#define VEC4_SCALAR(DST, SRC) \
81do { \
82    DST[0] = SRC; \
83    DST[1] = SRC; \
84    DST[2] = SRC; \
85    DST[3] = SRC; \
86} while(0)
87
88#define VEC4_ADD(R, A, B) \
89do { \
90   R[0] = A[0] + B[0]; \
91   R[1] = A[1] + B[1]; \
92   R[2] = A[2] + B[2]; \
93   R[3] = A[3] + B[3]; \
94} while (0)
95
96#define VEC4_SUB(R, A, B) \
97do { \
98   R[0] = A[0] - B[0]; \
99   R[1] = A[1] - B[1]; \
100   R[2] = A[2] - B[2]; \
101   R[3] = A[3] - B[3]; \
102} while (0)
103
104/** Add and limit result to ceiling of 1.0 */
105#define VEC4_ADD_SAT(R, A, B) \
106do { \
107   R[0] = A[0] + B[0];  if (R[0] > 1.0f) R[0] = 1.0f; \
108   R[1] = A[1] + B[1];  if (R[1] > 1.0f) R[1] = 1.0f; \
109   R[2] = A[2] + B[2];  if (R[2] > 1.0f) R[2] = 1.0f; \
110   R[3] = A[3] + B[3];  if (R[3] > 1.0f) R[3] = 1.0f; \
111} while (0)
112
113/** Subtract and limit result to floor of 0.0 */
114#define VEC4_SUB_SAT(R, A, B) \
115do { \
116   R[0] = A[0] - B[0];  if (R[0] < 0.0f) R[0] = 0.0f; \
117   R[1] = A[1] - B[1];  if (R[1] < 0.0f) R[1] = 0.0f; \
118   R[2] = A[2] - B[2];  if (R[2] < 0.0f) R[2] = 0.0f; \
119   R[3] = A[3] - B[3];  if (R[3] < 0.0f) R[3] = 0.0f; \
120} while (0)
121
122#define VEC4_MUL(R, A, B) \
123do { \
124   R[0] = A[0] * B[0]; \
125   R[1] = A[1] * B[1]; \
126   R[2] = A[2] * B[2]; \
127   R[3] = A[3] * B[3]; \
128} while (0)
129
130#define VEC4_MIN(R, A, B) \
131do { \
132   R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
133   R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
134   R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
135   R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
136} while (0)
137
138#define VEC4_MAX(R, A, B) \
139do { \
140   R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
141   R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
142   R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
143   R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
144} while (0)
145
146
147
148static void
149logicop_quad(struct quad_stage *qs,
150             float (*quadColor)[4],
151             float (*dest)[4])
152{
153   struct softpipe_context *softpipe = qs->softpipe;
154   ubyte src[4][4], dst[4][4], res[4][4];
155   uint *src4 = (uint *) src;
156   uint *dst4 = (uint *) dst;
157   uint *res4 = (uint *) res;
158   uint j;
159
160
161   /* convert to ubyte */
162   for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
163      dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
164      dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
165      dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
166      dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
167
168      src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
169      src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
170      src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
171      src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
172   }
173
174   switch (softpipe->blend->logicop_func) {
175   case PIPE_LOGICOP_CLEAR:
176      for (j = 0; j < 4; j++)
177         res4[j] = 0;
178      break;
179   case PIPE_LOGICOP_NOR:
180      for (j = 0; j < 4; j++)
181         res4[j] = ~(src4[j] | dst4[j]);
182      break;
183   case PIPE_LOGICOP_AND_INVERTED:
184      for (j = 0; j < 4; j++)
185         res4[j] = ~src4[j] & dst4[j];
186      break;
187   case PIPE_LOGICOP_COPY_INVERTED:
188      for (j = 0; j < 4; j++)
189         res4[j] = ~src4[j];
190      break;
191   case PIPE_LOGICOP_AND_REVERSE:
192      for (j = 0; j < 4; j++)
193         res4[j] = src4[j] & ~dst4[j];
194      break;
195   case PIPE_LOGICOP_INVERT:
196      for (j = 0; j < 4; j++)
197         res4[j] = ~dst4[j];
198      break;
199   case PIPE_LOGICOP_XOR:
200      for (j = 0; j < 4; j++)
201         res4[j] = dst4[j] ^ src4[j];
202      break;
203   case PIPE_LOGICOP_NAND:
204      for (j = 0; j < 4; j++)
205         res4[j] = ~(src4[j] & dst4[j]);
206      break;
207   case PIPE_LOGICOP_AND:
208      for (j = 0; j < 4; j++)
209         res4[j] = src4[j] & dst4[j];
210      break;
211   case PIPE_LOGICOP_EQUIV:
212      for (j = 0; j < 4; j++)
213         res4[j] = ~(src4[j] ^ dst4[j]);
214      break;
215   case PIPE_LOGICOP_NOOP:
216      for (j = 0; j < 4; j++)
217         res4[j] = dst4[j];
218      break;
219   case PIPE_LOGICOP_OR_INVERTED:
220      for (j = 0; j < 4; j++)
221         res4[j] = ~src4[j] | dst4[j];
222      break;
223   case PIPE_LOGICOP_COPY:
224      for (j = 0; j < 4; j++)
225         res4[j] = src4[j];
226      break;
227   case PIPE_LOGICOP_OR_REVERSE:
228      for (j = 0; j < 4; j++)
229         res4[j] = src4[j] | ~dst4[j];
230      break;
231   case PIPE_LOGICOP_OR:
232      for (j = 0; j < 4; j++)
233         res4[j] = src4[j] | dst4[j];
234      break;
235   case PIPE_LOGICOP_SET:
236      for (j = 0; j < 4; j++)
237         res4[j] = ~0;
238      break;
239   default:
240      assert(0 && "invalid logicop mode");
241   }
242
243   for (j = 0; j < 4; j++) {
244      quadColor[j][0] = ubyte_to_float(res[j][0]);
245      quadColor[j][1] = ubyte_to_float(res[j][1]);
246      quadColor[j][2] = ubyte_to_float(res[j][2]);
247      quadColor[j][3] = ubyte_to_float(res[j][3]);
248   }
249}
250
251
252
253/**
254 * Do blending for a 2x2 quad for one color buffer.
255 * \param quadColor  the incoming quad colors
256 * \param dest  the destination/framebuffer quad colors
257 * \param const_blend_color  the constant blend color
258 * \param blend_index  which set of blending terms to use
259 */
260static void
261blend_quad(struct quad_stage *qs,
262           float (*quadColor)[4],
263           float (*dest)[4],
264           const float const_blend_color[4],
265           unsigned blend_index)
266{
267   static const float zero[4] = { 0, 0, 0, 0 };
268   static const float one[4] = { 1, 1, 1, 1 };
269   struct softpipe_context *softpipe = qs->softpipe;
270   float source[4][QUAD_SIZE] = { { 0 } };
271   float blend_dest[4][QUAD_SIZE];
272
273   /*
274    * Compute src/first term RGB
275    */
276   switch (softpipe->blend->rt[blend_index].rgb_src_factor) {
277   case PIPE_BLENDFACTOR_ONE:
278      VEC4_COPY(source[0], quadColor[0]); /* R */
279      VEC4_COPY(source[1], quadColor[1]); /* G */
280      VEC4_COPY(source[2], quadColor[2]); /* B */
281      break;
282   case PIPE_BLENDFACTOR_SRC_COLOR:
283      VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
284      VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
285      VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
286      break;
287   case PIPE_BLENDFACTOR_SRC_ALPHA:
288      {
289         const float *alpha = quadColor[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_DST_COLOR:
296      VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
297      VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
298      VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
299      break;
300   case PIPE_BLENDFACTOR_DST_ALPHA:
301      {
302         const float *alpha = dest[3];
303         VEC4_MUL(source[0], quadColor[0], alpha); /* R */
304         VEC4_MUL(source[1], quadColor[1], alpha); /* G */
305         VEC4_MUL(source[2], quadColor[2], alpha); /* B */
306      }
307      break;
308   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
309      {
310         const float *alpha = quadColor[3];
311         float diff[4], temp[4];
312         VEC4_SUB(diff, one, dest[3]);
313         VEC4_MIN(temp, alpha, diff);
314         VEC4_MUL(source[0], quadColor[0], temp); /* R */
315         VEC4_MUL(source[1], quadColor[1], temp); /* G */
316         VEC4_MUL(source[2], quadColor[2], temp); /* B */
317      }
318      break;
319   case PIPE_BLENDFACTOR_CONST_COLOR:
320      {
321         float comp[4];
322         VEC4_SCALAR(comp, const_blend_color[0]); /* R */
323         VEC4_MUL(source[0], quadColor[0], comp); /* R */
324         VEC4_SCALAR(comp, const_blend_color[1]); /* G */
325         VEC4_MUL(source[1], quadColor[1], comp); /* G */
326         VEC4_SCALAR(comp, const_blend_color[2]); /* B */
327         VEC4_MUL(source[2], quadColor[2], comp); /* B */
328      }
329      break;
330   case PIPE_BLENDFACTOR_CONST_ALPHA:
331      {
332         float alpha[4];
333         VEC4_SCALAR(alpha, const_blend_color[3]);
334         VEC4_MUL(source[0], quadColor[0], alpha); /* R */
335         VEC4_MUL(source[1], quadColor[1], alpha); /* G */
336         VEC4_MUL(source[2], quadColor[2], alpha); /* B */
337      }
338      break;
339   case PIPE_BLENDFACTOR_SRC1_COLOR:
340      assert(0); /* to do */
341      break;
342   case PIPE_BLENDFACTOR_SRC1_ALPHA:
343      assert(0); /* to do */
344      break;
345   case PIPE_BLENDFACTOR_ZERO:
346      VEC4_COPY(source[0], zero); /* R */
347      VEC4_COPY(source[1], zero); /* G */
348      VEC4_COPY(source[2], zero); /* B */
349      break;
350   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
351      {
352         float inv_comp[4];
353         VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
354         VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
355         VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
356         VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
357         VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
358         VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
359      }
360      break;
361   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
362      {
363         float inv_alpha[4];
364         VEC4_SUB(inv_alpha, one, quadColor[3]);
365         VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
366         VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
367         VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
368      }
369      break;
370   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
371      {
372         float inv_alpha[4];
373         VEC4_SUB(inv_alpha, one, dest[3]);
374         VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
375         VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
376         VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
377      }
378      break;
379   case PIPE_BLENDFACTOR_INV_DST_COLOR:
380      {
381         float inv_comp[4];
382         VEC4_SUB(inv_comp, one, dest[0]); /* R */
383         VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
384         VEC4_SUB(inv_comp, one, dest[1]); /* G */
385         VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
386         VEC4_SUB(inv_comp, one, dest[2]); /* B */
387         VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
388      }
389      break;
390   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
391      {
392         float inv_comp[4];
393         /* R */
394         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
395         VEC4_MUL(source[0], quadColor[0], inv_comp);
396         /* G */
397         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
398         VEC4_MUL(source[1], quadColor[1], inv_comp);
399         /* B */
400         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
401         VEC4_MUL(source[2], quadColor[2], inv_comp);
402      }
403      break;
404   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
405      {
406         float inv_alpha[4];
407         VEC4_SCALAR(inv_alpha, 1.0f - const_blend_color[3]);
408         VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
409         VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
410         VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
411      }
412      break;
413   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
414      assert(0); /* to do */
415      break;
416   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
417      assert(0); /* to do */
418      break;
419   default:
420      assert(0 && "invalid rgb src factor");
421   }
422
423   /*
424    * Compute src/first term A
425    */
426   switch (softpipe->blend->rt[blend_index].alpha_src_factor) {
427   case PIPE_BLENDFACTOR_ONE:
428      VEC4_COPY(source[3], quadColor[3]); /* A */
429      break;
430   case PIPE_BLENDFACTOR_SRC_COLOR:
431      /* fall-through */
432   case PIPE_BLENDFACTOR_SRC_ALPHA:
433      {
434         const float *alpha = quadColor[3];
435         VEC4_MUL(source[3], quadColor[3], alpha); /* A */
436      }
437      break;
438   case PIPE_BLENDFACTOR_DST_COLOR:
439      /* fall-through */
440   case PIPE_BLENDFACTOR_DST_ALPHA:
441      VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
442      break;
443   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
444      /* multiply alpha by 1.0 */
445      VEC4_COPY(source[3], quadColor[3]); /* A */
446      break;
447   case PIPE_BLENDFACTOR_CONST_COLOR:
448      /* fall-through */
449   case PIPE_BLENDFACTOR_CONST_ALPHA:
450      {
451         float comp[4];
452         VEC4_SCALAR(comp, const_blend_color[3]); /* A */
453         VEC4_MUL(source[3], quadColor[3], comp); /* A */
454      }
455      break;
456   case PIPE_BLENDFACTOR_ZERO:
457      VEC4_COPY(source[3], zero); /* A */
458      break;
459   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
460      /* fall-through */
461   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
462      {
463         float inv_alpha[4];
464         VEC4_SUB(inv_alpha, one, quadColor[3]);
465         VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
466      }
467      break;
468   case PIPE_BLENDFACTOR_INV_DST_COLOR:
469      /* fall-through */
470   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
471      {
472         float inv_alpha[4];
473         VEC4_SUB(inv_alpha, one, dest[3]);
474         VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
475      }
476      break;
477   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
478      /* fall-through */
479   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
480      {
481         float inv_comp[4];
482         /* A */
483         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
484         VEC4_MUL(source[3], quadColor[3], inv_comp);
485      }
486      break;
487   default:
488      assert(0 && "invalid alpha src factor");
489   }
490
491   /* Save the original dest for use in masking */
492   VEC4_COPY(blend_dest[0], dest[0]);
493   VEC4_COPY(blend_dest[1], dest[1]);
494   VEC4_COPY(blend_dest[2], dest[2]);
495   VEC4_COPY(blend_dest[3], dest[3]);
496
497
498   /*
499    * Compute blend_dest/second term RGB
500    */
501   switch (softpipe->blend->rt[blend_index].rgb_dst_factor) {
502   case PIPE_BLENDFACTOR_ONE:
503      /* blend_dest = blend_dest * 1   NO-OP, leave blend_dest as-is */
504      break;
505   case PIPE_BLENDFACTOR_SRC_COLOR:
506      VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[0]); /* R */
507      VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[1]); /* G */
508      VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[2]); /* B */
509      break;
510   case PIPE_BLENDFACTOR_SRC_ALPHA:
511      VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[3]); /* R * A */
512      VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[3]); /* G * A */
513      VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[3]); /* B * A */
514      break;
515   case PIPE_BLENDFACTOR_DST_ALPHA:
516      VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[3]); /* R * A */
517      VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[3]); /* G * A */
518      VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[3]); /* B * A */
519      break;
520   case PIPE_BLENDFACTOR_DST_COLOR:
521      VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[0]); /* R */
522      VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[1]); /* G */
523      VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[2]); /* B */
524      break;
525   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
526      {
527         const float *alpha = quadColor[3];
528         float diff[4], temp[4];
529         VEC4_SUB(diff, one, blend_dest[3]);
530         VEC4_MIN(temp, alpha, diff);
531         VEC4_MUL(blend_dest[0], quadColor[0], temp); /* R */
532         VEC4_MUL(blend_dest[1], quadColor[1], temp); /* G */
533         VEC4_MUL(blend_dest[2], quadColor[2], temp); /* B */
534      }
535      break;
536   case PIPE_BLENDFACTOR_CONST_COLOR:
537      {
538         float comp[4];
539         VEC4_SCALAR(comp, const_blend_color[0]); /* R */
540         VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
541         VEC4_SCALAR(comp, const_blend_color[1]); /* G */
542         VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
543         VEC4_SCALAR(comp, const_blend_color[2]); /* B */
544         VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
545      }
546      break;
547   case PIPE_BLENDFACTOR_CONST_ALPHA:
548      {
549         float comp[4];
550         VEC4_SCALAR(comp, const_blend_color[3]); /* A */
551         VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
552         VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
553         VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
554      }
555      break;
556   case PIPE_BLENDFACTOR_ZERO:
557      VEC4_COPY(blend_dest[0], zero); /* R */
558      VEC4_COPY(blend_dest[1], zero); /* G */
559      VEC4_COPY(blend_dest[2], zero); /* B */
560      break;
561   case PIPE_BLENDFACTOR_SRC1_COLOR:
562   case PIPE_BLENDFACTOR_SRC1_ALPHA:
563      /* XXX what are these? */
564      assert(0);
565      break;
566   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
567      {
568         float inv_comp[4];
569         VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
570         VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
571         VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
572         VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
573         VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
574         VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
575      }
576      break;
577   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
578      {
579         float one_minus_alpha[QUAD_SIZE];
580         VEC4_SUB(one_minus_alpha, one, quadColor[3]);
581         VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */
582         VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */
583         VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */
584      }
585      break;
586   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
587      {
588         float inv_comp[4];
589         VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
590         VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
591         VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
592         VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
593      }
594      break;
595   case PIPE_BLENDFACTOR_INV_DST_COLOR:
596      {
597         float inv_comp[4];
598         VEC4_SUB(inv_comp, one, blend_dest[0]); /* R */
599         VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); /* R */
600         VEC4_SUB(inv_comp, one, blend_dest[1]); /* G */
601         VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); /* G */
602         VEC4_SUB(inv_comp, one, blend_dest[2]); /* B */
603         VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); /* B */
604      }
605      break;
606   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
607      {
608         float inv_comp[4];
609         /* R */
610         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
611         VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
612         /* G */
613         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
614         VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
615         /* B */
616         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
617         VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
618      }
619      break;
620   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
621      {
622         float inv_comp[4];
623         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
624         VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
625         VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
626         VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
627      }
628      break;
629   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
630   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
631      /* XXX what are these? */
632      assert(0);
633      break;
634   default:
635      assert(0 && "invalid rgb dst factor");
636   }
637
638   /*
639    * Compute blend_dest/second term A
640    */
641   switch (softpipe->blend->rt[blend_index].alpha_dst_factor) {
642   case PIPE_BLENDFACTOR_ONE:
643      /* blend_dest = blend_dest * 1   NO-OP, leave blend_dest as-is */
644      break;
645   case PIPE_BLENDFACTOR_SRC_COLOR:
646      /* fall-through */
647   case PIPE_BLENDFACTOR_SRC_ALPHA:
648      VEC4_MUL(blend_dest[3], blend_dest[3], quadColor[3]); /* A * A */
649      break;
650   case PIPE_BLENDFACTOR_DST_COLOR:
651      /* fall-through */
652   case PIPE_BLENDFACTOR_DST_ALPHA:
653      VEC4_MUL(blend_dest[3], blend_dest[3], blend_dest[3]); /* A */
654      break;
655   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
656      /* blend_dest = blend_dest * 1   NO-OP, leave blend_dest as-is */
657      break;
658   case PIPE_BLENDFACTOR_CONST_COLOR:
659      /* fall-through */
660   case PIPE_BLENDFACTOR_CONST_ALPHA:
661      {
662         float comp[4];
663         VEC4_SCALAR(comp, const_blend_color[3]); /* A */
664         VEC4_MUL(blend_dest[3], blend_dest[3], comp); /* A */
665      }
666      break;
667   case PIPE_BLENDFACTOR_ZERO:
668      VEC4_COPY(blend_dest[3], zero); /* A */
669      break;
670   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
671      /* fall-through */
672   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
673      {
674         float one_minus_alpha[QUAD_SIZE];
675         VEC4_SUB(one_minus_alpha, one, quadColor[3]);
676         VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */
677      }
678      break;
679   case PIPE_BLENDFACTOR_INV_DST_COLOR:
680      /* fall-through */
681   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
682      {
683         float inv_comp[4];
684         VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
685         VEC4_MUL(blend_dest[3], inv_comp, blend_dest[3]); /* A */
686      }
687      break;
688   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
689      /* fall-through */
690   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
691      {
692         float inv_comp[4];
693         VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
694         VEC4_MUL(blend_dest[3], blend_dest[3], inv_comp);
695      }
696      break;
697   default:
698      assert(0 && "invalid alpha dst factor");
699   }
700
701   /*
702    * Combine RGB terms
703    */
704   switch (softpipe->blend->rt[blend_index].rgb_func) {
705   case PIPE_BLEND_ADD:
706      VEC4_ADD(quadColor[0], source[0], blend_dest[0]); /* R */
707      VEC4_ADD(quadColor[1], source[1], blend_dest[1]); /* G */
708      VEC4_ADD(quadColor[2], source[2], blend_dest[2]); /* B */
709      break;
710   case PIPE_BLEND_SUBTRACT:
711      VEC4_SUB(quadColor[0], source[0], blend_dest[0]); /* R */
712      VEC4_SUB(quadColor[1], source[1], blend_dest[1]); /* G */
713      VEC4_SUB(quadColor[2], source[2], blend_dest[2]); /* B */
714      break;
715   case PIPE_BLEND_REVERSE_SUBTRACT:
716      VEC4_SUB(quadColor[0], blend_dest[0], source[0]); /* R */
717      VEC4_SUB(quadColor[1], blend_dest[1], source[1]); /* G */
718      VEC4_SUB(quadColor[2], blend_dest[2], source[2]); /* B */
719      break;
720   case PIPE_BLEND_MIN:
721      VEC4_MIN(quadColor[0], source[0], blend_dest[0]); /* R */
722      VEC4_MIN(quadColor[1], source[1], blend_dest[1]); /* G */
723      VEC4_MIN(quadColor[2], source[2], blend_dest[2]); /* B */
724      break;
725   case PIPE_BLEND_MAX:
726      VEC4_MAX(quadColor[0], source[0], blend_dest[0]); /* R */
727      VEC4_MAX(quadColor[1], source[1], blend_dest[1]); /* G */
728      VEC4_MAX(quadColor[2], source[2], blend_dest[2]); /* B */
729      break;
730   default:
731      assert(0 && "invalid rgb blend func");
732   }
733
734   /*
735    * Combine A terms
736    */
737   switch (softpipe->blend->rt[blend_index].alpha_func) {
738   case PIPE_BLEND_ADD:
739      VEC4_ADD(quadColor[3], source[3], blend_dest[3]); /* A */
740      break;
741   case PIPE_BLEND_SUBTRACT:
742      VEC4_SUB(quadColor[3], source[3], blend_dest[3]); /* A */
743      break;
744   case PIPE_BLEND_REVERSE_SUBTRACT:
745      VEC4_SUB(quadColor[3], blend_dest[3], source[3]); /* A */
746      break;
747   case PIPE_BLEND_MIN:
748      VEC4_MIN(quadColor[3], source[3], blend_dest[3]); /* A */
749      break;
750   case PIPE_BLEND_MAX:
751      VEC4_MAX(quadColor[3], source[3], blend_dest[3]); /* A */
752      break;
753   default:
754      assert(0 && "invalid alpha blend func");
755   }
756}
757
758static void
759colormask_quad(unsigned colormask,
760               float (*quadColor)[4],
761               float (*dest)[4])
762{
763   /* R */
764   if (!(colormask & PIPE_MASK_R))
765      COPY_4V(quadColor[0], dest[0]);
766
767   /* G */
768   if (!(colormask & PIPE_MASK_G))
769      COPY_4V(quadColor[1], dest[1]);
770
771   /* B */
772   if (!(colormask & PIPE_MASK_B))
773      COPY_4V(quadColor[2], dest[2]);
774
775   /* A */
776   if (!(colormask & PIPE_MASK_A))
777      COPY_4V(quadColor[3], dest[3]);
778}
779
780
781/**
782 * Clamp all colors in a quad to [0, 1]
783 */
784static void
785clamp_colors(float (*quadColor)[4])
786{
787   unsigned i, j;
788
789   for (j = 0; j < QUAD_SIZE; j++) {
790      for (i = 0; i < 4; i++) {
791         quadColor[i][j] = CLAMP(quadColor[i][j], 0.0F, 1.0F);
792      }
793   }
794}
795
796
797/**
798 * If we're drawing to a luminance, luminance/alpha or intensity surface
799 * we have to adjust (rebase) the fragment/quad colors before writing them
800 * to the tile cache.  The tile cache always stores RGBA colors but if
801 * we're caching a L/A surface (for example) we need to be sure that R=G=B
802 * so that subsequent reads from the surface cache appear to return L/A
803 * values.
804 * The piglit fbo-blending-formats test will exercise this.
805 */
806static void
807rebase_colors(enum format base_format, float (*quadColor)[4])
808{
809   unsigned i;
810
811   switch (base_format) {
812   case RGB:
813      for (i = 0; i < 4; i++) {
814         /* A = 1 */
815         quadColor[3][i] = 1.0F;
816      }
817      break;
818   case LUMINANCE:
819      for (i = 0; i < 4; i++) {
820         /* B = G = R */
821         quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
822         /* A = 1 */
823         quadColor[3][i] = 1.0F;
824      }
825      break;
826   case LUMINANCE_ALPHA:
827      for (i = 0; i < 4; i++) {
828         /* B = G = R */
829         quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
830      }
831      break;
832   case INTENSITY:
833      for (i = 0; i < 4; i++) {
834         /* A = B = G = R */
835         quadColor[3][i] = quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
836      }
837      break;
838   default:
839      ; /* nothing */
840   }
841}
842
843
844
845static void
846blend_fallback(struct quad_stage *qs,
847               struct quad_header *quads[],
848               unsigned nr)
849{
850   const struct blend_quad_stage *bqs = blend_quad_stage(qs);
851   struct softpipe_context *softpipe = qs->softpipe;
852   const struct pipe_blend_state *blend = softpipe->blend;
853   unsigned cbuf;
854   boolean write_all;
855
856   write_all = softpipe->fs_variant->info.color0_writes_all_cbufs;
857
858   for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
859   {
860      /* which blend/mask state index to use: */
861      const uint blend_buf = blend->independent_blend_enable ? cbuf : 0;
862      float dest[4][QUAD_SIZE];
863      struct softpipe_cached_tile *tile
864         = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
865                              quads[0]->input.x0,
866                              quads[0]->input.y0);
867      const boolean clamp = bqs->clamp[cbuf];
868      const float *blend_color;
869      uint q, i, j;
870
871      if (clamp)
872         blend_color = softpipe->blend_color_clamped.color;
873      else
874         blend_color = softpipe->blend_color.color;
875
876      for (q = 0; q < nr; q++) {
877         struct quad_header *quad = quads[q];
878         float (*quadColor)[4];
879         float temp_quad_color[QUAD_SIZE][4];
880         const int itx = (quad->input.x0 & (TILE_SIZE-1));
881         const int ity = (quad->input.y0 & (TILE_SIZE-1));
882
883         if (write_all) {
884            for (j = 0; j < QUAD_SIZE; j++) {
885               for (i = 0; i < 4; i++) {
886                  temp_quad_color[i][j] = quad->output.color[0][i][j];
887               }
888            }
889            quadColor = temp_quad_color;
890         } else {
891            quadColor = quad->output.color[cbuf];
892         }
893
894         /* If fixed-point dest color buffer, need to clamp the incoming
895          * fragment colors now.
896          */
897         if (clamp || softpipe->rasterizer->clamp_fragment_color) {
898            clamp_colors(quadColor);
899         }
900
901         /* get/swizzle dest colors
902          */
903         for (j = 0; j < QUAD_SIZE; j++) {
904            int x = itx + (j & 1);
905            int y = ity + (j >> 1);
906            for (i = 0; i < 4; i++) {
907               dest[i][j] = tile->data.color[y][x][i];
908            }
909         }
910
911
912         if (blend->logicop_enable) {
913            if (bqs->format_type[cbuf] != UTIL_FORMAT_TYPE_FLOAT) {
914               logicop_quad( qs, quadColor, dest );
915            }
916         }
917         else if (blend->rt[blend_buf].blend_enable) {
918            blend_quad(qs, quadColor, dest, blend_color, blend_buf);
919
920            /* If fixed-point dest color buffer, need to clamp the outgoing
921             * fragment colors now.
922             */
923            if (clamp) {
924               clamp_colors(quadColor);
925            }
926         }
927
928         rebase_colors(bqs->base_format[cbuf], quadColor);
929
930         if (blend->rt[blend_buf].colormask != 0xf)
931            colormask_quad( blend->rt[cbuf].colormask, quadColor, dest);
932
933         /* Output color values
934          */
935         for (j = 0; j < QUAD_SIZE; j++) {
936            if (quad->inout.mask & (1 << j)) {
937               int x = itx + (j & 1);
938               int y = ity + (j >> 1);
939               for (i = 0; i < 4; i++) { /* loop over color chans */
940                  tile->data.color[y][x][i] = quadColor[i][j];
941               }
942            }
943         }
944      }
945   }
946}
947
948
949static void
950blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
951                                         struct quad_header *quads[],
952                                         unsigned nr)
953{
954   const struct blend_quad_stage *bqs = blend_quad_stage(qs);
955   static const float one[4] = { 1, 1, 1, 1 };
956   float one_minus_alpha[QUAD_SIZE];
957   float dest[4][QUAD_SIZE];
958   float source[4][QUAD_SIZE];
959   uint i, j, q;
960
961   struct softpipe_cached_tile *tile
962      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
963                           quads[0]->input.x0,
964                           quads[0]->input.y0);
965
966   for (q = 0; q < nr; q++) {
967      struct quad_header *quad = quads[q];
968      float (*quadColor)[4] = quad->output.color[0];
969      const float *alpha = quadColor[3];
970      const int itx = (quad->input.x0 & (TILE_SIZE-1));
971      const int ity = (quad->input.y0 & (TILE_SIZE-1));
972
973      /* get/swizzle dest colors */
974      for (j = 0; j < QUAD_SIZE; j++) {
975         int x = itx + (j & 1);
976         int y = ity + (j >> 1);
977         for (i = 0; i < 4; i++) {
978            dest[i][j] = tile->data.color[y][x][i];
979         }
980      }
981
982      /* If fixed-point dest color buffer, need to clamp the incoming
983       * fragment colors now.
984       */
985      if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
986         clamp_colors(quadColor);
987      }
988
989      VEC4_MUL(source[0], quadColor[0], alpha); /* R */
990      VEC4_MUL(source[1], quadColor[1], alpha); /* G */
991      VEC4_MUL(source[2], quadColor[2], alpha); /* B */
992      VEC4_MUL(source[3], quadColor[3], alpha); /* A */
993
994      VEC4_SUB(one_minus_alpha, one, alpha);
995      VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
996      VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
997      VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
998      VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
999
1000      VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */
1001      VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */
1002      VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */
1003      VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */
1004
1005      /* If fixed-point dest color buffer, need to clamp the outgoing
1006       * fragment colors now.
1007       */
1008      if (bqs->clamp[0]) {
1009         clamp_colors(quadColor);
1010      }
1011
1012      rebase_colors(bqs->base_format[0], quadColor);
1013
1014      for (j = 0; j < QUAD_SIZE; j++) {
1015         if (quad->inout.mask & (1 << j)) {
1016            int x = itx + (j & 1);
1017            int y = ity + (j >> 1);
1018            for (i = 0; i < 4; i++) { /* loop over color chans */
1019               tile->data.color[y][x][i] = quadColor[i][j];
1020            }
1021         }
1022      }
1023   }
1024}
1025
1026static void
1027blend_single_add_one_one(struct quad_stage *qs,
1028                         struct quad_header *quads[],
1029                         unsigned nr)
1030{
1031   const struct blend_quad_stage *bqs = blend_quad_stage(qs);
1032   float dest[4][QUAD_SIZE];
1033   uint i, j, q;
1034
1035   struct softpipe_cached_tile *tile
1036      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
1037                           quads[0]->input.x0,
1038                           quads[0]->input.y0);
1039
1040   for (q = 0; q < nr; q++) {
1041      struct quad_header *quad = quads[q];
1042      float (*quadColor)[4] = quad->output.color[0];
1043      const int itx = (quad->input.x0 & (TILE_SIZE-1));
1044      const int ity = (quad->input.y0 & (TILE_SIZE-1));
1045
1046      /* get/swizzle dest colors */
1047      for (j = 0; j < QUAD_SIZE; j++) {
1048         int x = itx + (j & 1);
1049         int y = ity + (j >> 1);
1050         for (i = 0; i < 4; i++) {
1051            dest[i][j] = tile->data.color[y][x][i];
1052         }
1053      }
1054
1055      /* If fixed-point dest color buffer, need to clamp the incoming
1056       * fragment colors now.
1057       */
1058      if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
1059         clamp_colors(quadColor);
1060      }
1061
1062      VEC4_ADD(quadColor[0], quadColor[0], dest[0]); /* R */
1063      VEC4_ADD(quadColor[1], quadColor[1], dest[1]); /* G */
1064      VEC4_ADD(quadColor[2], quadColor[2], dest[2]); /* B */
1065      VEC4_ADD(quadColor[3], quadColor[3], dest[3]); /* A */
1066
1067      /* If fixed-point dest color buffer, need to clamp the outgoing
1068       * fragment colors now.
1069       */
1070      if (bqs->clamp[0]) {
1071         clamp_colors(quadColor);
1072      }
1073
1074      rebase_colors(bqs->base_format[0], quadColor);
1075
1076      for (j = 0; j < QUAD_SIZE; j++) {
1077         if (quad->inout.mask & (1 << j)) {
1078            int x = itx + (j & 1);
1079            int y = ity + (j >> 1);
1080            for (i = 0; i < 4; i++) { /* loop over color chans */
1081               tile->data.color[y][x][i] = quadColor[i][j];
1082            }
1083         }
1084      }
1085   }
1086}
1087
1088
1089/**
1090 * Just copy the quad color to the framebuffer tile (respecting the writemask),
1091 * for one color buffer.
1092 * Clamping will be done, if needed (depending on the color buffer's
1093 * datatype) when we write/pack the colors later.
1094 */
1095static void
1096single_output_color(struct quad_stage *qs,
1097                    struct quad_header *quads[],
1098                    unsigned nr)
1099{
1100   const struct blend_quad_stage *bqs = blend_quad_stage(qs);
1101   uint i, j, q;
1102
1103   struct softpipe_cached_tile *tile
1104      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
1105                           quads[0]->input.x0,
1106                           quads[0]->input.y0);
1107
1108   for (q = 0; q < nr; q++) {
1109      struct quad_header *quad = quads[q];
1110      float (*quadColor)[4] = quad->output.color[0];
1111      const int itx = (quad->input.x0 & (TILE_SIZE-1));
1112      const int ity = (quad->input.y0 & (TILE_SIZE-1));
1113
1114      if (qs->softpipe->rasterizer->clamp_fragment_color)
1115         clamp_colors(quadColor);
1116
1117      rebase_colors(bqs->base_format[0], quadColor);
1118
1119      for (j = 0; j < QUAD_SIZE; j++) {
1120         if (quad->inout.mask & (1 << j)) {
1121            int x = itx + (j & 1);
1122            int y = ity + (j >> 1);
1123            for (i = 0; i < 4; i++) { /* loop over color chans */
1124               tile->data.color[y][x][i] = quadColor[i][j];
1125            }
1126         }
1127      }
1128   }
1129}
1130
1131static void
1132blend_noop(struct quad_stage *qs,
1133           struct quad_header *quads[],
1134           unsigned nr)
1135{
1136}
1137
1138
1139static void
1140choose_blend_quad(struct quad_stage *qs,
1141                  struct quad_header *quads[],
1142                  unsigned nr)
1143{
1144   struct blend_quad_stage *bqs = blend_quad_stage(qs);
1145   struct softpipe_context *softpipe = qs->softpipe;
1146   const struct pipe_blend_state *blend = softpipe->blend;
1147   unsigned i;
1148
1149   qs->run = blend_fallback;
1150
1151   if (softpipe->framebuffer.nr_cbufs == 0) {
1152      qs->run = blend_noop;
1153   }
1154   else if (!softpipe->blend->logicop_enable &&
1155            softpipe->blend->rt[0].colormask == 0xf &&
1156            softpipe->framebuffer.nr_cbufs == 1)
1157   {
1158      if (!blend->rt[0].blend_enable) {
1159         qs->run = single_output_color;
1160      }
1161      else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor &&
1162               blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor &&
1163               blend->rt[0].rgb_func == blend->rt[0].alpha_func)
1164      {
1165         if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) {
1166            if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
1167                blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {
1168               qs->run = blend_single_add_one_one;
1169            }
1170            else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&
1171                blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
1172               qs->run = blend_single_add_src_alpha_inv_src_alpha;
1173
1174         }
1175      }
1176   }
1177
1178   /* For each color buffer, determine if the buffer has destination alpha and
1179    * whether color clamping is needed.
1180    */
1181   for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
1182      const enum pipe_format format = softpipe->framebuffer.cbufs[i]->format;
1183      const struct util_format_description *desc =
1184         util_format_description(format);
1185      /* assuming all or no color channels are normalized: */
1186      bqs->clamp[i] = desc->channel[0].normalized;
1187      bqs->format_type[i] = desc->channel[0].type;
1188
1189      if (util_format_is_intensity(format))
1190         bqs->base_format[i] = INTENSITY;
1191      else if (util_format_is_luminance(format))
1192         bqs->base_format[i] = LUMINANCE;
1193      else if (util_format_is_luminance_alpha(format))
1194         bqs->base_format[i] = LUMINANCE_ALPHA;
1195      else if (util_format_is_rgb_no_alpha(format))
1196         bqs->base_format[i] = RGB;
1197      else
1198         bqs->base_format[i] = RGBA;
1199   }
1200
1201   qs->run(qs, quads, nr);
1202}
1203
1204
1205static void blend_begin(struct quad_stage *qs)
1206{
1207   qs->run = choose_blend_quad;
1208}
1209
1210
1211static void blend_destroy(struct quad_stage *qs)
1212{
1213   FREE( qs );
1214}
1215
1216
1217struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
1218{
1219   struct blend_quad_stage *stage = CALLOC_STRUCT(blend_quad_stage);
1220
1221   if (!stage)
1222      return NULL;
1223
1224   stage->base.softpipe = softpipe;
1225   stage->base.begin = blend_begin;
1226   stage->base.run = choose_blend_quad;
1227   stage->base.destroy = blend_destroy;
1228
1229   return &stage->base;
1230}
1231