1 /* $Id: s_blend.c,v 1.26 2003/03/25 02:23:45 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
34 #include "s_alphabuf.h"
36 #include "s_context.h"
40 #if defined(USE_MMX_ASM)
42 #include "X86/common_x86_asm.h"
43 #define _BLENDAPI _ASMAPI
50 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
53 blend_noop( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
54 GLchan rgba
[][4], CONST GLchan dest
[][4] )
57 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
58 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ZERO
);
59 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
62 for (i
= 0; i
< n
; i
++) {
64 COPY_CHAN4( rgba
[i
], dest
[i
] );
71 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
74 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
75 GLchan rgba
[][4], CONST GLchan dest
[][4] )
77 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
78 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
79 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
89 * Common transparency blending mode.
92 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
93 GLchan rgba
[][4], CONST GLchan dest
[][4] )
96 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
97 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
98 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
103 const GLchan t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
106 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
107 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
108 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
109 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
111 else if (t
== CHAN_MAX
) {
112 /* 100% alpha, no-op */
116 /* This is pretty close, but Glean complains */
117 const GLint s
= CHAN_MAX
- t
;
118 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
119 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
120 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
121 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
123 /* This is slower but satisfies Glean */
124 const GLint s
= CHAN_MAX
- t
;
125 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
126 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
127 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
128 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
131 /* This satisfies Glean and should be reasonably fast */
132 /* Contributed by Nathan Hand */
134 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
137 #define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
139 const GLint r
= DIV255((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * t
) + dest
[i
][RCOMP
];
140 const GLint g
= DIV255((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * t
) + dest
[i
][GCOMP
];
141 const GLint b
= DIV255((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * t
) + dest
[i
][BCOMP
];
142 const GLint a
= DIV255((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * t
) + dest
[i
][ACOMP
];
145 #elif CHAN_BITS == 16
146 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
147 const GLint r
= (GLint
) ((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
]);
148 const GLint g
= (GLint
) ((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
]);
149 const GLint b
= (GLint
) ((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
]);
150 const GLint a
= (GLint
) ((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
]);
151 #else /* CHAN_BITS == 32 */
152 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
153 const GLfloat r
= (rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
];
154 const GLfloat g
= (rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
];
155 const GLfloat b
= (rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
];
156 const GLfloat a
= CLAMP( rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * t
+
157 CLAMP( dest
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * (1.0F
- t
);
160 ASSERT(r
<= CHAN_MAX
);
161 ASSERT(g
<= CHAN_MAX
);
162 ASSERT(b
<= CHAN_MAX
);
163 ASSERT(a
<= CHAN_MAX
);
164 rgba
[i
][RCOMP
] = (GLchan
) r
;
165 rgba
[i
][GCOMP
] = (GLchan
) g
;
166 rgba
[i
][BCOMP
] = (GLchan
) b
;
167 rgba
[i
][ACOMP
] = (GLchan
) a
;
178 static void _BLENDAPI
179 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
180 GLchan rgba
[][4], CONST GLchan dest
[][4] )
183 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
184 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
185 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
190 #if CHAN_TYPE == GL_FLOAT
191 /* don't RGB clamp to max */
192 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) + dest
[i
][ACOMP
];
193 rgba
[i
][RCOMP
] += dest
[i
][RCOMP
];
194 rgba
[i
][GCOMP
] += dest
[i
][GCOMP
];
195 rgba
[i
][BCOMP
] += dest
[i
][BCOMP
];
196 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAXF
);
198 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
199 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
200 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
201 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
202 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
203 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
204 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
205 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
214 * Blend min function (for GL_EXT_blend_minmax)
216 static void _BLENDAPI
217 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
218 GLchan rgba
[][4], CONST GLchan dest
[][4] )
221 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
226 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
227 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
228 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
229 #if CHAN_TYPE == GL_FLOAT
230 rgba
[i
][ACOMP
] = (GLchan
) MIN2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
233 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
242 * Blend max function (for GL_EXT_blend_minmax)
244 static void _BLENDAPI
245 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
246 GLchan rgba
[][4], CONST GLchan dest
[][4] )
249 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
254 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
255 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
256 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
257 #if CHAN_TYPE == GL_FLOAT
258 rgba
[i
][ACOMP
] = (GLchan
) MAX2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
261 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
270 * Modulate: result = src * dest
272 static void _BLENDAPI
273 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
274 GLchan rgba
[][4], CONST GLchan dest
[][4] )
281 #if CHAN_TYPE == GL_FLOAT
282 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
283 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
284 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
285 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
286 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
287 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 65535) >> 16;
288 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 65535) >> 16;
289 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 65535) >> 16;
290 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 65535) >> 16;
291 rgba
[i
][RCOMP
] = (GLchan
) r
;
292 rgba
[i
][GCOMP
] = (GLchan
) g
;
293 rgba
[i
][BCOMP
] = (GLchan
) b
;
294 rgba
[i
][ACOMP
] = (GLchan
) a
;
296 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 255) >> 8;
297 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 255) >> 8;
298 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 255) >> 8;
299 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 255) >> 8;
300 rgba
[i
][RCOMP
] = (GLchan
) r
;
301 rgba
[i
][GCOMP
] = (GLchan
) g
;
302 rgba
[i
][BCOMP
] = (GLchan
) b
;
303 rgba
[i
][ACOMP
] = (GLchan
) a
;
312 * General case blend pixels.
313 * Input: n - number of pixels
314 * mask - the usual write mask
315 * In/Out: rgba - the incoming and modified pixels
316 * Input: dest - the pixels from the dest color buffer
318 static void _BLENDAPI
319 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
320 GLchan rgba
[][4], CONST GLchan dest
[][4] )
322 const GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
323 const GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
324 const GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
325 const GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
330 #if CHAN_TYPE == GL_FLOAT
331 GLfloat Rs
, Gs
, Bs
, As
; /* Source colors */
332 GLfloat Rd
, Gd
, Bd
, Ad
; /* Dest colors */
334 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
335 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
337 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
338 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
339 GLfloat r
, g
, b
, a
; /* result color */
341 /* Incoming/source Color */
346 #if CHAN_TYPE == GL_FLOAT
348 Rs
= MIN2(Rs
, CHAN_MAXF
);
349 Gs
= MIN2(Gs
, CHAN_MAXF
);
350 Bs
= MIN2(Bs
, CHAN_MAXF
);
351 As
= MIN2(As
, CHAN_MAXF
);
354 /* Frame buffer/dest color */
359 #if CHAN_TYPE == GL_FLOAT
361 Rd
= MIN2(Rd
, CHAN_MAXF
);
362 Gd
= MIN2(Gd
, CHAN_MAXF
);
363 Bd
= MIN2(Bd
, CHAN_MAXF
);
364 Ad
= MIN2(Ad
, CHAN_MAXF
);
367 /* Source RGB factor */
368 switch (ctx
->Color
.BlendSrcRGB
) {
376 sR
= (GLfloat
) Rd
* rscale
;
377 sG
= (GLfloat
) Gd
* gscale
;
378 sB
= (GLfloat
) Bd
* bscale
;
380 case GL_ONE_MINUS_DST_COLOR
:
381 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
382 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
383 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
386 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
388 case GL_ONE_MINUS_SRC_ALPHA
:
389 sR
= sG
= sB
= 1.0F
- (GLfloat
) As
* ascale
;
392 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
394 case GL_ONE_MINUS_DST_ALPHA
:
395 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
397 case GL_SRC_ALPHA_SATURATE
:
398 if (As
< CHAN_MAX
- Ad
) {
399 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
402 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
405 case GL_CONSTANT_COLOR
:
406 sR
= ctx
->Color
.BlendColor
[0];
407 sG
= ctx
->Color
.BlendColor
[1];
408 sB
= ctx
->Color
.BlendColor
[2];
410 case GL_ONE_MINUS_CONSTANT_COLOR
:
411 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
412 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
413 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
415 case GL_CONSTANT_ALPHA
:
416 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
418 case GL_ONE_MINUS_CONSTANT_ALPHA
:
419 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
421 case GL_SRC_COLOR
: /* GL_NV_blend_square */
422 sR
= (GLfloat
) Rs
* rscale
;
423 sG
= (GLfloat
) Gs
* gscale
;
424 sB
= (GLfloat
) Bs
* bscale
;
426 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
427 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
428 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
429 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
432 /* this should never happen */
433 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
437 /* Source Alpha factor */
438 switch (ctx
->Color
.BlendSrcA
) {
446 sA
= (GLfloat
) Ad
* ascale
;
448 case GL_ONE_MINUS_DST_COLOR
:
449 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
452 sA
= (GLfloat
) As
* ascale
;
454 case GL_ONE_MINUS_SRC_ALPHA
:
455 sA
= 1.0F
- (GLfloat
) As
* ascale
;
458 sA
=(GLfloat
) Ad
* ascale
;
460 case GL_ONE_MINUS_DST_ALPHA
:
461 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
463 case GL_SRC_ALPHA_SATURATE
:
466 case GL_CONSTANT_COLOR
:
467 sA
= ctx
->Color
.BlendColor
[3];
469 case GL_ONE_MINUS_CONSTANT_COLOR
:
470 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
472 case GL_CONSTANT_ALPHA
:
473 sA
= ctx
->Color
.BlendColor
[3];
475 case GL_ONE_MINUS_CONSTANT_ALPHA
:
476 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
478 case GL_SRC_COLOR
: /* GL_NV_blend_square */
479 sA
= (GLfloat
) As
* ascale
;
481 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
482 sA
= 1.0F
- (GLfloat
) As
* ascale
;
485 /* this should never happen */
487 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
490 /* Dest RGB factor */
491 switch (ctx
->Color
.BlendDstRGB
) {
499 dR
= (GLfloat
) Rs
* rscale
;
500 dG
= (GLfloat
) Gs
* gscale
;
501 dB
= (GLfloat
) Bs
* bscale
;
503 case GL_ONE_MINUS_SRC_COLOR
:
504 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
505 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
506 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
509 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
511 case GL_ONE_MINUS_SRC_ALPHA
:
512 dR
= dG
= dB
= 1.0F
- (GLfloat
) As
* ascale
;
515 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
517 case GL_ONE_MINUS_DST_ALPHA
:
518 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
520 case GL_CONSTANT_COLOR
:
521 dR
= ctx
->Color
.BlendColor
[0];
522 dG
= ctx
->Color
.BlendColor
[1];
523 dB
= ctx
->Color
.BlendColor
[2];
525 case GL_ONE_MINUS_CONSTANT_COLOR
:
526 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
527 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
528 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
530 case GL_CONSTANT_ALPHA
:
531 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
533 case GL_ONE_MINUS_CONSTANT_ALPHA
:
534 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
536 case GL_DST_COLOR
: /* GL_NV_blend_square */
537 dR
= (GLfloat
) Rd
* rscale
;
538 dG
= (GLfloat
) Gd
* gscale
;
539 dB
= (GLfloat
) Bd
* bscale
;
541 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
542 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
543 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
544 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
547 /* this should never happen */
549 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
552 /* Dest Alpha factor */
553 switch (ctx
->Color
.BlendDstA
) {
561 dA
= (GLfloat
) As
* ascale
;
563 case GL_ONE_MINUS_SRC_COLOR
:
564 dA
= 1.0F
- (GLfloat
) As
* ascale
;
567 dA
= (GLfloat
) As
* ascale
;
569 case GL_ONE_MINUS_SRC_ALPHA
:
570 dA
= 1.0F
- (GLfloat
) As
* ascale
;
573 dA
= (GLfloat
) Ad
* ascale
;
575 case GL_ONE_MINUS_DST_ALPHA
:
576 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
578 case GL_CONSTANT_COLOR
:
579 dA
= ctx
->Color
.BlendColor
[3];
581 case GL_ONE_MINUS_CONSTANT_COLOR
:
582 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
584 case GL_CONSTANT_ALPHA
:
585 dA
= ctx
->Color
.BlendColor
[3];
587 case GL_ONE_MINUS_CONSTANT_ALPHA
:
588 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
590 case GL_DST_COLOR
: /* GL_NV_blend_square */
591 dA
= (GLfloat
) Ad
* ascale
;
593 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
594 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
597 /* this should never happen */
599 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
603 /* Due to round-off problems we have to clamp against zero. */
604 /* Optimization: we don't have to do this for all src & dst factors */
605 if (dA
< 0.0F
) dA
= 0.0F
;
606 if (dR
< 0.0F
) dR
= 0.0F
;
607 if (dG
< 0.0F
) dG
= 0.0F
;
608 if (dB
< 0.0F
) dB
= 0.0F
;
609 if (sA
< 0.0F
) sA
= 0.0F
;
610 if (sR
< 0.0F
) sR
= 0.0F
;
611 if (sG
< 0.0F
) sG
= 0.0F
;
612 if (sB
< 0.0F
) sB
= 0.0F
;
623 /* compute blended color */
624 #if CHAN_TYPE == GL_FLOAT
625 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
626 r
= Rs
* sR
+ Rd
* dR
;
627 g
= Gs
* sG
+ Gd
* dG
;
628 b
= Bs
* sB
+ Bd
* dB
;
629 a
= As
* sA
+ Ad
* dA
;
631 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
632 r
= Rs
* sR
- Rd
* dR
;
633 g
= Gs
* sG
- Gd
* dG
;
634 b
= Bs
* sB
- Bd
* dB
;
635 a
= As
* sA
- Ad
* dA
;
637 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
638 r
= Rd
* dR
- Rs
* sR
;
639 g
= Gd
* dG
- Gs
* sG
;
640 b
= Bd
* dB
- Bs
* sB
;
641 a
= Ad
* dA
- As
* sA
;
644 /* should never get here */
645 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
646 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
650 rgba
[i
][RCOMP
] = MAX2( r
, 0.0F
);
651 rgba
[i
][GCOMP
] = MAX2( g
, 0.0F
);
652 rgba
[i
][BCOMP
] = MAX2( b
, 0.0F
);
653 rgba
[i
][ACOMP
] = CLAMP( a
, 0.0F
, CHAN_MAXF
);
655 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
656 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
657 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
658 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
659 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
661 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
662 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
663 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
664 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
665 a
= As
* sA
- Ad
* dA
+ 0.5F
;
667 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
668 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
669 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
670 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
671 a
= Ad
* dA
- As
* sA
+ 0.5F
;
674 /* should never get here */
675 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
676 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
680 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
681 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
682 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
683 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
694 * Analyze current blending parameters to pick fastest blending function.
695 * Result: the ctx->Color.BlendFunc pointer is updated.
697 void _swrast_choose_blend_func( GLcontext
*ctx
)
699 const GLenum eq
= ctx
->Color
.BlendEquation
;
700 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
701 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
702 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
703 const GLenum dstA
= ctx
->Color
.BlendDstA
;
705 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
706 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
708 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
709 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
710 #if defined(USE_MMX_ASM)
712 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
716 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
718 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
719 #if defined(USE_MMX_ASM)
721 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_add
;
725 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
727 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
728 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
730 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
731 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
732 #if defined(USE_MMX_ASM)
734 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_modulate
;
738 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
740 else if (eq
==GL_MIN_EXT
) {
741 #if defined(USE_MMX_ASM)
743 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_min
;
747 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
749 else if (eq
==GL_MAX_EXT
) {
750 #if defined(USE_MMX_ASM)
752 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_max
;
756 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
758 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
759 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
761 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
762 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
765 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
772 * Apply the blending operator to a span of pixels.
773 * We can handle horizontal runs of pixels (spans) or arrays of x/y
777 _swrast_blend_span( GLcontext
*ctx
, const struct sw_span
*span
,
780 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
781 GLchan framebuffer
[MAX_WIDTH
][4];
783 ASSERT(span
->end
<= MAX_WIDTH
);
784 ASSERT(span
->arrayMask
& SPAN_RGBA
);
785 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
787 /* Read span of current frame buffer pixels */
788 if (span
->arrayMask
& SPAN_XY
) {
789 /* array of x/y pixel coords */
790 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, span
->end
,
791 span
->array
->x
, span
->array
->y
,
792 framebuffer
, span
->array
->mask
);
793 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
794 _swrast_read_alpha_pixels( ctx
, span
->end
,
795 span
->array
->x
, span
->array
->y
,
796 framebuffer
, span
->array
->mask
);
800 /* horizontal run of pixels */
801 _swrast_read_rgba_span( ctx
, ctx
->DrawBuffer
, span
->end
,
802 span
->x
, span
->y
, framebuffer
);
805 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, span
->end
, span
->array
->mask
, rgba
,
806 (const GLchan (*)[4]) framebuffer
);