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