fix compiler warning (windows)
[mesa.git] / src / mesa / swrast / s_blend.c
1 /* $Id: s_blend.c,v 1.13 2002/02/12 16:45:22 kschultz Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28
29 #include "glheader.h"
30 #include "context.h"
31 #include "macros.h"
32
33 #include "s_alphabuf.h"
34 #include "s_blend.h"
35 #include "s_context.h"
36 #include "s_span.h"
37
38
39 #if defined(USE_MMX_ASM)
40 #include "X86/mmx.h"
41 #include "X86/common_x86_asm.h"
42 #define _BLENDAPI _ASMAPI
43 #else
44 #define _BLENDAPI
45 #endif
46
47
48 /*
49 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
50 */
51 static void _BLENDAPI
52 blend_noop( GLcontext *ctx, GLuint n, const GLubyte mask[],
53 GLchan rgba[][4], CONST GLchan dest[][4] )
54 {
55 GLuint i;
56 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
57 ASSERT(ctx->Color.BlendSrcRGB==GL_ZERO);
58 ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
59 (void) ctx;
60
61 for (i = 0; i < n; i++) {
62 if (mask[i]) {
63 rgba[i][RCOMP] = dest[i][RCOMP];
64 rgba[i][GCOMP] = dest[i][GCOMP];
65 rgba[i][BCOMP] = dest[i][BCOMP];
66 rgba[i][ACOMP] = dest[i][ACOMP];
67 }
68 }
69 }
70
71
72 /*
73 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
74 */
75 static void _BLENDAPI
76 blend_replace( GLcontext *ctx, GLuint n, const GLubyte mask[],
77 GLchan rgba[][4], CONST GLchan dest[][4] )
78 {
79 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
80 ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
81 ASSERT(ctx->Color.BlendDstRGB==GL_ZERO);
82 (void) ctx;
83 (void) n;
84 (void) mask;
85 (void) rgba;
86 (void) dest;
87 }
88
89
90 /*
91 * Common transparency blending mode.
92 */
93 static void _BLENDAPI
94 blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
95 GLchan rgba[][4], CONST GLchan dest[][4] )
96 {
97 GLuint i;
98 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
99 ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
100 ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
101 (void) ctx;
102
103 for (i=0;i<n;i++) {
104 if (mask[i]) {
105 const GLint t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */
106 if (t == 0) {
107 /* 0% alpha */
108 rgba[i][RCOMP] = dest[i][RCOMP];
109 rgba[i][GCOMP] = dest[i][GCOMP];
110 rgba[i][BCOMP] = dest[i][BCOMP];
111 rgba[i][ACOMP] = dest[i][ACOMP];
112 }
113 else if (t == CHAN_MAX) {
114 /* 100% alpha, no-op */
115 }
116 else {
117 #if 0
118 /* This is pretty close, but Glean complains */
119 const GLint s = CHAN_MAX - t;
120 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s + 1) >> 8;
121 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s + 1) >> 8;
122 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s + 1) >> 8;
123 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s + 1) >> 8;
124 #elif 0
125 /* This is slower but satisfies Glean */
126 const GLint s = CHAN_MAX - t;
127 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) / 255;
128 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) / 255;
129 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) / 255;
130 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) / 255;
131 #else
132 #if CHAN_BITS == 8
133 /* This satisfies Glean and should be reasonably fast */
134 /* Contributed by Nathan Hand */
135 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
136 const GLint s = CHAN_MAX - t;
137 const GLint r = DIV255(rgba[i][RCOMP] * t + dest[i][RCOMP] * s);
138 const GLint g = DIV255(rgba[i][GCOMP] * t + dest[i][GCOMP] * s);
139 const GLint b = DIV255(rgba[i][BCOMP] * t + dest[i][BCOMP] * s);
140 const GLint a = DIV255(rgba[i][ACOMP] * t + dest[i][ACOMP] * s);
141 #undef DIV255
142 #elif CHAN_BITS == 16
143 const GLfloat tt = (GLfloat) t / CHAN_MAXF;
144 const GLfloat s = 1.0 - tt;
145 const GLint r = (GLint) (rgba[i][RCOMP] * tt + dest[i][RCOMP] * s);
146 const GLint g = (GLint) (rgba[i][GCOMP] * tt + dest[i][GCOMP] * s);
147 const GLint b = (GLint) (rgba[i][BCOMP] * tt + dest[i][BCOMP] * s);
148 const GLint a = (GLint) (rgba[i][ACOMP] * tt + dest[i][ACOMP] * s);
149 #else /* CHAN_BITS == 32 */
150 const GLfloat tt = (GLfloat) t / CHAN_MAXF;
151 const GLfloat s = 1.0 - tt;
152 const GLfloat r = rgba[i][RCOMP] * tt + dest[i][RCOMP] * s;
153 const GLfloat g = rgba[i][GCOMP] * tt + dest[i][GCOMP] * s;
154 const GLfloat b = rgba[i][BCOMP] * tt + dest[i][BCOMP] * s;
155 const GLfloat a = rgba[i][ACOMP] * tt + dest[i][ACOMP] * s;
156 #endif
157 #endif
158 ASSERT(r <= CHAN_MAX);
159 ASSERT(g <= CHAN_MAX);
160 ASSERT(b <= CHAN_MAX);
161 ASSERT(a <= CHAN_MAX);
162 rgba[i][RCOMP] = (GLchan) r;
163 rgba[i][GCOMP] = (GLchan) g;
164 rgba[i][BCOMP] = (GLchan) b;
165 rgba[i][ACOMP] = (GLchan) a;
166 }
167 }
168 }
169 }
170
171
172
173 /*
174 * Add src and dest.
175 */
176 static void _BLENDAPI
177 blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
178 GLchan rgba[][4], CONST GLchan dest[][4] )
179 {
180 GLuint i;
181 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
182 ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
183 ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
184 (void) ctx;
185
186 for (i=0;i<n;i++) {
187 if (mask[i]) {
188 GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
189 GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
190 GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
191 GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
192 rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX );
193 rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX );
194 rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX );
195 rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX );
196 }
197 }
198 }
199
200
201
202 /*
203 * Blend min function (for GL_EXT_blend_minmax)
204 */
205 static void _BLENDAPI
206 blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
207 GLchan rgba[][4], CONST GLchan dest[][4] )
208 {
209 GLuint i;
210 ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
211 (void) ctx;
212
213 for (i=0;i<n;i++) {
214 if (mask[i]) {
215 rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
216 rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
217 rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
218 rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
219 }
220 }
221 }
222
223
224
225 /*
226 * Blend max function (for GL_EXT_blend_minmax)
227 */
228 static void _BLENDAPI
229 blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
230 GLchan rgba[][4], CONST GLchan dest[][4] )
231 {
232 GLuint i;
233 ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
234 (void) ctx;
235
236 for (i=0;i<n;i++) {
237 if (mask[i]) {
238 rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
239 rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
240 rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
241 rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
242 }
243 }
244 }
245
246
247
248 /*
249 * Modulate: result = src * dest
250 */
251 static void _BLENDAPI
252 blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
253 GLchan rgba[][4], CONST GLchan dest[][4] )
254 {
255 GLuint i;
256 (void) ctx;
257
258 for (i=0;i<n;i++) {
259 if (mask[i]) {
260 #if CHAN_TYPE == GL_FLOAT
261 rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
262 rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
263 rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
264 rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
265 #else
266 GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
267 GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
268 GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
269 GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
270 rgba[i][RCOMP] = (GLchan) r;
271 rgba[i][GCOMP] = (GLchan) g;
272 rgba[i][BCOMP] = (GLchan) b;
273 rgba[i][ACOMP] = (GLchan) a;
274 #endif
275 }
276 }
277 }
278
279
280
281 /*
282 * General case blend pixels.
283 * Input: n - number of pixels
284 * mask - the usual write mask
285 * In/Out: rgba - the incoming and modified pixels
286 * Input: dest - the pixels from the dest color buffer
287 */
288 static void _BLENDAPI
289 blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
290 GLchan rgba[][4], CONST GLchan dest[][4] )
291 {
292 GLfloat rscale = 1.0F / CHAN_MAXF;
293 GLfloat gscale = 1.0F / CHAN_MAXF;
294 GLfloat bscale = 1.0F / CHAN_MAXF;
295 GLfloat ascale = 1.0F / CHAN_MAXF;
296 GLuint i;
297
298 for (i=0;i<n;i++) {
299 if (mask[i]) {
300 GLint Rs, Gs, Bs, As; /* Source colors */
301 GLint Rd, Gd, Bd, Ad; /* Dest colors */
302 GLfloat sR, sG, sB, sA; /* Source scaling */
303 GLfloat dR, dG, dB, dA; /* Dest scaling */
304 GLfloat r, g, b, a;
305
306 /* Source Color */
307 Rs = rgba[i][RCOMP];
308 Gs = rgba[i][GCOMP];
309 Bs = rgba[i][BCOMP];
310 As = rgba[i][ACOMP];
311
312 /* Frame buffer color */
313 Rd = dest[i][RCOMP];
314 Gd = dest[i][GCOMP];
315 Bd = dest[i][BCOMP];
316 Ad = dest[i][ACOMP];
317
318 /* Source RGB factor */
319 switch (ctx->Color.BlendSrcRGB) {
320 case GL_ZERO:
321 sR = sG = sB = 0.0F;
322 break;
323 case GL_ONE:
324 sR = sG = sB = 1.0F;
325 break;
326 case GL_DST_COLOR:
327 sR = (GLfloat) Rd * rscale;
328 sG = (GLfloat) Gd * gscale;
329 sB = (GLfloat) Bd * bscale;
330 break;
331 case GL_ONE_MINUS_DST_COLOR:
332 sR = 1.0F - (GLfloat) Rd * rscale;
333 sG = 1.0F - (GLfloat) Gd * gscale;
334 sB = 1.0F - (GLfloat) Bd * bscale;
335 break;
336 case GL_SRC_ALPHA:
337 sR = sG = sB = (GLfloat) As * ascale;
338 break;
339 case GL_ONE_MINUS_SRC_ALPHA:
340 sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale;
341 break;
342 case GL_DST_ALPHA:
343 sR = sG = sB = (GLfloat) Ad * ascale;
344 break;
345 case GL_ONE_MINUS_DST_ALPHA:
346 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
347 break;
348 case GL_SRC_ALPHA_SATURATE:
349 if (As < CHAN_MAX - Ad) {
350 sR = sG = sB = (GLfloat) As * ascale;
351 }
352 else {
353 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
354 }
355 break;
356 case GL_CONSTANT_COLOR:
357 sR = ctx->Color.BlendColor[0];
358 sG = ctx->Color.BlendColor[1];
359 sB = ctx->Color.BlendColor[2];
360 break;
361 case GL_ONE_MINUS_CONSTANT_COLOR:
362 sR = 1.0F - ctx->Color.BlendColor[0];
363 sG = 1.0F - ctx->Color.BlendColor[1];
364 sB = 1.0F - ctx->Color.BlendColor[2];
365 break;
366 case GL_CONSTANT_ALPHA:
367 sR = sG = sB = ctx->Color.BlendColor[3];
368 break;
369 case GL_ONE_MINUS_CONSTANT_ALPHA:
370 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
371 break;
372 case GL_SRC_COLOR: /* GL_NV_blend_square */
373 sR = (GLfloat) Rs * rscale;
374 sG = (GLfloat) Gs * gscale;
375 sB = (GLfloat) Bs * bscale;
376 break;
377 case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
378 sR = 1.0F - (GLfloat) Rs * rscale;
379 sG = 1.0F - (GLfloat) Gs * gscale;
380 sB = 1.0F - (GLfloat) Bs * bscale;
381 break;
382 default:
383 /* this should never happen */
384 _mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
385 return;
386 }
387
388 /* Source Alpha factor */
389 switch (ctx->Color.BlendSrcA) {
390 case GL_ZERO:
391 sA = 0.0F;
392 break;
393 case GL_ONE:
394 sA = 1.0F;
395 break;
396 case GL_DST_COLOR:
397 sA = (GLfloat) Ad * ascale;
398 break;
399 case GL_ONE_MINUS_DST_COLOR:
400 sA = 1.0F - (GLfloat) Ad * ascale;
401 break;
402 case GL_SRC_ALPHA:
403 sA = (GLfloat) As * ascale;
404 break;
405 case GL_ONE_MINUS_SRC_ALPHA:
406 sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
407 break;
408 case GL_DST_ALPHA:
409 sA =(GLfloat) Ad * ascale;
410 break;
411 case GL_ONE_MINUS_DST_ALPHA:
412 sA = 1.0F - (GLfloat) Ad * ascale;
413 break;
414 case GL_SRC_ALPHA_SATURATE:
415 sA = 1.0;
416 break;
417 case GL_CONSTANT_COLOR:
418 sA = ctx->Color.BlendColor[3];
419 break;
420 case GL_ONE_MINUS_CONSTANT_COLOR:
421 sA = 1.0F - ctx->Color.BlendColor[3];
422 break;
423 case GL_CONSTANT_ALPHA:
424 sA = ctx->Color.BlendColor[3];
425 break;
426 case GL_ONE_MINUS_CONSTANT_ALPHA:
427 sA = 1.0F - ctx->Color.BlendColor[3];
428 break;
429 case GL_SRC_COLOR: /* GL_NV_blend_square */
430 sA = (GLfloat) As * ascale;
431 break;
432 case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
433 sA = 1.0F - (GLfloat) As * ascale;
434 break;
435 default:
436 /* this should never happen */
437 sA = 0.0F;
438 _mesa_problem(ctx, "Bad blend source A factor in do_blend");
439 }
440
441 /* Dest RGB factor */
442 switch (ctx->Color.BlendDstRGB) {
443 case GL_ZERO:
444 dR = dG = dB = 0.0F;
445 break;
446 case GL_ONE:
447 dR = dG = dB = 1.0F;
448 break;
449 case GL_SRC_COLOR:
450 dR = (GLfloat) Rs * rscale;
451 dG = (GLfloat) Gs * gscale;
452 dB = (GLfloat) Bs * bscale;
453 break;
454 case GL_ONE_MINUS_SRC_COLOR:
455 dR = 1.0F - (GLfloat) Rs * rscale;
456 dG = 1.0F - (GLfloat) Gs * gscale;
457 dB = 1.0F - (GLfloat) Bs * bscale;
458 break;
459 case GL_SRC_ALPHA:
460 dR = dG = dB = (GLfloat) As * ascale;
461 break;
462 case GL_ONE_MINUS_SRC_ALPHA:
463 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
464 break;
465 case GL_DST_ALPHA:
466 dR = dG = dB = (GLfloat) Ad * ascale;
467 break;
468 case GL_ONE_MINUS_DST_ALPHA:
469 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
470 break;
471 case GL_CONSTANT_COLOR:
472 dR = ctx->Color.BlendColor[0];
473 dG = ctx->Color.BlendColor[1];
474 dB = ctx->Color.BlendColor[2];
475 break;
476 case GL_ONE_MINUS_CONSTANT_COLOR:
477 dR = 1.0F - ctx->Color.BlendColor[0];
478 dG = 1.0F - ctx->Color.BlendColor[1];
479 dB = 1.0F - ctx->Color.BlendColor[2];
480 break;
481 case GL_CONSTANT_ALPHA:
482 dR = dG = dB = ctx->Color.BlendColor[3];
483 break;
484 case GL_ONE_MINUS_CONSTANT_ALPHA:
485 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
486 break;
487 case GL_DST_COLOR: /* GL_NV_blend_square */
488 dR = (GLfloat) Rd * rscale;
489 dG = (GLfloat) Gd * gscale;
490 dB = (GLfloat) Bd * bscale;
491 break;
492 case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
493 dR = 1.0F - (GLfloat) Rd * rscale;
494 dG = 1.0F - (GLfloat) Gd * gscale;
495 dB = 1.0F - (GLfloat) Bd * bscale;
496 break;
497 default:
498 /* this should never happen */
499 dR = dG = dB = 0.0F;
500 _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
501 }
502
503 /* Dest Alpha factor */
504 switch (ctx->Color.BlendDstA) {
505 case GL_ZERO:
506 dA = 0.0F;
507 break;
508 case GL_ONE:
509 dA = 1.0F;
510 break;
511 case GL_SRC_COLOR:
512 dA = (GLfloat) As * ascale;
513 break;
514 case GL_ONE_MINUS_SRC_COLOR:
515 dA = 1.0F - (GLfloat) As * ascale;
516 break;
517 case GL_SRC_ALPHA:
518 dA = (GLfloat) As * ascale;
519 break;
520 case GL_ONE_MINUS_SRC_ALPHA:
521 dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
522 break;
523 case GL_DST_ALPHA:
524 dA = (GLfloat) Ad * ascale;
525 break;
526 case GL_ONE_MINUS_DST_ALPHA:
527 dA = 1.0F - (GLfloat) Ad * ascale;
528 break;
529 case GL_CONSTANT_COLOR:
530 dA = ctx->Color.BlendColor[3];
531 break;
532 case GL_ONE_MINUS_CONSTANT_COLOR:
533 dA = 1.0F - ctx->Color.BlendColor[3];
534 break;
535 case GL_CONSTANT_ALPHA:
536 dA = ctx->Color.BlendColor[3];
537 break;
538 case GL_ONE_MINUS_CONSTANT_ALPHA:
539 dA = 1.0F - ctx->Color.BlendColor[3];
540 break;
541 case GL_DST_COLOR: /* GL_NV_blend_square */
542 dA = (GLfloat) Ad * ascale;
543 break;
544 case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
545 dA = 1.0F - (GLfloat) Ad * ascale;
546 break;
547 default:
548 /* this should never happen */
549 dA = 0.0F;
550 _mesa_problem(ctx, "Bad blend dest A factor in do_blend");
551 return;
552 }
553
554 /* Due to round-off problems we have to clamp against zero. */
555 /* Optimization: we don't have to do this for all src & dst factors */
556 if (dA < 0.0F) dA = 0.0F;
557 if (dR < 0.0F) dR = 0.0F;
558 if (dG < 0.0F) dG = 0.0F;
559 if (dB < 0.0F) dB = 0.0F;
560 if (sA < 0.0F) sA = 0.0F;
561 if (sR < 0.0F) sR = 0.0F;
562 if (sG < 0.0F) sG = 0.0F;
563 if (sB < 0.0F) sB = 0.0F;
564
565 ASSERT( sR <= 1.0 );
566 ASSERT( sG <= 1.0 );
567 ASSERT( sB <= 1.0 );
568 ASSERT( sA <= 1.0 );
569 ASSERT( dR <= 1.0 );
570 ASSERT( dG <= 1.0 );
571 ASSERT( dB <= 1.0 );
572 ASSERT( dA <= 1.0 );
573
574 /* compute blended color */
575 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
576 r = Rs * sR + Rd * dR + 0.5F;
577 g = Gs * sG + Gd * dG + 0.5F;
578 b = Bs * sB + Bd * dB + 0.5F;
579 a = As * sA + Ad * dA + 0.5F;
580 }
581 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
582 r = Rs * sR - Rd * dR + 0.5F;
583 g = Gs * sG - Gd * dG + 0.5F;
584 b = Bs * sB - Bd * dB + 0.5F;
585 a = As * sA - Ad * dA + 0.5F;
586 }
587 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
588 r = Rd * dR - Rs * sR + 0.5F;
589 g = Gd * dG - Gs * sG + 0.5F;
590 b = Bd * dB - Bs * sB + 0.5F;
591 a = Ad * dA - As * sA + 0.5F;
592 }
593 else {
594 /* should never get here */
595 r = g = b = a = 0.0F; /* silence uninitialized var warning */
596 _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
597 }
598
599 /* final clamping */
600 rgba[i][RCOMP] = (GLchan) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
601 rgba[i][GCOMP] = (GLchan) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
602 rgba[i][BCOMP] = (GLchan) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
603 rgba[i][ACOMP] = (GLchan) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
604 }
605 }
606 }
607
608
609
610
611
612 /*
613 * Analyze current blending parameters to pick fastest blending function.
614 * Result: the ctx->Color.BlendFunc pointer is updated.
615 */
616 void _swrast_choose_blend_func( GLcontext *ctx )
617 {
618 const GLenum eq = ctx->Color.BlendEquation;
619 const GLenum srcRGB = ctx->Color.BlendSrcRGB;
620 const GLenum dstRGB = ctx->Color.BlendDstRGB;
621 const GLenum srcA = ctx->Color.BlendSrcA;
622 const GLenum dstA = ctx->Color.BlendDstA;
623
624 if (srcRGB != srcA || dstRGB != dstA) {
625 SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
626 }
627 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
628 && dstRGB==GL_ONE_MINUS_SRC_ALPHA)
629 {
630 /* XXX It looks like the MMX blend code is broken. Disable for now. */
631 #if 0 && defined(USE_MMX_ASM)
632 if ( cpu_has_mmx ) {
633 SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
634 }
635 else
636 #endif
637 SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
638 }
639 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
640 SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
641 }
642 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
643 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
644 ||
645 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
646 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
647 SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
648 }
649 else if (eq==GL_MIN_EXT) {
650 SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
651 }
652 else if (eq==GL_MAX_EXT) {
653 SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
654 }
655 else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
656 SWRAST_CONTEXT(ctx)->BlendFunc = blend_noop;
657 }
658 else if (eq==GL_FUNC_ADD_EXT && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
659 SWRAST_CONTEXT(ctx)->BlendFunc = blend_replace;
660 }
661 else {
662 SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
663 }
664 }
665
666
667
668 /*
669 * Apply the blending operator to a span of pixels.
670 * We can handle horizontal runs of pixels (spans) or arrays of x/y
671 * pixel coordinates.
672 */
673 void
674 _mesa_blend_span( GLcontext *ctx, const struct sw_span *span,
675 GLchan rgba[][4] )
676 {
677 SWcontext *swrast = SWRAST_CONTEXT(ctx);
678 GLchan framebuffer[MAX_WIDTH][4];
679
680 ASSERT(span->end < MAX_WIDTH);
681 ASSERT(span->arrayMask & SPAN_RGBA);
682 ASSERT(!ctx->Color.ColorLogicOpEnabled);
683
684 /* Read span of current frame buffer pixels */
685 if (span->arrayMask & SPAN_XY) {
686 /* array of x/y pixel coords */
687 (*swrast->Driver.ReadRGBAPixels)( ctx, span->end,
688 span->xArray, span->yArray,
689 framebuffer, span->mask );
690 if (swrast->_RasterMask & ALPHABUF_BIT) {
691 _mesa_read_alpha_pixels( ctx, span->end, span->xArray, span->yArray,
692 framebuffer, span->mask );
693 }
694 }
695 else {
696 /* horizontal run of pixels */
697 _mesa_read_rgba_span( ctx, ctx->DrawBuffer, span->end,
698 span->x, span->y, framebuffer );
699 }
700
701 SWRAST_CONTEXT(ctx)->BlendFunc( ctx, span->end, span->mask, rgba,
702 (const GLchan (*)[4]) framebuffer );
703 }