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