2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Regarding GL_NV_blend_square:
28 * Portions of this software may use or implement intellectual
29 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
30 * any and all warranties with respect to such intellectual property,
31 * including any use thereof or modifications thereto.
40 #include "s_alphabuf.h"
42 #include "s_context.h"
46 #if defined(USE_MMX_ASM)
48 #include "x86/common_x86_asm.h"
49 #define _BLENDAPI _ASMAPI
56 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
59 blend_noop( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
60 GLchan rgba
[][4], CONST GLchan dest
[][4] )
63 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
64 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
65 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ZERO
);
66 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
69 for (i
= 0; i
< n
; i
++) {
71 COPY_CHAN4( rgba
[i
], dest
[i
] );
78 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
81 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
82 GLchan rgba
[][4], CONST GLchan dest
[][4] )
84 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
85 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
86 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
87 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
97 * Common transparency blending mode.
100 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
101 GLchan rgba
[][4], CONST GLchan dest
[][4] )
104 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
105 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
106 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
107 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
112 const GLchan t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
115 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
116 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
117 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
118 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
120 else if (t
== CHAN_MAX
) {
121 /* 100% alpha, no-op */
125 /* This is pretty close, but Glean complains */
126 const GLint s
= CHAN_MAX
- t
;
127 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
128 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
129 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
130 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
132 /* This is slower but satisfies Glean */
133 const GLint s
= CHAN_MAX
- t
;
134 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
135 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
136 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
137 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
140 /* This satisfies Glean and should be reasonably fast */
141 /* Contributed by Nathan Hand */
143 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
146 #define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
148 const GLint r
= DIV255((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * t
) + dest
[i
][RCOMP
];
149 const GLint g
= DIV255((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * t
) + dest
[i
][GCOMP
];
150 const GLint b
= DIV255((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * t
) + dest
[i
][BCOMP
];
151 const GLint a
= DIV255((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * t
) + dest
[i
][ACOMP
];
154 #elif CHAN_BITS == 16
155 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
156 const GLint r
= (GLint
) ((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
]);
157 const GLint g
= (GLint
) ((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
]);
158 const GLint b
= (GLint
) ((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
]);
159 const GLint a
= (GLint
) ((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
]);
160 #else /* CHAN_BITS == 32 */
161 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
162 const GLfloat r
= (rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
];
163 const GLfloat g
= (rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
];
164 const GLfloat b
= (rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
];
165 const GLfloat a
= CLAMP( rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * t
+
166 CLAMP( dest
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * (1.0F
- t
);
169 ASSERT(r
<= CHAN_MAX
);
170 ASSERT(g
<= CHAN_MAX
);
171 ASSERT(b
<= CHAN_MAX
);
172 ASSERT(a
<= CHAN_MAX
);
173 rgba
[i
][RCOMP
] = (GLchan
) r
;
174 rgba
[i
][GCOMP
] = (GLchan
) g
;
175 rgba
[i
][BCOMP
] = (GLchan
) b
;
176 rgba
[i
][ACOMP
] = (GLchan
) a
;
187 static void _BLENDAPI
188 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
189 GLchan rgba
[][4], CONST GLchan dest
[][4] )
192 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
193 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
194 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
195 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
200 #if CHAN_TYPE == GL_FLOAT
201 /* don't RGB clamp to max */
202 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) + dest
[i
][ACOMP
];
203 rgba
[i
][RCOMP
] += dest
[i
][RCOMP
];
204 rgba
[i
][GCOMP
] += dest
[i
][GCOMP
];
205 rgba
[i
][BCOMP
] += dest
[i
][BCOMP
];
206 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAXF
);
208 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
209 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
210 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
211 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
212 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
213 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
214 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
215 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
224 * Blend min function (for GL_EXT_blend_minmax)
226 static void _BLENDAPI
227 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
228 GLchan rgba
[][4], CONST GLchan dest
[][4] )
231 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_MIN
);
232 ASSERT(ctx
->Color
.BlendEquationA
==GL_MIN
);
237 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
238 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
239 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
240 #if CHAN_TYPE == GL_FLOAT
241 rgba
[i
][ACOMP
] = (GLchan
) MIN2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
244 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
253 * Blend max function (for GL_EXT_blend_minmax)
255 static void _BLENDAPI
256 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
257 GLchan rgba
[][4], CONST GLchan dest
[][4] )
260 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_MAX
);
261 ASSERT(ctx
->Color
.BlendEquationA
==GL_MAX
);
266 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
267 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
268 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
269 #if CHAN_TYPE == GL_FLOAT
270 rgba
[i
][ACOMP
] = (GLchan
) MAX2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
273 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
282 * Modulate: result = src * dest
284 static void _BLENDAPI
285 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
286 GLchan rgba
[][4], CONST GLchan dest
[][4] )
293 #if CHAN_TYPE == GL_FLOAT
294 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
295 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
296 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
297 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
298 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
299 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 65535) >> 16;
300 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 65535) >> 16;
301 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 65535) >> 16;
302 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 65535) >> 16;
303 rgba
[i
][RCOMP
] = (GLchan
) r
;
304 rgba
[i
][GCOMP
] = (GLchan
) g
;
305 rgba
[i
][BCOMP
] = (GLchan
) b
;
306 rgba
[i
][ACOMP
] = (GLchan
) a
;
308 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 255) >> 8;
309 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 255) >> 8;
310 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 255) >> 8;
311 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 255) >> 8;
312 rgba
[i
][RCOMP
] = (GLchan
) r
;
313 rgba
[i
][GCOMP
] = (GLchan
) g
;
314 rgba
[i
][BCOMP
] = (GLchan
) b
;
315 rgba
[i
][ACOMP
] = (GLchan
) a
;
324 * General case blend pixels.
325 * Input: n - number of pixels
326 * mask - the usual write mask
327 * In/Out: rgba - the incoming and modified pixels
328 * Input: dest - the pixels from the dest color buffer
330 static void _BLENDAPI
331 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
332 GLchan rgba
[][4], CONST GLchan dest
[][4] )
334 const GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
335 const GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
336 const GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
337 const GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
342 #if CHAN_TYPE == GL_FLOAT
343 GLfloat Rs
, Gs
, Bs
, As
; /* Source colors */
344 GLfloat Rd
, Gd
, Bd
, Ad
; /* Dest colors */
346 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
347 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
349 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
350 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
351 GLfloat r
, g
, b
, a
; /* result color */
353 /* Incoming/source Color */
358 #if CHAN_TYPE == GL_FLOAT
360 Rs
= MIN2(Rs
, CHAN_MAXF
);
361 Gs
= MIN2(Gs
, CHAN_MAXF
);
362 Bs
= MIN2(Bs
, CHAN_MAXF
);
363 As
= MIN2(As
, CHAN_MAXF
);
366 /* Frame buffer/dest color */
371 #if CHAN_TYPE == GL_FLOAT
373 Rd
= MIN2(Rd
, CHAN_MAXF
);
374 Gd
= MIN2(Gd
, CHAN_MAXF
);
375 Bd
= MIN2(Bd
, CHAN_MAXF
);
376 Ad
= MIN2(Ad
, CHAN_MAXF
);
379 /* Source RGB factor */
380 switch (ctx
->Color
.BlendSrcRGB
) {
388 sR
= (GLfloat
) Rd
* rscale
;
389 sG
= (GLfloat
) Gd
* gscale
;
390 sB
= (GLfloat
) Bd
* bscale
;
392 case GL_ONE_MINUS_DST_COLOR
:
393 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
394 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
395 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
398 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
400 case GL_ONE_MINUS_SRC_ALPHA
:
401 sR
= sG
= sB
= 1.0F
- (GLfloat
) As
* ascale
;
404 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
406 case GL_ONE_MINUS_DST_ALPHA
:
407 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
409 case GL_SRC_ALPHA_SATURATE
:
410 if (As
< CHAN_MAX
- Ad
) {
411 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
414 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
417 case GL_CONSTANT_COLOR
:
418 sR
= ctx
->Color
.BlendColor
[0];
419 sG
= ctx
->Color
.BlendColor
[1];
420 sB
= ctx
->Color
.BlendColor
[2];
422 case GL_ONE_MINUS_CONSTANT_COLOR
:
423 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
424 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
425 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
427 case GL_CONSTANT_ALPHA
:
428 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
430 case GL_ONE_MINUS_CONSTANT_ALPHA
:
431 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
433 case GL_SRC_COLOR
: /* GL_NV_blend_square */
434 sR
= (GLfloat
) Rs
* rscale
;
435 sG
= (GLfloat
) Gs
* gscale
;
436 sB
= (GLfloat
) Bs
* bscale
;
438 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
439 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
440 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
441 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
444 /* this should never happen */
445 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
449 /* Source Alpha factor */
450 switch (ctx
->Color
.BlendSrcA
) {
458 sA
= (GLfloat
) Ad
* ascale
;
460 case GL_ONE_MINUS_DST_COLOR
:
461 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
464 sA
= (GLfloat
) As
* ascale
;
466 case GL_ONE_MINUS_SRC_ALPHA
:
467 sA
= 1.0F
- (GLfloat
) As
* ascale
;
470 sA
=(GLfloat
) Ad
* ascale
;
472 case GL_ONE_MINUS_DST_ALPHA
:
473 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
475 case GL_SRC_ALPHA_SATURATE
:
478 case GL_CONSTANT_COLOR
:
479 sA
= ctx
->Color
.BlendColor
[3];
481 case GL_ONE_MINUS_CONSTANT_COLOR
:
482 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
484 case GL_CONSTANT_ALPHA
:
485 sA
= ctx
->Color
.BlendColor
[3];
487 case GL_ONE_MINUS_CONSTANT_ALPHA
:
488 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
490 case GL_SRC_COLOR
: /* GL_NV_blend_square */
491 sA
= (GLfloat
) As
* ascale
;
493 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
494 sA
= 1.0F
- (GLfloat
) As
* ascale
;
497 /* this should never happen */
499 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
502 /* Dest RGB factor */
503 switch (ctx
->Color
.BlendDstRGB
) {
511 dR
= (GLfloat
) Rs
* rscale
;
512 dG
= (GLfloat
) Gs
* gscale
;
513 dB
= (GLfloat
) Bs
* bscale
;
515 case GL_ONE_MINUS_SRC_COLOR
:
516 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
517 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
518 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
521 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
523 case GL_ONE_MINUS_SRC_ALPHA
:
524 dR
= dG
= dB
= 1.0F
- (GLfloat
) As
* ascale
;
527 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
529 case GL_ONE_MINUS_DST_ALPHA
:
530 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
532 case GL_CONSTANT_COLOR
:
533 dR
= ctx
->Color
.BlendColor
[0];
534 dG
= ctx
->Color
.BlendColor
[1];
535 dB
= ctx
->Color
.BlendColor
[2];
537 case GL_ONE_MINUS_CONSTANT_COLOR
:
538 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
539 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
540 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
542 case GL_CONSTANT_ALPHA
:
543 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
545 case GL_ONE_MINUS_CONSTANT_ALPHA
:
546 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
548 case GL_DST_COLOR
: /* GL_NV_blend_square */
549 dR
= (GLfloat
) Rd
* rscale
;
550 dG
= (GLfloat
) Gd
* gscale
;
551 dB
= (GLfloat
) Bd
* bscale
;
553 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
554 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
555 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
556 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
559 /* this should never happen */
561 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
564 /* Dest Alpha factor */
565 switch (ctx
->Color
.BlendDstA
) {
573 dA
= (GLfloat
) As
* ascale
;
575 case GL_ONE_MINUS_SRC_COLOR
:
576 dA
= 1.0F
- (GLfloat
) As
* ascale
;
579 dA
= (GLfloat
) As
* ascale
;
581 case GL_ONE_MINUS_SRC_ALPHA
:
582 dA
= 1.0F
- (GLfloat
) As
* ascale
;
585 dA
= (GLfloat
) Ad
* ascale
;
587 case GL_ONE_MINUS_DST_ALPHA
:
588 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
590 case GL_CONSTANT_COLOR
:
591 dA
= ctx
->Color
.BlendColor
[3];
593 case GL_ONE_MINUS_CONSTANT_COLOR
:
594 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
596 case GL_CONSTANT_ALPHA
:
597 dA
= ctx
->Color
.BlendColor
[3];
599 case GL_ONE_MINUS_CONSTANT_ALPHA
:
600 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
602 case GL_DST_COLOR
: /* GL_NV_blend_square */
603 dA
= (GLfloat
) Ad
* ascale
;
605 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
606 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
609 /* this should never happen */
611 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
615 /* Due to round-off problems we have to clamp against zero. */
616 /* Optimization: we don't have to do this for all src & dst factors */
617 if (dA
< 0.0F
) dA
= 0.0F
;
618 if (dR
< 0.0F
) dR
= 0.0F
;
619 if (dG
< 0.0F
) dG
= 0.0F
;
620 if (dB
< 0.0F
) dB
= 0.0F
;
621 if (sA
< 0.0F
) sA
= 0.0F
;
622 if (sR
< 0.0F
) sR
= 0.0F
;
623 if (sG
< 0.0F
) sG
= 0.0F
;
624 if (sB
< 0.0F
) sB
= 0.0F
;
635 /* compute blended color */
636 #if CHAN_TYPE == GL_FLOAT
637 if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
) {
638 r
= Rs
* sR
+ Rd
* dR
;
639 g
= Gs
* sG
+ Gd
* dG
;
640 b
= Bs
* sB
+ Bd
* dB
;
641 a
= As
* sA
+ Ad
* dA
;
643 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_SUBTRACT
) {
644 r
= Rs
* sR
- Rd
* dR
;
645 g
= Gs
* sG
- Gd
* dG
;
646 b
= Bs
* sB
- Bd
* dB
;
647 a
= As
* sA
- Ad
* dA
;
649 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_REVERSE_SUBTRACT
) {
650 r
= Rd
* dR
- Rs
* sR
;
651 g
= Gd
* dG
- Gs
* sG
;
652 b
= Bd
* dB
- Bs
* sB
;
653 a
= Ad
* dA
- As
* sA
;
655 else if (ctx
->Color
.BlendEquationRGB
==GL_MIN
) {
660 else if (ctx
->Color
.BlendEquationRGB
==GL_MAX
) {
666 /* should never get here */
667 r
= g
= b
= 0.0F
; /* silence uninitialized var warning */
668 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
671 if (ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
) {
672 a
= As
* sA
+ Ad
* dA
;
674 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_SUBTRACT
) {
675 a
= As
* sA
- Ad
* dA
;
677 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_REVERSE_SUBTRACT
) {
678 a
= Ad
* dA
- As
* sA
;
680 else if (ctx
->Color
.BlendEquationA
==GL_MIN
) {
683 else if (ctx
->Color
.BlendEquationA
==GL_MAX
) {
687 /* should never get here */
688 a
= 0.0F
; /* silence uninitialized var warning */
689 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
693 rgba
[i
][RCOMP
] = MAX2( r
, 0.0F
);
694 rgba
[i
][GCOMP
] = MAX2( g
, 0.0F
);
695 rgba
[i
][BCOMP
] = MAX2( b
, 0.0F
);
696 rgba
[i
][ACOMP
] = CLAMP( a
, 0.0F
, CHAN_MAXF
);
698 if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
) {
699 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
700 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
701 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
703 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_SUBTRACT
) {
704 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
705 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
706 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
708 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_REVERSE_SUBTRACT
) {
709 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
710 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
711 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
713 else if (ctx
->Color
.BlendEquationRGB
==GL_MIN
) {
718 else if (ctx
->Color
.BlendEquationRGB
==GL_MAX
) {
724 /* should never get here */
725 r
= g
= b
= 0.0F
; /* silence uninitialized var warning */
726 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
729 if (ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
) {
730 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
732 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_SUBTRACT
) {
733 a
= As
* sA
- Ad
* dA
+ 0.5F
;
735 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_REVERSE_SUBTRACT
) {
736 a
= Ad
* dA
- As
* sA
+ 0.5F
;
738 else if (ctx
->Color
.BlendEquationA
==GL_MIN
) {
741 else if (ctx
->Color
.BlendEquationA
==GL_MAX
) {
745 /* should never get here */
746 a
= 0.0F
; /* silence uninitialized var warning */
747 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
751 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
752 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
753 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
754 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
762 * Analyze current blending parameters to pick fastest blending function.
763 * Result: the ctx->Color.BlendFunc pointer is updated.
765 void _swrast_choose_blend_func( GLcontext
*ctx
)
767 const GLenum eq
= ctx
->Color
.BlendEquationRGB
;
768 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
769 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
770 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
771 const GLenum dstA
= ctx
->Color
.BlendDstA
;
773 if (ctx
->Color
.BlendEquationRGB
!= ctx
->Color
.BlendEquationA
) {
774 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
776 else if (eq
==GL_MIN
) {
777 /* Note: GL_MIN ignores the blending weight factors */
778 #if defined(USE_MMX_ASM)
780 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_min
;
784 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
786 else if (eq
==GL_MAX
) {
787 /* Note: GL_MAX ignores the blending weight factors */
788 #if defined(USE_MMX_ASM)
790 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_max
;
794 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
796 else if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
797 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
799 else if (eq
==GL_FUNC_ADD
&& srcRGB
==GL_SRC_ALPHA
800 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
801 #if defined(USE_MMX_ASM)
803 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
807 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
809 else if (eq
==GL_FUNC_ADD
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
810 #if defined(USE_MMX_ASM)
812 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_add
;
816 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
818 else if (((eq
==GL_FUNC_ADD
|| eq
==GL_FUNC_REVERSE_SUBTRACT
)
819 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
821 ((eq
==GL_FUNC_ADD
|| eq
==GL_FUNC_SUBTRACT
)
822 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
823 #if defined(USE_MMX_ASM)
825 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_modulate
;
829 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
831 else if (eq
==GL_FUNC_ADD
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
832 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
834 else if (eq
==GL_FUNC_ADD
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
835 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
838 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
845 * Apply the blending operator to a span of pixels.
846 * We can handle horizontal runs of pixels (spans) or arrays of x/y
850 _swrast_blend_span( GLcontext
*ctx
, const struct sw_span
*span
,
853 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
854 GLchan framebuffer
[MAX_WIDTH
][4];
856 ASSERT(span
->end
<= MAX_WIDTH
);
857 ASSERT(span
->arrayMask
& SPAN_RGBA
);
858 ASSERT(!ctx
->Color
._LogicOpEnabled
);
860 /* Read span of current frame buffer pixels */
861 if (span
->arrayMask
& SPAN_XY
) {
862 /* array of x/y pixel coords */
863 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, span
->end
,
864 span
->array
->x
, span
->array
->y
,
865 framebuffer
, span
->array
->mask
);
866 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
867 _swrast_read_alpha_pixels( ctx
, span
->end
,
868 span
->array
->x
, span
->array
->y
,
869 framebuffer
, span
->array
->mask
);
873 /* horizontal run of pixels */
874 _swrast_read_rgba_span( ctx
, ctx
->DrawBuffer
, span
->end
,
875 span
->x
, span
->y
, framebuffer
);
878 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, span
->end
, span
->array
->mask
, rgba
,
879 (const GLchan (*)[4]) framebuffer
);