sp_quad_blend.c revision 1078844d18367b4259cd3b6a3a73e3cd72ea019f
1/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/**
29 * quad blending
30 * \author Brian Paul
31 */
32
33#include "pipe/p_defines.h"
34#include "util/u_math.h"
35#include "util/u_memory.h"
36#include "sp_context.h"
37#include "sp_quad.h"
38#include "sp_surface.h"
39#include "sp_tile_cache.h"
40#include "sp_quad_pipe.h"
41
42
43#define VEC4_COPY(DST, SRC) \
44do { \
45    DST[0] = SRC[0]; \
46    DST[1] = SRC[1]; \
47    DST[2] = SRC[2]; \
48    DST[3] = SRC[3]; \
49} while(0)
50
51#define VEC4_SCALAR(DST, SRC) \
52do { \
53    DST[0] = SRC; \
54    DST[1] = SRC; \
55    DST[2] = SRC; \
56    DST[3] = SRC; \
57} while(0)
58
59#define VEC4_ADD(R, A, B) \
60do { \
61   R[0] = A[0] + B[0]; \
62   R[1] = A[1] + B[1]; \
63   R[2] = A[2] + B[2]; \
64   R[3] = A[3] + B[3]; \
65} while (0)
66
67#define VEC4_SUB(R, A, B) \
68do { \
69   R[0] = A[0] - B[0]; \
70   R[1] = A[1] - B[1]; \
71   R[2] = A[2] - B[2]; \
72   R[3] = A[3] - B[3]; \
73} while (0)
74
75/** Add and limit result to ceiling of 1.0 */
76#define VEC4_ADD_SAT(R, A, B) \
77do { \
78   R[0] = A[0] + B[0];  if (R[0] > 1.0f) R[0] = 1.0f; \
79   R[1] = A[1] + B[1];  if (R[1] > 1.0f) R[1] = 1.0f; \
80   R[2] = A[2] + B[2];  if (R[2] > 1.0f) R[2] = 1.0f; \
81   R[3] = A[3] + B[3];  if (R[3] > 1.0f) R[3] = 1.0f; \
82} while (0)
83
84/** Subtract and limit result to floor of 0.0 */
85#define VEC4_SUB_SAT(R, A, B) \
86do { \
87   R[0] = A[0] - B[0];  if (R[0] < 0.0f) R[0] = 0.0f; \
88   R[1] = A[1] - B[1];  if (R[1] < 0.0f) R[1] = 0.0f; \
89   R[2] = A[2] - B[2];  if (R[2] < 0.0f) R[2] = 0.0f; \
90   R[3] = A[3] - B[3];  if (R[3] < 0.0f) R[3] = 0.0f; \
91} while (0)
92
93#define VEC4_MUL(R, A, B) \
94do { \
95   R[0] = A[0] * B[0]; \
96   R[1] = A[1] * B[1]; \
97   R[2] = A[2] * B[2]; \
98   R[3] = A[3] * B[3]; \
99} while (0)
100
101#define VEC4_MIN(R, A, B) \
102do { \
103   R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
104   R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
105   R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
106   R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
107} while (0)
108
109#define VEC4_MAX(R, A, B) \
110do { \
111   R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
112   R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
113   R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
114   R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
115} while (0)
116
117
118
119static void
120logicop_quad(struct quad_stage *qs,
121             float (*quadColor)[4],
122             float (*dest)[4])
123{
124   struct softpipe_context *softpipe = qs->softpipe;
125   ubyte src[4][4], dst[4][4], res[4][4];
126   uint *src4 = (uint *) src;
127   uint *dst4 = (uint *) dst;
128   uint *res4 = (uint *) res;
129   uint j;
130
131
132   /* convert to ubyte */
133   for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
134      dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
135      dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
136      dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
137      dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
138
139      src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
140      src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
141      src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
142      src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
143   }
144
145   switch (softpipe->blend->logicop_func) {
146   case PIPE_LOGICOP_CLEAR:
147      for (j = 0; j < 4; j++)
148         res4[j] = 0;
149      break;
150   case PIPE_LOGICOP_NOR:
151      for (j = 0; j < 4; j++)
152         res4[j] = ~(src4[j] | dst4[j]);
153      break;
154   case PIPE_LOGICOP_AND_INVERTED:
155      for (j = 0; j < 4; j++)
156         res4[j] = ~src4[j] & dst4[j];
157      break;
158   case PIPE_LOGICOP_COPY_INVERTED:
159      for (j = 0; j < 4; j++)
160         res4[j] = ~src4[j];
161      break;
162   case PIPE_LOGICOP_AND_REVERSE:
163      for (j = 0; j < 4; j++)
164         res4[j] = src4[j] & ~dst4[j];
165      break;
166   case PIPE_LOGICOP_INVERT:
167      for (j = 0; j < 4; j++)
168         res4[j] = ~dst4[j];
169      break;
170   case PIPE_LOGICOP_XOR:
171      for (j = 0; j < 4; j++)
172         res4[j] = dst4[j] ^ src4[j];
173      break;
174   case PIPE_LOGICOP_NAND:
175      for (j = 0; j < 4; j++)
176         res4[j] = ~(src4[j] & dst4[j]);
177      break;
178   case PIPE_LOGICOP_AND:
179      for (j = 0; j < 4; j++)
180         res4[j] = src4[j] & dst4[j];
181      break;
182   case PIPE_LOGICOP_EQUIV:
183      for (j = 0; j < 4; j++)
184         res4[j] = ~(src4[j] ^ dst4[j]);
185      break;
186   case PIPE_LOGICOP_NOOP:
187      for (j = 0; j < 4; j++)
188         res4[j] = dst4[j];
189      break;
190   case PIPE_LOGICOP_OR_INVERTED:
191      for (j = 0; j < 4; j++)
192         res4[j] = ~src4[j] | dst4[j];
193      break;
194   case PIPE_LOGICOP_COPY:
195      for (j = 0; j < 4; j++)
196         res4[j] = src4[j];
197      break;
198   case PIPE_LOGICOP_OR_REVERSE:
199      for (j = 0; j < 4; j++)
200         res4[j] = src4[j] | ~dst4[j];
201      break;
202   case PIPE_LOGICOP_OR:
203      for (j = 0; j < 4; j++)
204         res4[j] = src4[j] | dst4[j];
205      break;
206   case PIPE_LOGICOP_SET:
207      for (j = 0; j < 4; j++)
208         res4[j] = ~0;
209      break;
210   default:
211      assert(0);
212   }
213
214   for (j = 0; j < 4; j++) {
215      quadColor[j][0] = ubyte_to_float(res[j][0]);
216      quadColor[j][1] = ubyte_to_float(res[j][1]);
217      quadColor[j][2] = ubyte_to_float(res[j][2]);
218      quadColor[j][3] = ubyte_to_float(res[j][3]);
219   }
220}
221
222
223
224static void
225blend_quad(struct quad_stage *qs,
226           float (*quadColor)[4],
227           float (*dest)[4])
228{
229   static const float zero[4] = { 0, 0, 0, 0 };
230   static const float one[4] = { 1, 1, 1, 1 };
231   struct softpipe_context *softpipe = qs->softpipe;
232   float source[4][QUAD_SIZE];
233
234   /*
235    * Compute src/first term RGB
236    */
237   switch (softpipe->blend->rgb_src_factor) {
238   case PIPE_BLENDFACTOR_ONE:
239      VEC4_COPY(source[0], quadColor[0]); /* R */
240      VEC4_COPY(source[1], quadColor[1]); /* G */
241      VEC4_COPY(source[2], quadColor[2]); /* B */
242      break;
243   case PIPE_BLENDFACTOR_SRC_COLOR:
244      VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
245      VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
246      VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
247      break;
248   case PIPE_BLENDFACTOR_SRC_ALPHA:
249   {
250      const float *alpha = quadColor[3];
251      VEC4_MUL(source[0], quadColor[0], alpha); /* R */
252      VEC4_MUL(source[1], quadColor[1], alpha); /* G */
253      VEC4_MUL(source[2], quadColor[2], alpha); /* B */
254   }
255   break;
256   case PIPE_BLENDFACTOR_DST_COLOR:
257      VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
258      VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
259      VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
260      break;
261   case PIPE_BLENDFACTOR_DST_ALPHA:
262   {
263      const float *alpha = dest[3];
264      VEC4_MUL(source[0], quadColor[0], alpha); /* R */
265      VEC4_MUL(source[1], quadColor[1], alpha); /* G */
266      VEC4_MUL(source[2], quadColor[2], alpha); /* B */
267   }
268   break;
269   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
270   {
271      const float *alpha = quadColor[3];
272      float diff[4], temp[4];
273      VEC4_SUB(diff, one, dest[3]);
274      VEC4_MIN(temp, alpha, diff);
275      VEC4_MUL(source[0], quadColor[0], temp); /* R */
276      VEC4_MUL(source[1], quadColor[1], temp); /* G */
277      VEC4_MUL(source[2], quadColor[2], temp); /* B */
278   }
279   break;
280   case PIPE_BLENDFACTOR_CONST_COLOR:
281   {
282      float comp[4];
283      VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
284      VEC4_MUL(source[0], quadColor[0], comp); /* R */
285      VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
286      VEC4_MUL(source[1], quadColor[1], comp); /* G */
287      VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
288      VEC4_MUL(source[2], quadColor[2], comp); /* B */
289   }
290   break;
291   case PIPE_BLENDFACTOR_CONST_ALPHA:
292   {
293      float alpha[4];
294      VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
295      VEC4_MUL(source[0], quadColor[0], alpha); /* R */
296      VEC4_MUL(source[1], quadColor[1], alpha); /* G */
297      VEC4_MUL(source[2], quadColor[2], alpha); /* B */
298   }
299   break;
300   case PIPE_BLENDFACTOR_SRC1_COLOR:
301      assert(0); /* to do */
302      break;
303   case PIPE_BLENDFACTOR_SRC1_ALPHA:
304      assert(0); /* to do */
305      break;
306   case PIPE_BLENDFACTOR_ZERO:
307      VEC4_COPY(source[0], zero); /* R */
308      VEC4_COPY(source[1], zero); /* G */
309      VEC4_COPY(source[2], zero); /* B */
310      break;
311   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
312   {
313      float inv_comp[4];
314      VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
315      VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
316      VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
317      VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
318      VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
319      VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
320   }
321   break;
322   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
323   {
324      float inv_alpha[4];
325      VEC4_SUB(inv_alpha, one, quadColor[3]);
326      VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
327      VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
328      VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
329   }
330   break;
331   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
332   {
333      float inv_alpha[4];
334      VEC4_SUB(inv_alpha, one, dest[3]);
335      VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
336      VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
337      VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
338   }
339   break;
340   case PIPE_BLENDFACTOR_INV_DST_COLOR:
341   {
342      float inv_comp[4];
343      VEC4_SUB(inv_comp, one, dest[0]); /* R */
344      VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
345      VEC4_SUB(inv_comp, one, dest[1]); /* G */
346      VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
347      VEC4_SUB(inv_comp, one, dest[2]); /* B */
348      VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
349   }
350   break;
351   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
352   {
353      float inv_comp[4];
354      /* R */
355      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
356      VEC4_MUL(source[0], quadColor[0], inv_comp);
357      /* G */
358      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
359      VEC4_MUL(source[1], quadColor[1], inv_comp);
360      /* B */
361      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
362      VEC4_MUL(source[2], quadColor[2], inv_comp);
363   }
364   break;
365   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
366   {
367      float inv_alpha[4];
368      VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]);
369      VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
370      VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
371      VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
372   }
373   break;
374   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
375      assert(0); /* to do */
376      break;
377   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
378      assert(0); /* to do */
379      break;
380   default:
381      assert(0);
382   }
383
384   /*
385    * Compute src/first term A
386    */
387   switch (softpipe->blend->alpha_src_factor) {
388   case PIPE_BLENDFACTOR_ONE:
389      VEC4_COPY(source[3], quadColor[3]); /* A */
390      break;
391   case PIPE_BLENDFACTOR_SRC_COLOR:
392      /* fall-through */
393   case PIPE_BLENDFACTOR_SRC_ALPHA:
394   {
395      const float *alpha = quadColor[3];
396      VEC4_MUL(source[3], quadColor[3], alpha); /* A */
397   }
398   break;
399   case PIPE_BLENDFACTOR_DST_COLOR:
400      /* fall-through */
401   case PIPE_BLENDFACTOR_DST_ALPHA:
402      VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
403      break;
404   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
405      /* multiply alpha by 1.0 */
406      VEC4_COPY(source[3], quadColor[3]); /* A */
407      break;
408   case PIPE_BLENDFACTOR_CONST_COLOR:
409      /* fall-through */
410   case PIPE_BLENDFACTOR_CONST_ALPHA:
411   {
412      float comp[4];
413      VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
414      VEC4_MUL(source[3], quadColor[3], comp); /* A */
415   }
416   break;
417   case PIPE_BLENDFACTOR_ZERO:
418      VEC4_COPY(source[3], zero); /* A */
419      break;
420   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
421      /* fall-through */
422   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
423   {
424      float inv_alpha[4];
425      VEC4_SUB(inv_alpha, one, quadColor[3]);
426      VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
427   }
428   break;
429   case PIPE_BLENDFACTOR_INV_DST_COLOR:
430      /* fall-through */
431   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
432   {
433      float inv_alpha[4];
434      VEC4_SUB(inv_alpha, one, dest[3]);
435      VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
436   }
437   break;
438   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
439      /* fall-through */
440   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
441   {
442      float inv_comp[4];
443      /* A */
444      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
445      VEC4_MUL(source[3], quadColor[3], inv_comp);
446   }
447   break;
448   default:
449      assert(0);
450   }
451
452
453   /*
454    * Compute dest/second term RGB
455    */
456   switch (softpipe->blend->rgb_dst_factor) {
457   case PIPE_BLENDFACTOR_ONE:
458      /* dest = dest * 1   NO-OP, leave dest as-is */
459      break;
460   case PIPE_BLENDFACTOR_SRC_COLOR:
461      VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
462      VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
463      VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
464      break;
465   case PIPE_BLENDFACTOR_SRC_ALPHA:
466      VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
467      VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
468      VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
469      break;
470   case PIPE_BLENDFACTOR_DST_ALPHA:
471      VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
472      VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
473      VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
474      break;
475   case PIPE_BLENDFACTOR_DST_COLOR:
476      VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
477      VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
478      VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
479      break;
480   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
481      assert(0); /* illegal */
482      break;
483   case PIPE_BLENDFACTOR_CONST_COLOR:
484   {
485      float comp[4];
486      VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
487      VEC4_MUL(dest[0], dest[0], comp); /* R */
488      VEC4_SCALAR(comp, softpipe->blend_color.color[1]); /* G */
489      VEC4_MUL(dest[1], dest[1], comp); /* G */
490      VEC4_SCALAR(comp, softpipe->blend_color.color[2]); /* B */
491      VEC4_MUL(dest[2], dest[2], comp); /* B */
492   }
493   break;
494   case PIPE_BLENDFACTOR_CONST_ALPHA:
495   {
496      float comp[4];
497      VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
498      VEC4_MUL(dest[0], dest[0], comp); /* R */
499      VEC4_MUL(dest[1], dest[1], comp); /* G */
500      VEC4_MUL(dest[2], dest[2], comp); /* B */
501   }
502   break;
503   case PIPE_BLENDFACTOR_ZERO:
504      VEC4_COPY(dest[0], zero); /* R */
505      VEC4_COPY(dest[1], zero); /* G */
506      VEC4_COPY(dest[2], zero); /* B */
507      break;
508   case PIPE_BLENDFACTOR_SRC1_COLOR:
509   case PIPE_BLENDFACTOR_SRC1_ALPHA:
510      /* XXX what are these? */
511      assert(0);
512      break;
513   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
514   {
515      float inv_comp[4];
516      VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
517      VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
518      VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
519      VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
520      VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
521      VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
522   }
523   break;
524   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
525   {
526      float one_minus_alpha[QUAD_SIZE];
527      VEC4_SUB(one_minus_alpha, one, quadColor[3]);
528      VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
529      VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
530      VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
531   }
532   break;
533   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
534   {
535      float inv_comp[4];
536      VEC4_SUB(inv_comp, one, dest[3]); /* A */
537      VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
538      VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
539      VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
540   }
541   break;
542   case PIPE_BLENDFACTOR_INV_DST_COLOR:
543   {
544      float inv_comp[4];
545      VEC4_SUB(inv_comp, one, dest[0]); /* R */
546      VEC4_MUL(dest[0], dest[0], inv_comp); /* R */
547      VEC4_SUB(inv_comp, one, dest[1]); /* G */
548      VEC4_MUL(dest[1], dest[1], inv_comp); /* G */
549      VEC4_SUB(inv_comp, one, dest[2]); /* B */
550      VEC4_MUL(dest[2], dest[2], inv_comp); /* B */
551   }
552   break;
553   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
554   {
555      float inv_comp[4];
556      /* R */
557      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[0]);
558      VEC4_MUL(dest[0], dest[0], inv_comp);
559      /* G */
560      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[1]);
561      VEC4_MUL(dest[1], dest[1], inv_comp);
562      /* B */
563      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[2]);
564      VEC4_MUL(dest[2], dest[2], inv_comp);
565   }
566   break;
567   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
568   {
569      float inv_comp[4];
570      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
571      VEC4_MUL(dest[0], dest[0], inv_comp);
572      VEC4_MUL(dest[1], dest[1], inv_comp);
573      VEC4_MUL(dest[2], dest[2], inv_comp);
574   }
575   break;
576   case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
577   case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
578      /* XXX what are these? */
579      assert(0);
580      break;
581   default:
582      assert(0);
583   }
584
585   /*
586    * Compute dest/second term A
587    */
588   switch (softpipe->blend->alpha_dst_factor) {
589   case PIPE_BLENDFACTOR_ONE:
590      /* dest = dest * 1   NO-OP, leave dest as-is */
591      break;
592   case PIPE_BLENDFACTOR_SRC_COLOR:
593      /* fall-through */
594   case PIPE_BLENDFACTOR_SRC_ALPHA:
595      VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
596      break;
597   case PIPE_BLENDFACTOR_DST_COLOR:
598      /* fall-through */
599   case PIPE_BLENDFACTOR_DST_ALPHA:
600      VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
601      break;
602   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
603      assert(0); /* illegal */
604      break;
605   case PIPE_BLENDFACTOR_CONST_COLOR:
606      /* fall-through */
607   case PIPE_BLENDFACTOR_CONST_ALPHA:
608   {
609      float comp[4];
610      VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
611      VEC4_MUL(dest[3], dest[3], comp); /* A */
612   }
613   break;
614   case PIPE_BLENDFACTOR_ZERO:
615      VEC4_COPY(dest[3], zero); /* A */
616      break;
617   case PIPE_BLENDFACTOR_INV_SRC_COLOR:
618      /* fall-through */
619   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
620   {
621      float one_minus_alpha[QUAD_SIZE];
622      VEC4_SUB(one_minus_alpha, one, quadColor[3]);
623      VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
624   }
625   break;
626   case PIPE_BLENDFACTOR_INV_DST_COLOR:
627      /* fall-through */
628   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
629   {
630      float inv_comp[4];
631      VEC4_SUB(inv_comp, one, dest[3]); /* A */
632      VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
633   }
634   break;
635   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
636      /* fall-through */
637   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
638   {
639      float inv_comp[4];
640      VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
641      VEC4_MUL(dest[3], dest[3], inv_comp);
642   }
643   break;
644   default:
645      assert(0);
646   }
647
648   /*
649    * Combine RGB terms
650    */
651   switch (softpipe->blend->rgb_func) {
652   case PIPE_BLEND_ADD:
653      VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
654      VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
655      VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
656      break;
657   case PIPE_BLEND_SUBTRACT:
658      VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */
659      VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */
660      VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */
661      break;
662   case PIPE_BLEND_REVERSE_SUBTRACT:
663      VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */
664      VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */
665      VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */
666      break;
667   case PIPE_BLEND_MIN:
668      VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
669      VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
670      VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
671      break;
672   case PIPE_BLEND_MAX:
673      VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
674      VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
675      VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
676      break;
677   default:
678      assert(0);
679   }
680
681   /*
682    * Combine A terms
683    */
684   switch (softpipe->blend->alpha_func) {
685   case PIPE_BLEND_ADD:
686      VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
687      break;
688   case PIPE_BLEND_SUBTRACT:
689      VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
690      break;
691   case PIPE_BLEND_REVERSE_SUBTRACT:
692      VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
693      break;
694   case PIPE_BLEND_MIN:
695      VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
696      break;
697   case PIPE_BLEND_MAX:
698      VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
699      break;
700   default:
701      assert(0);
702   }
703}
704
705static void
706colormask_quad(struct quad_stage *qs,
707               float (*quadColor)[4],
708               float (*dest)[4])
709{
710   struct softpipe_context *softpipe = qs->softpipe;
711
712   /* R */
713   if (!(softpipe->blend->colormask & PIPE_MASK_R))
714      COPY_4V(quadColor[0], dest[0]);
715
716   /* G */
717   if (!(softpipe->blend->colormask & PIPE_MASK_G))
718      COPY_4V(quadColor[1], dest[1]);
719
720   /* B */
721   if (!(softpipe->blend->colormask & PIPE_MASK_B))
722      COPY_4V(quadColor[2], dest[2]);
723
724   /* A */
725   if (!(softpipe->blend->colormask & PIPE_MASK_A))
726      COPY_4V(quadColor[3], dest[3]);
727}
728
729
730static void
731blend_fallback(struct quad_stage *qs,
732               struct quad_header *quads[],
733               unsigned nr)
734{
735   struct softpipe_context *softpipe = qs->softpipe;
736   const struct pipe_blend_state *blend = softpipe->blend;
737   unsigned cbuf;
738
739   for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
740   {
741      float dest[4][QUAD_SIZE];
742      struct softpipe_cached_tile *tile
743         = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
744                              quads[0]->input.x0,
745                              quads[0]->input.y0);
746      uint q, i, j;
747
748      for (q = 0; q < nr; q++) {
749         struct quad_header *quad = quads[q];
750         float (*quadColor)[4] = quad->output.color[cbuf];
751         const int itx = (quad->input.x0 & (TILE_SIZE-1));
752         const int ity = (quad->input.y0 & (TILE_SIZE-1));
753
754         /* get/swizzle dest colors
755          */
756         for (j = 0; j < QUAD_SIZE; j++) {
757            int x = itx + (j & 1);
758            int y = ity + (j >> 1);
759            for (i = 0; i < 4; i++) {
760               dest[i][j] = tile->data.color[y][x][i];
761            }
762         }
763
764
765         if (blend->logicop_enable) {
766            logicop_quad( qs, quadColor, dest );
767         }
768         else if (blend->blend_enable) {
769            blend_quad( qs, quadColor, dest );
770         }
771
772         if (blend->colormask != 0xf)
773            colormask_quad( qs, quadColor, dest );
774
775         /* Output color values
776          */
777         for (j = 0; j < QUAD_SIZE; j++) {
778            if (quad->inout.mask & (1 << j)) {
779               int x = itx + (j & 1);
780               int y = ity + (j >> 1);
781               for (i = 0; i < 4; i++) { /* loop over color chans */
782                  tile->data.color[y][x][i] = quadColor[i][j];
783               }
784            }
785         }
786      }
787   }
788}
789
790
791static void
792blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
793                                         struct quad_header *quads[],
794                                         unsigned nr)
795{
796   static const float one[4] = { 1, 1, 1, 1 };
797   float one_minus_alpha[QUAD_SIZE];
798   float dest[4][QUAD_SIZE];
799   float source[4][QUAD_SIZE];
800   uint i, j, q;
801
802   struct softpipe_cached_tile *tile
803      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
804                           quads[0]->input.x0,
805                           quads[0]->input.y0);
806
807   for (q = 0; q < nr; q++) {
808      struct quad_header *quad = quads[q];
809      float (*quadColor)[4] = quad->output.color[0];
810      const float *alpha = quadColor[3];
811      const int itx = (quad->input.x0 & (TILE_SIZE-1));
812      const int ity = (quad->input.y0 & (TILE_SIZE-1));
813
814      /* get/swizzle dest colors */
815      for (j = 0; j < QUAD_SIZE; j++) {
816         int x = itx + (j & 1);
817         int y = ity + (j >> 1);
818         for (i = 0; i < 4; i++) {
819            dest[i][j] = tile->data.color[y][x][i];
820         }
821      }
822
823      VEC4_MUL(source[0], quadColor[0], alpha); /* R */
824      VEC4_MUL(source[1], quadColor[1], alpha); /* G */
825      VEC4_MUL(source[2], quadColor[2], alpha); /* B */
826      VEC4_MUL(source[3], quadColor[3], alpha); /* A */
827
828      VEC4_SUB(one_minus_alpha, one, alpha);
829      VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
830      VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
831      VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
832      VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* B */
833
834      VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
835      VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
836      VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
837      VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
838
839      for (j = 0; j < QUAD_SIZE; j++) {
840         if (quad->inout.mask & (1 << j)) {
841            int x = itx + (j & 1);
842            int y = ity + (j >> 1);
843            for (i = 0; i < 4; i++) { /* loop over color chans */
844               tile->data.color[y][x][i] = quadColor[i][j];
845            }
846         }
847      }
848   }
849}
850
851static void
852blend_single_add_one_one(struct quad_stage *qs,
853                         struct quad_header *quads[],
854                         unsigned nr)
855{
856   float dest[4][QUAD_SIZE];
857   uint i, j, q;
858
859   struct softpipe_cached_tile *tile
860      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
861                           quads[0]->input.x0,
862                           quads[0]->input.y0);
863
864   for (q = 0; q < nr; q++) {
865      struct quad_header *quad = quads[q];
866      float (*quadColor)[4] = quad->output.color[0];
867      const int itx = (quad->input.x0 & (TILE_SIZE-1));
868      const int ity = (quad->input.y0 & (TILE_SIZE-1));
869
870      /* get/swizzle dest colors */
871      for (j = 0; j < QUAD_SIZE; j++) {
872         int x = itx + (j & 1);
873         int y = ity + (j >> 1);
874         for (i = 0; i < 4; i++) {
875            dest[i][j] = tile->data.color[y][x][i];
876         }
877      }
878
879      VEC4_ADD_SAT(quadColor[0], quadColor[0], dest[0]); /* R */
880      VEC4_ADD_SAT(quadColor[1], quadColor[1], dest[1]); /* G */
881      VEC4_ADD_SAT(quadColor[2], quadColor[2], dest[2]); /* B */
882      VEC4_ADD_SAT(quadColor[3], quadColor[3], dest[3]); /* A */
883
884      for (j = 0; j < QUAD_SIZE; j++) {
885         if (quad->inout.mask & (1 << j)) {
886            int x = itx + (j & 1);
887            int y = ity + (j >> 1);
888            for (i = 0; i < 4; i++) { /* loop over color chans */
889               tile->data.color[y][x][i] = quadColor[i][j];
890            }
891         }
892      }
893   }
894}
895
896
897static void
898single_output_color(struct quad_stage *qs,
899                    struct quad_header *quads[],
900                    unsigned nr)
901{
902   uint i, j, q;
903
904   struct softpipe_cached_tile *tile
905      = sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
906                           quads[0]->input.x0,
907                           quads[0]->input.y0);
908
909   for (q = 0; q < nr; q++) {
910      struct quad_header *quad = quads[q];
911      float (*quadColor)[4] = quad->output.color[0];
912      const int itx = (quad->input.x0 & (TILE_SIZE-1));
913      const int ity = (quad->input.y0 & (TILE_SIZE-1));
914
915      for (j = 0; j < QUAD_SIZE; j++) {
916         if (quad->inout.mask & (1 << j)) {
917            int x = itx + (j & 1);
918            int y = ity + (j >> 1);
919            for (i = 0; i < 4; i++) { /* loop over color chans */
920               tile->data.color[y][x][i] = quadColor[i][j];
921            }
922         }
923      }
924   }
925}
926
927static void
928blend_noop(struct quad_stage *qs,
929           struct quad_header *quads[],
930           unsigned nr)
931{
932}
933
934
935static void
936choose_blend_quad(struct quad_stage *qs,
937                  struct quad_header *quads[],
938                  unsigned nr)
939{
940   struct softpipe_context *softpipe = qs->softpipe;
941   const struct pipe_blend_state *blend = softpipe->blend;
942
943   qs->run = blend_fallback;
944
945   if (softpipe->framebuffer.nr_cbufs == 0) {
946      qs->run = blend_noop;
947   }
948   else if (!softpipe->blend->logicop_enable &&
949            softpipe->blend->colormask == 0xf)
950   {
951      if (!blend->blend_enable) {
952         qs->run = single_output_color;
953      }
954      else if (blend->rgb_src_factor == blend->alpha_src_factor &&
955               blend->rgb_dst_factor == blend->alpha_dst_factor &&
956               blend->rgb_func == blend->alpha_func &&
957               softpipe->framebuffer.nr_cbufs == 1)
958      {
959         if (blend->alpha_func == PIPE_BLEND_ADD) {
960            if (blend->rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
961                blend->rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {
962               qs->run = blend_single_add_one_one;
963            }
964            else if (blend->rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&
965                blend->rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
966               qs->run = blend_single_add_src_alpha_inv_src_alpha;
967
968         }
969      }
970   }
971
972   qs->run(qs, quads, nr);
973}
974
975
976static void blend_begin(struct quad_stage *qs)
977{
978   qs->run = choose_blend_quad;
979}
980
981
982static void blend_destroy(struct quad_stage *qs)
983{
984   FREE( qs );
985}
986
987
988struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
989{
990   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
991
992   stage->softpipe = softpipe;
993   stage->begin = blend_begin;
994   stage->run = choose_blend_quad;
995   stage->destroy = blend_destroy;
996
997   return stage;
998}
999