Consistent copyright info (version number, date) across all files.
[mesa.git] / src / mesa / swrast / s_blend.c
1 /* $Id: s_blend.c,v 1.6 2001/03/12 00:48:41 gareth Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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_pb.h"
37 #include "s_span.h"
38
39
40 #if defined(USE_MMX_ASM)
41 #include "X86/mmx.h"
42 #include "X86/common_x86_asm.h"
43 #define _BLENDAPI _ASMAPI
44 #else
45 #define _BLENDAPI
46 #endif
47
48
49 /*
50 * Common transparency blending mode.
51 */
52 static void _BLENDAPI
53 blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
54 GLchan rgba[][4], CONST GLchan dest[][4] )
55 {
56 GLuint i;
57 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
58 ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
59 ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
60 (void) ctx;
61
62 for (i=0;i<n;i++) {
63 if (mask[i]) {
64 const GLint t = rgba[i][ACOMP]; /* t in [0, CHAN_MAX] */
65 if (t == 0) {
66 /* 0% alpha */
67 rgba[i][RCOMP] = dest[i][RCOMP];
68 rgba[i][GCOMP] = dest[i][GCOMP];
69 rgba[i][BCOMP] = dest[i][BCOMP];
70 rgba[i][ACOMP] = dest[i][ACOMP];
71 }
72 else if (t == CHAN_MAX) {
73 /* 100% alpha, no-op */
74 }
75 else {
76 #if 0
77 /* This is pretty close, but Glean complains */
78 const GLint s = CHAN_MAX - t;
79 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s + 1) >> 8;
80 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s + 1) >> 8;
81 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s + 1) >> 8;
82 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s + 1) >> 8;
83 #elif 0
84 /* This is slower but satisfies Glean */
85 const GLint s = CHAN_MAX - t;
86 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) / 255;
87 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) / 255;
88 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) / 255;
89 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) / 255;
90 #else
91 #if CHAN_BITS == 8
92 /* This satisfies Glean and should be reasonably fast */
93 /* Contributed by Nathan Hand */
94 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
95 const GLint s = CHAN_MAX - t;
96 const GLint r = DIV255(rgba[i][RCOMP] * t + dest[i][RCOMP] * s);
97 const GLint g = DIV255(rgba[i][GCOMP] * t + dest[i][GCOMP] * s);
98 const GLint b = DIV255(rgba[i][BCOMP] * t + dest[i][BCOMP] * s);
99 const GLint a = DIV255(rgba[i][ACOMP] * t + dest[i][ACOMP] * s);
100 #undef DIV255
101 #elif CHAN_BITS == 16
102 const GLfloat tt = (GLfloat) t / CHAN_MAXF;
103 const GLfloat s = 1.0 - tt;
104 const GLint r = (GLint) (rgba[i][RCOMP] * tt + dest[i][RCOMP] * s);
105 const GLint g = (GLint) (rgba[i][GCOMP] * tt + dest[i][GCOMP] * s);
106 const GLint b = (GLint) (rgba[i][BCOMP] * tt + dest[i][BCOMP] * s);
107 const GLint a = (GLint) (rgba[i][ACOMP] * tt + dest[i][ACOMP] * s);
108 #else /* CHAN_BITS == 32 */
109 const GLfloat tt = (GLfloat) t / CHAN_MAXF;
110 const GLfloat s = 1.0 - tt;
111 const GLfloat r = rgba[i][RCOMP] * tt + dest[i][RCOMP] * s;
112 const GLfloat g = rgba[i][GCOMP] * tt + dest[i][GCOMP] * s;
113 const GLfloat b = rgba[i][BCOMP] * tt + dest[i][BCOMP] * s;
114 const GLfloat a = rgba[i][ACOMP] * tt + dest[i][ACOMP] * s;
115 #endif
116 #endif
117 ASSERT(r <= CHAN_MAX);
118 ASSERT(g <= CHAN_MAX);
119 ASSERT(b <= CHAN_MAX);
120 ASSERT(a <= CHAN_MAX);
121 rgba[i][RCOMP] = (GLchan) r;
122 rgba[i][GCOMP] = (GLchan) g;
123 rgba[i][BCOMP] = (GLchan) b;
124 rgba[i][ACOMP] = (GLchan) a;
125 }
126 }
127 }
128 }
129
130
131
132 /*
133 * Add src and dest.
134 */
135 static void _BLENDAPI
136 blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
137 GLchan rgba[][4], CONST GLchan dest[][4] )
138 {
139 GLuint i;
140 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
141 ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
142 ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
143 (void) ctx;
144
145 for (i=0;i<n;i++) {
146 if (mask[i]) {
147 GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
148 GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
149 GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
150 GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
151 rgba[i][RCOMP] = (GLchan) MIN2( r, CHAN_MAX );
152 rgba[i][GCOMP] = (GLchan) MIN2( g, CHAN_MAX );
153 rgba[i][BCOMP] = (GLchan) MIN2( b, CHAN_MAX );
154 rgba[i][ACOMP] = (GLchan) MIN2( a, CHAN_MAX );
155 }
156 }
157 }
158
159
160
161 /*
162 * Blend min function (for GL_EXT_blend_minmax)
163 */
164 static void _BLENDAPI
165 blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
166 GLchan rgba[][4], CONST GLchan dest[][4] )
167 {
168 GLuint i;
169 ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
170 (void) ctx;
171
172 for (i=0;i<n;i++) {
173 if (mask[i]) {
174 rgba[i][RCOMP] = (GLchan) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
175 rgba[i][GCOMP] = (GLchan) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
176 rgba[i][BCOMP] = (GLchan) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
177 rgba[i][ACOMP] = (GLchan) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
178 }
179 }
180 }
181
182
183
184 /*
185 * Blend max function (for GL_EXT_blend_minmax)
186 */
187 static void _BLENDAPI
188 blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
189 GLchan rgba[][4], CONST GLchan dest[][4] )
190 {
191 GLuint i;
192 ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
193 (void) ctx;
194
195 for (i=0;i<n;i++) {
196 if (mask[i]) {
197 rgba[i][RCOMP] = (GLchan) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
198 rgba[i][GCOMP] = (GLchan) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
199 rgba[i][BCOMP] = (GLchan) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
200 rgba[i][ACOMP] = (GLchan) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
201 }
202 }
203 }
204
205
206
207 /*
208 * Modulate: result = src * dest
209 */
210 static void _BLENDAPI
211 blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
212 GLchan rgba[][4], CONST GLchan dest[][4] )
213 {
214 GLuint i;
215 (void) ctx;
216
217 for (i=0;i<n;i++) {
218 if (mask[i]) {
219 GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
220 GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
221 GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
222 GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
223 rgba[i][RCOMP] = (GLchan) r;
224 rgba[i][GCOMP] = (GLchan) g;
225 rgba[i][BCOMP] = (GLchan) b;
226 rgba[i][ACOMP] = (GLchan) a;
227 }
228 }
229 }
230
231
232
233 /*
234 * General case blend pixels.
235 * Input: n - number of pixels
236 * mask - the usual write mask
237 * In/Out: rgba - the incoming and modified pixels
238 * Input: dest - the pixels from the dest color buffer
239 */
240 static void _BLENDAPI
241 blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
242 GLchan rgba[][4], CONST GLchan dest[][4] )
243 {
244 GLfloat rscale = 1.0F / CHAN_MAXF;
245 GLfloat gscale = 1.0F / CHAN_MAXF;
246 GLfloat bscale = 1.0F / CHAN_MAXF;
247 GLfloat ascale = 1.0F / CHAN_MAXF;
248 GLuint i;
249
250 for (i=0;i<n;i++) {
251 if (mask[i]) {
252 GLint Rs, Gs, Bs, As; /* Source colors */
253 GLint Rd, Gd, Bd, Ad; /* Dest colors */
254 GLfloat sR, sG, sB, sA; /* Source scaling */
255 GLfloat dR, dG, dB, dA; /* Dest scaling */
256 GLfloat r, g, b, a;
257
258 /* Source Color */
259 Rs = rgba[i][RCOMP];
260 Gs = rgba[i][GCOMP];
261 Bs = rgba[i][BCOMP];
262 As = rgba[i][ACOMP];
263
264 /* Frame buffer color */
265 Rd = dest[i][RCOMP];
266 Gd = dest[i][GCOMP];
267 Bd = dest[i][BCOMP];
268 Ad = dest[i][ACOMP];
269
270 /* Source RGB factor */
271 switch (ctx->Color.BlendSrcRGB) {
272 case GL_ZERO:
273 sR = sG = sB = 0.0F;
274 break;
275 case GL_ONE:
276 sR = sG = sB = 1.0F;
277 break;
278 case GL_DST_COLOR:
279 sR = (GLfloat) Rd * rscale;
280 sG = (GLfloat) Gd * gscale;
281 sB = (GLfloat) Bd * bscale;
282 break;
283 case GL_ONE_MINUS_DST_COLOR:
284 sR = 1.0F - (GLfloat) Rd * rscale;
285 sG = 1.0F - (GLfloat) Gd * gscale;
286 sB = 1.0F - (GLfloat) Bd * bscale;
287 break;
288 case GL_SRC_ALPHA:
289 sR = sG = sB = (GLfloat) As * ascale;
290 break;
291 case GL_ONE_MINUS_SRC_ALPHA:
292 sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale;
293 break;
294 case GL_DST_ALPHA:
295 sR = sG = sB = (GLfloat) Ad * ascale;
296 break;
297 case GL_ONE_MINUS_DST_ALPHA:
298 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
299 break;
300 case GL_SRC_ALPHA_SATURATE:
301 if (As < CHAN_MAX - Ad) {
302 sR = sG = sB = (GLfloat) As * ascale;
303 }
304 else {
305 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
306 }
307 break;
308 case GL_CONSTANT_COLOR:
309 sR = ctx->Color.BlendColor[0];
310 sG = ctx->Color.BlendColor[1];
311 sB = ctx->Color.BlendColor[2];
312 break;
313 case GL_ONE_MINUS_CONSTANT_COLOR:
314 sR = 1.0F - ctx->Color.BlendColor[0];
315 sG = 1.0F - ctx->Color.BlendColor[1];
316 sB = 1.0F - ctx->Color.BlendColor[2];
317 break;
318 case GL_CONSTANT_ALPHA:
319 sR = sG = sB = ctx->Color.BlendColor[3];
320 break;
321 case GL_ONE_MINUS_CONSTANT_ALPHA:
322 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
323 break;
324 case GL_SRC_COLOR: /* GL_NV_blend_square */
325 sR = (GLfloat) Rs * rscale;
326 sG = (GLfloat) Gs * gscale;
327 sB = (GLfloat) Bs * bscale;
328 break;
329 case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
330 sR = 1.0F - (GLfloat) Rs * rscale;
331 sG = 1.0F - (GLfloat) Gs * gscale;
332 sB = 1.0F - (GLfloat) Bs * bscale;
333 break;
334 default:
335 /* this should never happen */
336 _mesa_problem(ctx, "Bad blend source RGB factor in do_blend");
337 return;
338 }
339
340 /* Source Alpha factor */
341 switch (ctx->Color.BlendSrcA) {
342 case GL_ZERO:
343 sA = 0.0F;
344 break;
345 case GL_ONE:
346 sA = 1.0F;
347 break;
348 case GL_DST_COLOR:
349 sA = (GLfloat) Ad * ascale;
350 break;
351 case GL_ONE_MINUS_DST_COLOR:
352 sA = 1.0F - (GLfloat) Ad * ascale;
353 break;
354 case GL_SRC_ALPHA:
355 sA = (GLfloat) As * ascale;
356 break;
357 case GL_ONE_MINUS_SRC_ALPHA:
358 sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
359 break;
360 case GL_DST_ALPHA:
361 sA =(GLfloat) Ad * ascale;
362 break;
363 case GL_ONE_MINUS_DST_ALPHA:
364 sA = 1.0F - (GLfloat) Ad * ascale;
365 break;
366 case GL_SRC_ALPHA_SATURATE:
367 sA = 1.0;
368 break;
369 case GL_CONSTANT_COLOR:
370 sA = ctx->Color.BlendColor[3];
371 break;
372 case GL_ONE_MINUS_CONSTANT_COLOR:
373 sA = 1.0F - ctx->Color.BlendColor[3];
374 break;
375 case GL_CONSTANT_ALPHA:
376 sA = ctx->Color.BlendColor[3];
377 break;
378 case GL_ONE_MINUS_CONSTANT_ALPHA:
379 sA = 1.0F - ctx->Color.BlendColor[3];
380 break;
381 case GL_SRC_COLOR: /* GL_NV_blend_square */
382 sA = (GLfloat) As * ascale;
383 break;
384 case GL_ONE_MINUS_SRC_COLOR: /* GL_NV_blend_square */
385 sA = 1.0F - (GLfloat) As * ascale;
386 break;
387 default:
388 /* this should never happen */
389 sA = 0.0F;
390 _mesa_problem(ctx, "Bad blend source A factor in do_blend");
391 }
392
393 /* Dest RGB factor */
394 switch (ctx->Color.BlendDstRGB) {
395 case GL_ZERO:
396 dR = dG = dB = 0.0F;
397 break;
398 case GL_ONE:
399 dR = dG = dB = 1.0F;
400 break;
401 case GL_SRC_COLOR:
402 dR = (GLfloat) Rs * rscale;
403 dG = (GLfloat) Gs * gscale;
404 dB = (GLfloat) Bs * bscale;
405 break;
406 case GL_ONE_MINUS_SRC_COLOR:
407 dR = 1.0F - (GLfloat) Rs * rscale;
408 dG = 1.0F - (GLfloat) Gs * gscale;
409 dB = 1.0F - (GLfloat) Bs * bscale;
410 break;
411 case GL_SRC_ALPHA:
412 dR = dG = dB = (GLfloat) As * ascale;
413 break;
414 case GL_ONE_MINUS_SRC_ALPHA:
415 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
416 break;
417 case GL_DST_ALPHA:
418 dR = dG = dB = (GLfloat) Ad * ascale;
419 break;
420 case GL_ONE_MINUS_DST_ALPHA:
421 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
422 break;
423 case GL_CONSTANT_COLOR:
424 dR = ctx->Color.BlendColor[0];
425 dG = ctx->Color.BlendColor[1];
426 dB = ctx->Color.BlendColor[2];
427 break;
428 case GL_ONE_MINUS_CONSTANT_COLOR:
429 dR = 1.0F - ctx->Color.BlendColor[0];
430 dG = 1.0F - ctx->Color.BlendColor[1];
431 dB = 1.0F - ctx->Color.BlendColor[2];
432 break;
433 case GL_CONSTANT_ALPHA:
434 dR = dG = dB = ctx->Color.BlendColor[3];
435 break;
436 case GL_ONE_MINUS_CONSTANT_ALPHA:
437 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
438 break;
439 case GL_DST_COLOR: /* GL_NV_blend_square */
440 dR = (GLfloat) Rd * rscale;
441 dG = (GLfloat) Gd * gscale;
442 dB = (GLfloat) Bd * bscale;
443 break;
444 case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
445 dR = 1.0F - (GLfloat) Rd * rscale;
446 dG = 1.0F - (GLfloat) Gd * gscale;
447 dB = 1.0F - (GLfloat) Bd * bscale;
448 break;
449 default:
450 /* this should never happen */
451 dR = dG = dB = 0.0F;
452 _mesa_problem(ctx, "Bad blend dest RGB factor in do_blend");
453 }
454
455 /* Dest Alpha factor */
456 switch (ctx->Color.BlendDstA) {
457 case GL_ZERO:
458 dA = 0.0F;
459 break;
460 case GL_ONE:
461 dA = 1.0F;
462 break;
463 case GL_SRC_COLOR:
464 dA = (GLfloat) As * ascale;
465 break;
466 case GL_ONE_MINUS_SRC_COLOR:
467 dA = 1.0F - (GLfloat) As * ascale;
468 break;
469 case GL_SRC_ALPHA:
470 dA = (GLfloat) As * ascale;
471 break;
472 case GL_ONE_MINUS_SRC_ALPHA:
473 dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
474 break;
475 case GL_DST_ALPHA:
476 dA = (GLfloat) Ad * ascale;
477 break;
478 case GL_ONE_MINUS_DST_ALPHA:
479 dA = 1.0F - (GLfloat) Ad * ascale;
480 break;
481 case GL_CONSTANT_COLOR:
482 dA = ctx->Color.BlendColor[3];
483 break;
484 case GL_ONE_MINUS_CONSTANT_COLOR:
485 dA = 1.0F - ctx->Color.BlendColor[3];
486 break;
487 case GL_CONSTANT_ALPHA:
488 dA = ctx->Color.BlendColor[3];
489 break;
490 case GL_ONE_MINUS_CONSTANT_ALPHA:
491 dA = 1.0F - ctx->Color.BlendColor[3];
492 break;
493 case GL_DST_COLOR: /* GL_NV_blend_square */
494 dA = (GLfloat) Ad * ascale;
495 break;
496 case GL_ONE_MINUS_DST_COLOR: /* GL_NV_blend_square */
497 dA = 1.0F - (GLfloat) Ad * ascale;
498 break;
499 default:
500 /* this should never happen */
501 dA = 0.0F;
502 _mesa_problem(ctx, "Bad blend dest A factor in do_blend");
503 return;
504 }
505
506 /* Due to round-off problems we have to clamp against zero. */
507 /* Optimization: we don't have to do this for all src & dst factors */
508 if (dA < 0.0F) dA = 0.0F;
509 if (dR < 0.0F) dR = 0.0F;
510 if (dG < 0.0F) dG = 0.0F;
511 if (dB < 0.0F) dB = 0.0F;
512 if (sA < 0.0F) sA = 0.0F;
513 if (sR < 0.0F) sR = 0.0F;
514 if (sG < 0.0F) sG = 0.0F;
515 if (sB < 0.0F) sB = 0.0F;
516
517 ASSERT( sR <= 1.0 );
518 ASSERT( sG <= 1.0 );
519 ASSERT( sB <= 1.0 );
520 ASSERT( sA <= 1.0 );
521 ASSERT( dR <= 1.0 );
522 ASSERT( dG <= 1.0 );
523 ASSERT( dB <= 1.0 );
524 ASSERT( dA <= 1.0 );
525
526 /* compute blended color */
527 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
528 r = Rs * sR + Rd * dR + 0.5F;
529 g = Gs * sG + Gd * dG + 0.5F;
530 b = Bs * sB + Bd * dB + 0.5F;
531 a = As * sA + Ad * dA + 0.5F;
532 }
533 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
534 r = Rs * sR - Rd * dR + 0.5F;
535 g = Gs * sG - Gd * dG + 0.5F;
536 b = Bs * sB - Bd * dB + 0.5F;
537 a = As * sA - Ad * dA + 0.5F;
538 }
539 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
540 r = Rd * dR - Rs * sR + 0.5F;
541 g = Gd * dG - Gs * sG + 0.5F;
542 b = Bd * dB - Bs * sB + 0.5F;
543 a = Ad * dA - As * sA + 0.5F;
544 }
545 else {
546 /* should never get here */
547 r = g = b = a = 0.0F; /* silence uninitialized var warning */
548 _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
549 }
550
551 /* final clamping */
552 rgba[i][RCOMP] = (GLchan) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
553 rgba[i][GCOMP] = (GLchan) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
554 rgba[i][BCOMP] = (GLchan) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
555 rgba[i][ACOMP] = (GLchan) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
556 }
557 }
558 }
559
560
561
562
563
564 /*
565 * Analyze current blending parameters to pick fastest blending function.
566 * Result: the ctx->Color.BlendFunc pointer is updated.
567 */
568 void _swrast_choose_blend_func( GLcontext *ctx )
569 {
570 const GLenum eq = ctx->Color.BlendEquation;
571 const GLenum srcRGB = ctx->Color.BlendSrcRGB;
572 const GLenum dstRGB = ctx->Color.BlendDstRGB;
573 const GLenum srcA = ctx->Color.BlendSrcA;
574 const GLenum dstA = ctx->Color.BlendDstA;
575
576 if (srcRGB != srcA || dstRGB != dstA) {
577 SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
578 }
579 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
580 && dstRGB==GL_ONE_MINUS_SRC_ALPHA)
581 {
582 #if defined(USE_MMX_ASM)
583 if ( cpu_has_mmx ) {
584 SWRAST_CONTEXT(ctx)->BlendFunc = _mesa_mmx_blend_transparency;
585 }
586 else
587 #endif
588 SWRAST_CONTEXT(ctx)->BlendFunc = blend_transparency;
589 }
590 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
591 SWRAST_CONTEXT(ctx)->BlendFunc = blend_add;
592 }
593 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
594 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
595 ||
596 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
597 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
598 SWRAST_CONTEXT(ctx)->BlendFunc = blend_modulate;
599 }
600 else if (eq==GL_MIN_EXT) {
601 SWRAST_CONTEXT(ctx)->BlendFunc = blend_min;
602 }
603 else if (eq==GL_MAX_EXT) {
604 SWRAST_CONTEXT(ctx)->BlendFunc = blend_max;
605 }
606 else {
607 SWRAST_CONTEXT(ctx)->BlendFunc = blend_general;
608 }
609 }
610
611
612
613 /*
614 * Apply the blending operator to a span of pixels.
615 * Input: n - number of pixels in span
616 * x, y - location of leftmost pixel in span in window coords.
617 * mask - boolean mask indicating which pixels to blend.
618 * In/Out: rgba - pixel values
619 */
620 void
621 _mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
622 GLchan rgba[][4], const GLubyte mask[] )
623 {
624 GLchan dest[MAX_WIDTH][4];
625
626 /* Check if device driver can do the work */
627 if (ctx->Color.BlendEquation==GL_LOGIC_OP &&
628 !ctx->Color.ColorLogicOpEnabled) {
629 return;
630 }
631
632 /* Read span of current frame buffer pixels */
633 _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
634
635 SWRAST_CONTEXT(ctx)->BlendFunc( ctx, n, mask, rgba,
636 (const GLchan (*)[4]) dest );
637 }
638
639
640
641 /*
642 * Apply the blending operator to an array of pixels.
643 * Input: n - number of pixels in span
644 * x, y - array of pixel locations
645 * mask - boolean mask indicating which pixels to blend.
646 * In/Out: rgba - pixel values
647 */
648 void
649 _mesa_blend_pixels( GLcontext *ctx,
650 GLuint n, const GLint x[], const GLint y[],
651 GLchan rgba[][4], const GLubyte mask[] )
652 {
653 SWcontext *swrast = SWRAST_CONTEXT(ctx);
654 GLchan dest[PB_SIZE][4];
655
656 /* Check if device driver can do the work */
657 if (ctx->Color.BlendEquation==GL_LOGIC_OP &&
658 !ctx->Color.ColorLogicOpEnabled) {
659 return;
660 }
661
662 /* Read pixels from current color buffer */
663 (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
664 if (swrast->_RasterMask & ALPHABUF_BIT) {
665 _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask );
666 }
667
668 swrast->BlendFunc( ctx, n, mask, rgba, (const GLchan (*)[4])dest );
669 }