2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 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.
32 #include "s_alphabuf.h"
34 #include "s_context.h"
38 #if defined(USE_MMX_ASM)
40 #include "x86/common_x86_asm.h"
41 #define _BLENDAPI _ASMAPI
48 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
51 blend_noop( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
52 GLchan rgba
[][4], CONST GLchan dest
[][4] )
55 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
56 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ZERO
);
57 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
60 for (i
= 0; i
< n
; i
++) {
62 COPY_CHAN4( rgba
[i
], dest
[i
] );
69 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
72 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
73 GLchan rgba
[][4], CONST GLchan dest
[][4] )
75 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
76 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
77 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
87 * Common transparency blending mode.
90 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
91 GLchan rgba
[][4], CONST GLchan dest
[][4] )
94 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
95 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
96 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
101 const GLchan t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
104 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
105 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
106 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
107 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
109 else if (t
== CHAN_MAX
) {
110 /* 100% alpha, no-op */
114 /* This is pretty close, but Glean complains */
115 const GLint s
= CHAN_MAX
- t
;
116 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
117 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
118 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
119 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
121 /* This is slower but satisfies Glean */
122 const GLint s
= CHAN_MAX
- t
;
123 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
124 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
125 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
126 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
129 /* This satisfies Glean and should be reasonably fast */
130 /* Contributed by Nathan Hand */
132 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
135 #define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
137 const GLint r
= DIV255((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * t
) + dest
[i
][RCOMP
];
138 const GLint g
= DIV255((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * t
) + dest
[i
][GCOMP
];
139 const GLint b
= DIV255((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * t
) + dest
[i
][BCOMP
];
140 const GLint a
= DIV255((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * t
) + dest
[i
][ACOMP
];
143 #elif CHAN_BITS == 16
144 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
145 const GLint r
= (GLint
) ((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
]);
146 const GLint g
= (GLint
) ((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
]);
147 const GLint b
= (GLint
) ((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
]);
148 const GLint a
= (GLint
) ((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
]);
149 #else /* CHAN_BITS == 32 */
150 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
151 const GLfloat r
= (rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
];
152 const GLfloat g
= (rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
];
153 const GLfloat b
= (rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
];
154 const GLfloat a
= CLAMP( rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * t
+
155 CLAMP( dest
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * (1.0F
- t
);
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
;
176 static void _BLENDAPI
177 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
178 GLchan rgba
[][4], CONST GLchan dest
[][4] )
181 ASSERT(ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
);
182 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
183 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
188 #if CHAN_TYPE == GL_FLOAT
189 /* don't RGB clamp to max */
190 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) + dest
[i
][ACOMP
];
191 rgba
[i
][RCOMP
] += dest
[i
][RCOMP
];
192 rgba
[i
][GCOMP
] += dest
[i
][GCOMP
];
193 rgba
[i
][BCOMP
] += dest
[i
][BCOMP
];
194 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAXF
);
196 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
197 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
198 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
199 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
200 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
201 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
202 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
203 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
212 * Blend min function (for GL_EXT_blend_minmax)
214 static void _BLENDAPI
215 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
216 GLchan rgba
[][4], CONST GLchan dest
[][4] )
219 ASSERT(ctx
->Color
.BlendEquation
==GL_MIN_EXT
);
224 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
225 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
226 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
227 #if CHAN_TYPE == GL_FLOAT
228 rgba
[i
][ACOMP
] = (GLchan
) MIN2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
231 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
240 * Blend max function (for GL_EXT_blend_minmax)
242 static void _BLENDAPI
243 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
244 GLchan rgba
[][4], CONST GLchan dest
[][4] )
247 ASSERT(ctx
->Color
.BlendEquation
==GL_MAX_EXT
);
252 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
253 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
254 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
255 #if CHAN_TYPE == GL_FLOAT
256 rgba
[i
][ACOMP
] = (GLchan
) MAX2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
259 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
268 * Modulate: result = src * dest
270 static void _BLENDAPI
271 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
272 GLchan rgba
[][4], CONST GLchan dest
[][4] )
279 #if CHAN_TYPE == GL_FLOAT
280 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
281 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
282 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
283 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
284 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
285 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 65535) >> 16;
286 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 65535) >> 16;
287 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 65535) >> 16;
288 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 65535) >> 16;
289 rgba
[i
][RCOMP
] = (GLchan
) r
;
290 rgba
[i
][GCOMP
] = (GLchan
) g
;
291 rgba
[i
][BCOMP
] = (GLchan
) b
;
292 rgba
[i
][ACOMP
] = (GLchan
) a
;
294 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 255) >> 8;
295 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 255) >> 8;
296 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 255) >> 8;
297 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 255) >> 8;
298 rgba
[i
][RCOMP
] = (GLchan
) r
;
299 rgba
[i
][GCOMP
] = (GLchan
) g
;
300 rgba
[i
][BCOMP
] = (GLchan
) b
;
301 rgba
[i
][ACOMP
] = (GLchan
) a
;
310 * General case blend pixels.
311 * Input: n - number of pixels
312 * mask - the usual write mask
313 * In/Out: rgba - the incoming and modified pixels
314 * Input: dest - the pixels from the dest color buffer
316 static void _BLENDAPI
317 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
318 GLchan rgba
[][4], CONST GLchan dest
[][4] )
320 const GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
321 const GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
322 const GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
323 const GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
328 #if CHAN_TYPE == GL_FLOAT
329 GLfloat Rs
, Gs
, Bs
, As
; /* Source colors */
330 GLfloat Rd
, Gd
, Bd
, Ad
; /* Dest colors */
332 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
333 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
335 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
336 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
337 GLfloat r
, g
, b
, a
; /* result color */
339 /* Incoming/source Color */
344 #if CHAN_TYPE == GL_FLOAT
346 Rs
= MIN2(Rs
, CHAN_MAXF
);
347 Gs
= MIN2(Gs
, CHAN_MAXF
);
348 Bs
= MIN2(Bs
, CHAN_MAXF
);
349 As
= MIN2(As
, CHAN_MAXF
);
352 /* Frame buffer/dest color */
357 #if CHAN_TYPE == GL_FLOAT
359 Rd
= MIN2(Rd
, CHAN_MAXF
);
360 Gd
= MIN2(Gd
, CHAN_MAXF
);
361 Bd
= MIN2(Bd
, CHAN_MAXF
);
362 Ad
= MIN2(Ad
, CHAN_MAXF
);
365 /* Source RGB factor */
366 switch (ctx
->Color
.BlendSrcRGB
) {
374 sR
= (GLfloat
) Rd
* rscale
;
375 sG
= (GLfloat
) Gd
* gscale
;
376 sB
= (GLfloat
) Bd
* bscale
;
378 case GL_ONE_MINUS_DST_COLOR
:
379 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
380 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
381 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
384 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
386 case GL_ONE_MINUS_SRC_ALPHA
:
387 sR
= sG
= sB
= 1.0F
- (GLfloat
) As
* ascale
;
390 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
392 case GL_ONE_MINUS_DST_ALPHA
:
393 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
395 case GL_SRC_ALPHA_SATURATE
:
396 if (As
< CHAN_MAX
- Ad
) {
397 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
400 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
403 case GL_CONSTANT_COLOR
:
404 sR
= ctx
->Color
.BlendColor
[0];
405 sG
= ctx
->Color
.BlendColor
[1];
406 sB
= ctx
->Color
.BlendColor
[2];
408 case GL_ONE_MINUS_CONSTANT_COLOR
:
409 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
410 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
411 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
413 case GL_CONSTANT_ALPHA
:
414 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
416 case GL_ONE_MINUS_CONSTANT_ALPHA
:
417 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
419 case GL_SRC_COLOR
: /* GL_NV_blend_square */
420 sR
= (GLfloat
) Rs
* rscale
;
421 sG
= (GLfloat
) Gs
* gscale
;
422 sB
= (GLfloat
) Bs
* bscale
;
424 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
425 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
426 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
427 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
430 /* this should never happen */
431 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
435 /* Source Alpha factor */
436 switch (ctx
->Color
.BlendSrcA
) {
444 sA
= (GLfloat
) Ad
* ascale
;
446 case GL_ONE_MINUS_DST_COLOR
:
447 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
450 sA
= (GLfloat
) As
* ascale
;
452 case GL_ONE_MINUS_SRC_ALPHA
:
453 sA
= 1.0F
- (GLfloat
) As
* ascale
;
456 sA
=(GLfloat
) Ad
* ascale
;
458 case GL_ONE_MINUS_DST_ALPHA
:
459 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
461 case GL_SRC_ALPHA_SATURATE
:
464 case GL_CONSTANT_COLOR
:
465 sA
= ctx
->Color
.BlendColor
[3];
467 case GL_ONE_MINUS_CONSTANT_COLOR
:
468 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
470 case GL_CONSTANT_ALPHA
:
471 sA
= ctx
->Color
.BlendColor
[3];
473 case GL_ONE_MINUS_CONSTANT_ALPHA
:
474 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
476 case GL_SRC_COLOR
: /* GL_NV_blend_square */
477 sA
= (GLfloat
) As
* ascale
;
479 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
480 sA
= 1.0F
- (GLfloat
) As
* ascale
;
483 /* this should never happen */
485 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
488 /* Dest RGB factor */
489 switch (ctx
->Color
.BlendDstRGB
) {
497 dR
= (GLfloat
) Rs
* rscale
;
498 dG
= (GLfloat
) Gs
* gscale
;
499 dB
= (GLfloat
) Bs
* bscale
;
501 case GL_ONE_MINUS_SRC_COLOR
:
502 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
503 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
504 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
507 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
509 case GL_ONE_MINUS_SRC_ALPHA
:
510 dR
= dG
= dB
= 1.0F
- (GLfloat
) As
* ascale
;
513 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
515 case GL_ONE_MINUS_DST_ALPHA
:
516 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
518 case GL_CONSTANT_COLOR
:
519 dR
= ctx
->Color
.BlendColor
[0];
520 dG
= ctx
->Color
.BlendColor
[1];
521 dB
= ctx
->Color
.BlendColor
[2];
523 case GL_ONE_MINUS_CONSTANT_COLOR
:
524 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
525 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
526 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
528 case GL_CONSTANT_ALPHA
:
529 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
531 case GL_ONE_MINUS_CONSTANT_ALPHA
:
532 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
534 case GL_DST_COLOR
: /* GL_NV_blend_square */
535 dR
= (GLfloat
) Rd
* rscale
;
536 dG
= (GLfloat
) Gd
* gscale
;
537 dB
= (GLfloat
) Bd
* bscale
;
539 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
540 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
541 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
542 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
545 /* this should never happen */
547 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
550 /* Dest Alpha factor */
551 switch (ctx
->Color
.BlendDstA
) {
559 dA
= (GLfloat
) As
* ascale
;
561 case GL_ONE_MINUS_SRC_COLOR
:
562 dA
= 1.0F
- (GLfloat
) As
* ascale
;
565 dA
= (GLfloat
) As
* ascale
;
567 case GL_ONE_MINUS_SRC_ALPHA
:
568 dA
= 1.0F
- (GLfloat
) As
* ascale
;
571 dA
= (GLfloat
) Ad
* ascale
;
573 case GL_ONE_MINUS_DST_ALPHA
:
574 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
576 case GL_CONSTANT_COLOR
:
577 dA
= ctx
->Color
.BlendColor
[3];
579 case GL_ONE_MINUS_CONSTANT_COLOR
:
580 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
582 case GL_CONSTANT_ALPHA
:
583 dA
= ctx
->Color
.BlendColor
[3];
585 case GL_ONE_MINUS_CONSTANT_ALPHA
:
586 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
588 case GL_DST_COLOR
: /* GL_NV_blend_square */
589 dA
= (GLfloat
) Ad
* ascale
;
591 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
592 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
595 /* this should never happen */
597 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
601 /* Due to round-off problems we have to clamp against zero. */
602 /* Optimization: we don't have to do this for all src & dst factors */
603 if (dA
< 0.0F
) dA
= 0.0F
;
604 if (dR
< 0.0F
) dR
= 0.0F
;
605 if (dG
< 0.0F
) dG
= 0.0F
;
606 if (dB
< 0.0F
) dB
= 0.0F
;
607 if (sA
< 0.0F
) sA
= 0.0F
;
608 if (sR
< 0.0F
) sR
= 0.0F
;
609 if (sG
< 0.0F
) sG
= 0.0F
;
610 if (sB
< 0.0F
) sB
= 0.0F
;
621 /* compute blended color */
622 #if CHAN_TYPE == GL_FLOAT
623 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
624 r
= Rs
* sR
+ Rd
* dR
;
625 g
= Gs
* sG
+ Gd
* dG
;
626 b
= Bs
* sB
+ Bd
* dB
;
627 a
= As
* sA
+ Ad
* dA
;
629 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
630 r
= Rs
* sR
- Rd
* dR
;
631 g
= Gs
* sG
- Gd
* dG
;
632 b
= Bs
* sB
- Bd
* dB
;
633 a
= As
* sA
- Ad
* dA
;
635 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
636 r
= Rd
* dR
- Rs
* sR
;
637 g
= Gd
* dG
- Gs
* sG
;
638 b
= Bd
* dB
- Bs
* sB
;
639 a
= Ad
* dA
- As
* sA
;
642 /* should never get here */
643 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
644 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
648 rgba
[i
][RCOMP
] = MAX2( r
, 0.0F
);
649 rgba
[i
][GCOMP
] = MAX2( g
, 0.0F
);
650 rgba
[i
][BCOMP
] = MAX2( b
, 0.0F
);
651 rgba
[i
][ACOMP
] = CLAMP( a
, 0.0F
, CHAN_MAXF
);
653 if (ctx
->Color
.BlendEquation
==GL_FUNC_ADD_EXT
) {
654 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
655 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
656 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
657 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
659 else if (ctx
->Color
.BlendEquation
==GL_FUNC_SUBTRACT_EXT
) {
660 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
661 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
662 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
663 a
= As
* sA
- Ad
* dA
+ 0.5F
;
665 else if (ctx
->Color
.BlendEquation
==GL_FUNC_REVERSE_SUBTRACT_EXT
) {
666 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
667 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
668 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
669 a
= Ad
* dA
- As
* sA
+ 0.5F
;
672 /* should never get here */
673 r
= g
= b
= a
= 0.0F
; /* silence uninitialized var warning */
674 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
678 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
679 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
680 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
681 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
692 * Analyze current blending parameters to pick fastest blending function.
693 * Result: the ctx->Color.BlendFunc pointer is updated.
695 void _swrast_choose_blend_func( GLcontext
*ctx
)
697 const GLenum eq
= ctx
->Color
.BlendEquation
;
698 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
699 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
700 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
701 const GLenum dstA
= ctx
->Color
.BlendDstA
;
703 if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
704 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
706 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_SRC_ALPHA
707 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
708 #if defined(USE_MMX_ASM)
710 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
714 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
716 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
717 #if defined(USE_MMX_ASM)
719 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_add
;
723 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
725 else if (((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_REVERSE_SUBTRACT_EXT
)
726 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
728 ((eq
==GL_FUNC_ADD_EXT
|| eq
==GL_FUNC_SUBTRACT_EXT
)
729 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
730 #if defined(USE_MMX_ASM)
732 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_modulate
;
736 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
738 else if (eq
==GL_MIN_EXT
) {
739 #if defined(USE_MMX_ASM)
741 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_min
;
745 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
747 else if (eq
==GL_MAX_EXT
) {
748 #if defined(USE_MMX_ASM)
750 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_max
;
754 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
756 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
757 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
759 else if (eq
==GL_FUNC_ADD_EXT
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
760 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
763 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
770 * Apply the blending operator to a span of pixels.
771 * We can handle horizontal runs of pixels (spans) or arrays of x/y
775 _swrast_blend_span( GLcontext
*ctx
, const struct sw_span
*span
,
778 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
779 GLchan framebuffer
[MAX_WIDTH
][4];
781 ASSERT(span
->end
<= MAX_WIDTH
);
782 ASSERT(span
->arrayMask
& SPAN_RGBA
);
783 ASSERT(!ctx
->Color
.ColorLogicOpEnabled
);
785 /* Read span of current frame buffer pixels */
786 if (span
->arrayMask
& SPAN_XY
) {
787 /* array of x/y pixel coords */
788 (*swrast
->Driver
.ReadRGBAPixels
)( ctx
, span
->end
,
789 span
->array
->x
, span
->array
->y
,
790 framebuffer
, span
->array
->mask
);
791 if (swrast
->_RasterMask
& ALPHABUF_BIT
) {
792 _swrast_read_alpha_pixels( ctx
, span
->end
,
793 span
->array
->x
, span
->array
->y
,
794 framebuffer
, span
->array
->mask
);
798 /* horizontal run of pixels */
799 _swrast_read_rgba_span( ctx
, ctx
->DrawBuffer
, span
->end
,
800 span
->x
, span
->y
, framebuffer
);
803 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, span
->end
, span
->array
->mask
, rgba
,
804 (const GLchan (*)[4]) framebuffer
);