2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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.
41 #include "s_context.h"
45 #if defined(USE_MMX_ASM)
47 #include "x86/common_x86_asm.h"
48 #define _BLENDAPI _ASMAPI
55 * Special case for glBlendFunc(GL_ZERO, GL_ONE)
58 blend_noop( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
59 GLchan rgba
[][4], CONST GLchan dest
[][4] )
62 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
63 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
64 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ZERO
);
65 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
68 for (i
= 0; i
< n
; i
++) {
70 COPY_CHAN4( rgba
[i
], dest
[i
] );
77 * Special case for glBlendFunc(GL_ONE, GL_ZERO)
80 blend_replace( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
81 GLchan rgba
[][4], CONST GLchan dest
[][4] )
83 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
84 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
85 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
86 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ZERO
);
96 * Common transparency blending mode.
99 blend_transparency( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
100 GLchan rgba
[][4], CONST GLchan dest
[][4] )
103 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
104 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
105 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_SRC_ALPHA
);
106 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE_MINUS_SRC_ALPHA
);
111 const GLchan t
= rgba
[i
][ACOMP
]; /* t in [0, CHAN_MAX] */
114 rgba
[i
][RCOMP
] = dest
[i
][RCOMP
];
115 rgba
[i
][GCOMP
] = dest
[i
][GCOMP
];
116 rgba
[i
][BCOMP
] = dest
[i
][BCOMP
];
117 rgba
[i
][ACOMP
] = dest
[i
][ACOMP
];
119 else if (t
== CHAN_MAX
) {
120 /* 100% alpha, no-op */
124 /* This is pretty close, but Glean complains */
125 const GLint s
= CHAN_MAX
- t
;
126 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
+ 1) >> 8;
127 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
+ 1) >> 8;
128 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
+ 1) >> 8;
129 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
+ 1) >> 8;
131 /* This is slower but satisfies Glean */
132 const GLint s
= CHAN_MAX
- t
;
133 const GLint r
= (rgba
[i
][RCOMP
] * t
+ dest
[i
][RCOMP
] * s
) / 255;
134 const GLint g
= (rgba
[i
][GCOMP
] * t
+ dest
[i
][GCOMP
] * s
) / 255;
135 const GLint b
= (rgba
[i
][BCOMP
] * t
+ dest
[i
][BCOMP
] * s
) / 255;
136 const GLint a
= (rgba
[i
][ACOMP
] * t
+ dest
[i
][ACOMP
] * s
) / 255;
139 /* This satisfies Glean and should be reasonably fast */
140 /* Contributed by Nathan Hand */
142 #define DIV255(X) (((X) << 8) + (X) + 256) >> 16
145 #define DIV255(X) (temp = (X), ((temp << 8) + temp + 256) >> 16)
147 const GLint r
= DIV255((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * t
) + dest
[i
][RCOMP
];
148 const GLint g
= DIV255((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * t
) + dest
[i
][GCOMP
];
149 const GLint b
= DIV255((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * t
) + dest
[i
][BCOMP
];
150 const GLint a
= DIV255((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * t
) + dest
[i
][ACOMP
];
153 #elif CHAN_BITS == 16
154 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
155 const GLint r
= (GLint
) ((rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
]);
156 const GLint g
= (GLint
) ((rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
]);
157 const GLint b
= (GLint
) ((rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
]);
158 const GLint a
= (GLint
) ((rgba
[i
][ACOMP
] - dest
[i
][ACOMP
]) * tt
+ dest
[i
][ACOMP
]);
159 #else /* CHAN_BITS == 32 */
160 const GLfloat tt
= (GLfloat
) t
/ CHAN_MAXF
;
161 const GLfloat r
= (rgba
[i
][RCOMP
] - dest
[i
][RCOMP
]) * tt
+ dest
[i
][RCOMP
];
162 const GLfloat g
= (rgba
[i
][GCOMP
] - dest
[i
][GCOMP
]) * tt
+ dest
[i
][GCOMP
];
163 const GLfloat b
= (rgba
[i
][BCOMP
] - dest
[i
][BCOMP
]) * tt
+ dest
[i
][BCOMP
];
164 const GLfloat a
= CLAMP( rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * t
+
165 CLAMP( dest
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) * (1.0F
- t
);
168 ASSERT(r
<= CHAN_MAX
);
169 ASSERT(g
<= CHAN_MAX
);
170 ASSERT(b
<= CHAN_MAX
);
171 ASSERT(a
<= CHAN_MAX
);
172 rgba
[i
][RCOMP
] = (GLchan
) r
;
173 rgba
[i
][GCOMP
] = (GLchan
) g
;
174 rgba
[i
][BCOMP
] = (GLchan
) b
;
175 rgba
[i
][ACOMP
] = (GLchan
) a
;
186 static void _BLENDAPI
187 blend_add( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
188 GLchan rgba
[][4], CONST GLchan dest
[][4] )
191 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
);
192 ASSERT(ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
);
193 ASSERT(ctx
->Color
.BlendSrcRGB
==GL_ONE
);
194 ASSERT(ctx
->Color
.BlendDstRGB
==GL_ONE
);
199 #if CHAN_TYPE == GL_FLOAT
200 /* don't RGB clamp to max */
201 GLfloat a
= CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
) + dest
[i
][ACOMP
];
202 rgba
[i
][RCOMP
] += dest
[i
][RCOMP
];
203 rgba
[i
][GCOMP
] += dest
[i
][GCOMP
];
204 rgba
[i
][BCOMP
] += dest
[i
][BCOMP
];
205 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAXF
);
207 GLint r
= rgba
[i
][RCOMP
] + dest
[i
][RCOMP
];
208 GLint g
= rgba
[i
][GCOMP
] + dest
[i
][GCOMP
];
209 GLint b
= rgba
[i
][BCOMP
] + dest
[i
][BCOMP
];
210 GLint a
= rgba
[i
][ACOMP
] + dest
[i
][ACOMP
];
211 rgba
[i
][RCOMP
] = (GLchan
) MIN2( r
, CHAN_MAX
);
212 rgba
[i
][GCOMP
] = (GLchan
) MIN2( g
, CHAN_MAX
);
213 rgba
[i
][BCOMP
] = (GLchan
) MIN2( b
, CHAN_MAX
);
214 rgba
[i
][ACOMP
] = (GLchan
) MIN2( a
, CHAN_MAX
);
223 * Blend min function (for GL_EXT_blend_minmax)
225 static void _BLENDAPI
226 blend_min( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
227 GLchan rgba
[][4], CONST GLchan dest
[][4] )
230 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_MIN
);
231 ASSERT(ctx
->Color
.BlendEquationA
==GL_MIN
);
236 rgba
[i
][RCOMP
] = (GLchan
) MIN2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
237 rgba
[i
][GCOMP
] = (GLchan
) MIN2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
238 rgba
[i
][BCOMP
] = (GLchan
) MIN2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
239 #if CHAN_TYPE == GL_FLOAT
240 rgba
[i
][ACOMP
] = (GLchan
) MIN2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
243 rgba
[i
][ACOMP
] = (GLchan
) MIN2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
252 * Blend max function (for GL_EXT_blend_minmax)
254 static void _BLENDAPI
255 blend_max( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
256 GLchan rgba
[][4], CONST GLchan dest
[][4] )
259 ASSERT(ctx
->Color
.BlendEquationRGB
==GL_MAX
);
260 ASSERT(ctx
->Color
.BlendEquationA
==GL_MAX
);
265 rgba
[i
][RCOMP
] = (GLchan
) MAX2( rgba
[i
][RCOMP
], dest
[i
][RCOMP
] );
266 rgba
[i
][GCOMP
] = (GLchan
) MAX2( rgba
[i
][GCOMP
], dest
[i
][GCOMP
] );
267 rgba
[i
][BCOMP
] = (GLchan
) MAX2( rgba
[i
][BCOMP
], dest
[i
][BCOMP
] );
268 #if CHAN_TYPE == GL_FLOAT
269 rgba
[i
][ACOMP
] = (GLchan
) MAX2(CLAMP(rgba
[i
][ACOMP
], 0.0F
, CHAN_MAXF
),
272 rgba
[i
][ACOMP
] = (GLchan
) MAX2( rgba
[i
][ACOMP
], dest
[i
][ACOMP
] );
281 * Modulate: result = src * dest
283 static void _BLENDAPI
284 blend_modulate( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
285 GLchan rgba
[][4], CONST GLchan dest
[][4] )
292 #if CHAN_TYPE == GL_FLOAT
293 rgba
[i
][RCOMP
] = rgba
[i
][RCOMP
] * dest
[i
][RCOMP
];
294 rgba
[i
][GCOMP
] = rgba
[i
][GCOMP
] * dest
[i
][GCOMP
];
295 rgba
[i
][BCOMP
] = rgba
[i
][BCOMP
] * dest
[i
][BCOMP
];
296 rgba
[i
][ACOMP
] = rgba
[i
][ACOMP
] * dest
[i
][ACOMP
];
297 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
298 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 65535) >> 16;
299 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 65535) >> 16;
300 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 65535) >> 16;
301 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 65535) >> 16;
302 rgba
[i
][RCOMP
] = (GLchan
) r
;
303 rgba
[i
][GCOMP
] = (GLchan
) g
;
304 rgba
[i
][BCOMP
] = (GLchan
) b
;
305 rgba
[i
][ACOMP
] = (GLchan
) a
;
307 GLint r
= (rgba
[i
][RCOMP
] * dest
[i
][RCOMP
] + 255) >> 8;
308 GLint g
= (rgba
[i
][GCOMP
] * dest
[i
][GCOMP
] + 255) >> 8;
309 GLint b
= (rgba
[i
][BCOMP
] * dest
[i
][BCOMP
] + 255) >> 8;
310 GLint a
= (rgba
[i
][ACOMP
] * dest
[i
][ACOMP
] + 255) >> 8;
311 rgba
[i
][RCOMP
] = (GLchan
) r
;
312 rgba
[i
][GCOMP
] = (GLchan
) g
;
313 rgba
[i
][BCOMP
] = (GLchan
) b
;
314 rgba
[i
][ACOMP
] = (GLchan
) a
;
323 * General case blend pixels.
324 * Input: n - number of pixels
325 * mask - the usual write mask
326 * In/Out: rgba - the incoming and modified pixels
327 * Input: dest - the pixels from the dest color buffer
329 static void _BLENDAPI
330 blend_general( GLcontext
*ctx
, GLuint n
, const GLubyte mask
[],
331 GLchan rgba
[][4], CONST GLchan dest
[][4] )
333 const GLfloat rscale
= 1.0F
/ CHAN_MAXF
;
334 const GLfloat gscale
= 1.0F
/ CHAN_MAXF
;
335 const GLfloat bscale
= 1.0F
/ CHAN_MAXF
;
336 const GLfloat ascale
= 1.0F
/ CHAN_MAXF
;
341 #if CHAN_TYPE == GL_FLOAT
342 GLfloat Rs
, Gs
, Bs
, As
; /* Source colors */
343 GLfloat Rd
, Gd
, Bd
, Ad
; /* Dest colors */
345 GLint Rs
, Gs
, Bs
, As
; /* Source colors */
346 GLint Rd
, Gd
, Bd
, Ad
; /* Dest colors */
348 GLfloat sR
, sG
, sB
, sA
; /* Source scaling */
349 GLfloat dR
, dG
, dB
, dA
; /* Dest scaling */
350 GLfloat r
, g
, b
, a
; /* result color */
352 /* Incoming/source Color */
357 #if CHAN_TYPE == GL_FLOAT
359 Rs
= MIN2(Rs
, CHAN_MAXF
);
360 Gs
= MIN2(Gs
, CHAN_MAXF
);
361 Bs
= MIN2(Bs
, CHAN_MAXF
);
362 As
= MIN2(As
, CHAN_MAXF
);
365 /* Frame buffer/dest color */
370 #if CHAN_TYPE == GL_FLOAT
372 Rd
= MIN2(Rd
, CHAN_MAXF
);
373 Gd
= MIN2(Gd
, CHAN_MAXF
);
374 Bd
= MIN2(Bd
, CHAN_MAXF
);
375 Ad
= MIN2(Ad
, CHAN_MAXF
);
378 /* Source RGB factor */
379 switch (ctx
->Color
.BlendSrcRGB
) {
387 sR
= (GLfloat
) Rd
* rscale
;
388 sG
= (GLfloat
) Gd
* gscale
;
389 sB
= (GLfloat
) Bd
* bscale
;
391 case GL_ONE_MINUS_DST_COLOR
:
392 sR
= 1.0F
- (GLfloat
) Rd
* rscale
;
393 sG
= 1.0F
- (GLfloat
) Gd
* gscale
;
394 sB
= 1.0F
- (GLfloat
) Bd
* bscale
;
397 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
399 case GL_ONE_MINUS_SRC_ALPHA
:
400 sR
= sG
= sB
= 1.0F
- (GLfloat
) As
* ascale
;
403 sR
= sG
= sB
= (GLfloat
) Ad
* ascale
;
405 case GL_ONE_MINUS_DST_ALPHA
:
406 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
408 case GL_SRC_ALPHA_SATURATE
:
409 if (As
< CHAN_MAX
- Ad
) {
410 sR
= sG
= sB
= (GLfloat
) As
* ascale
;
413 sR
= sG
= sB
= 1.0F
- (GLfloat
) Ad
* ascale
;
416 case GL_CONSTANT_COLOR
:
417 sR
= ctx
->Color
.BlendColor
[0];
418 sG
= ctx
->Color
.BlendColor
[1];
419 sB
= ctx
->Color
.BlendColor
[2];
421 case GL_ONE_MINUS_CONSTANT_COLOR
:
422 sR
= 1.0F
- ctx
->Color
.BlendColor
[0];
423 sG
= 1.0F
- ctx
->Color
.BlendColor
[1];
424 sB
= 1.0F
- ctx
->Color
.BlendColor
[2];
426 case GL_CONSTANT_ALPHA
:
427 sR
= sG
= sB
= ctx
->Color
.BlendColor
[3];
429 case GL_ONE_MINUS_CONSTANT_ALPHA
:
430 sR
= sG
= sB
= 1.0F
- ctx
->Color
.BlendColor
[3];
432 case GL_SRC_COLOR
: /* GL_NV_blend_square */
433 sR
= (GLfloat
) Rs
* rscale
;
434 sG
= (GLfloat
) Gs
* gscale
;
435 sB
= (GLfloat
) Bs
* bscale
;
437 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
438 sR
= 1.0F
- (GLfloat
) Rs
* rscale
;
439 sG
= 1.0F
- (GLfloat
) Gs
* gscale
;
440 sB
= 1.0F
- (GLfloat
) Bs
* bscale
;
443 /* this should never happen */
444 _mesa_problem(ctx
, "Bad blend source RGB factor in do_blend");
448 /* Source Alpha factor */
449 switch (ctx
->Color
.BlendSrcA
) {
457 sA
= (GLfloat
) Ad
* ascale
;
459 case GL_ONE_MINUS_DST_COLOR
:
460 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
463 sA
= (GLfloat
) As
* ascale
;
465 case GL_ONE_MINUS_SRC_ALPHA
:
466 sA
= 1.0F
- (GLfloat
) As
* ascale
;
469 sA
=(GLfloat
) Ad
* ascale
;
471 case GL_ONE_MINUS_DST_ALPHA
:
472 sA
= 1.0F
- (GLfloat
) Ad
* ascale
;
474 case GL_SRC_ALPHA_SATURATE
:
477 case GL_CONSTANT_COLOR
:
478 sA
= ctx
->Color
.BlendColor
[3];
480 case GL_ONE_MINUS_CONSTANT_COLOR
:
481 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
483 case GL_CONSTANT_ALPHA
:
484 sA
= ctx
->Color
.BlendColor
[3];
486 case GL_ONE_MINUS_CONSTANT_ALPHA
:
487 sA
= 1.0F
- ctx
->Color
.BlendColor
[3];
489 case GL_SRC_COLOR
: /* GL_NV_blend_square */
490 sA
= (GLfloat
) As
* ascale
;
492 case GL_ONE_MINUS_SRC_COLOR
: /* GL_NV_blend_square */
493 sA
= 1.0F
- (GLfloat
) As
* ascale
;
496 /* this should never happen */
498 _mesa_problem(ctx
, "Bad blend source A factor in do_blend");
501 /* Dest RGB factor */
502 switch (ctx
->Color
.BlendDstRGB
) {
510 dR
= (GLfloat
) Rs
* rscale
;
511 dG
= (GLfloat
) Gs
* gscale
;
512 dB
= (GLfloat
) Bs
* bscale
;
514 case GL_ONE_MINUS_SRC_COLOR
:
515 dR
= 1.0F
- (GLfloat
) Rs
* rscale
;
516 dG
= 1.0F
- (GLfloat
) Gs
* gscale
;
517 dB
= 1.0F
- (GLfloat
) Bs
* bscale
;
520 dR
= dG
= dB
= (GLfloat
) As
* ascale
;
522 case GL_ONE_MINUS_SRC_ALPHA
:
523 dR
= dG
= dB
= 1.0F
- (GLfloat
) As
* ascale
;
526 dR
= dG
= dB
= (GLfloat
) Ad
* ascale
;
528 case GL_ONE_MINUS_DST_ALPHA
:
529 dR
= dG
= dB
= 1.0F
- (GLfloat
) Ad
* ascale
;
531 case GL_CONSTANT_COLOR
:
532 dR
= ctx
->Color
.BlendColor
[0];
533 dG
= ctx
->Color
.BlendColor
[1];
534 dB
= ctx
->Color
.BlendColor
[2];
536 case GL_ONE_MINUS_CONSTANT_COLOR
:
537 dR
= 1.0F
- ctx
->Color
.BlendColor
[0];
538 dG
= 1.0F
- ctx
->Color
.BlendColor
[1];
539 dB
= 1.0F
- ctx
->Color
.BlendColor
[2];
541 case GL_CONSTANT_ALPHA
:
542 dR
= dG
= dB
= ctx
->Color
.BlendColor
[3];
544 case GL_ONE_MINUS_CONSTANT_ALPHA
:
545 dR
= dG
= dB
= 1.0F
- ctx
->Color
.BlendColor
[3];
547 case GL_DST_COLOR
: /* GL_NV_blend_square */
548 dR
= (GLfloat
) Rd
* rscale
;
549 dG
= (GLfloat
) Gd
* gscale
;
550 dB
= (GLfloat
) Bd
* bscale
;
552 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
553 dR
= 1.0F
- (GLfloat
) Rd
* rscale
;
554 dG
= 1.0F
- (GLfloat
) Gd
* gscale
;
555 dB
= 1.0F
- (GLfloat
) Bd
* bscale
;
558 /* this should never happen */
560 _mesa_problem(ctx
, "Bad blend dest RGB factor in do_blend");
563 /* Dest Alpha factor */
564 switch (ctx
->Color
.BlendDstA
) {
572 dA
= (GLfloat
) As
* ascale
;
574 case GL_ONE_MINUS_SRC_COLOR
:
575 dA
= 1.0F
- (GLfloat
) As
* ascale
;
578 dA
= (GLfloat
) As
* ascale
;
580 case GL_ONE_MINUS_SRC_ALPHA
:
581 dA
= 1.0F
- (GLfloat
) As
* ascale
;
584 dA
= (GLfloat
) Ad
* ascale
;
586 case GL_ONE_MINUS_DST_ALPHA
:
587 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
589 case GL_CONSTANT_COLOR
:
590 dA
= ctx
->Color
.BlendColor
[3];
592 case GL_ONE_MINUS_CONSTANT_COLOR
:
593 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
595 case GL_CONSTANT_ALPHA
:
596 dA
= ctx
->Color
.BlendColor
[3];
598 case GL_ONE_MINUS_CONSTANT_ALPHA
:
599 dA
= 1.0F
- ctx
->Color
.BlendColor
[3];
601 case GL_DST_COLOR
: /* GL_NV_blend_square */
602 dA
= (GLfloat
) Ad
* ascale
;
604 case GL_ONE_MINUS_DST_COLOR
: /* GL_NV_blend_square */
605 dA
= 1.0F
- (GLfloat
) Ad
* ascale
;
608 /* this should never happen */
610 _mesa_problem(ctx
, "Bad blend dest A factor in do_blend");
614 /* Due to round-off problems we have to clamp against zero. */
615 /* Optimization: we don't have to do this for all src & dst factors */
616 if (dA
< 0.0F
) dA
= 0.0F
;
617 if (dR
< 0.0F
) dR
= 0.0F
;
618 if (dG
< 0.0F
) dG
= 0.0F
;
619 if (dB
< 0.0F
) dB
= 0.0F
;
620 if (sA
< 0.0F
) sA
= 0.0F
;
621 if (sR
< 0.0F
) sR
= 0.0F
;
622 if (sG
< 0.0F
) sG
= 0.0F
;
623 if (sB
< 0.0F
) sB
= 0.0F
;
634 /* compute blended color */
635 #if CHAN_TYPE == GL_FLOAT
636 if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
) {
637 r
= Rs
* sR
+ Rd
* dR
;
638 g
= Gs
* sG
+ Gd
* dG
;
639 b
= Bs
* sB
+ Bd
* dB
;
640 a
= As
* sA
+ Ad
* dA
;
642 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_SUBTRACT
) {
643 r
= Rs
* sR
- Rd
* dR
;
644 g
= Gs
* sG
- Gd
* dG
;
645 b
= Bs
* sB
- Bd
* dB
;
646 a
= As
* sA
- Ad
* dA
;
648 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_REVERSE_SUBTRACT
) {
649 r
= Rd
* dR
- Rs
* sR
;
650 g
= Gd
* dG
- Gs
* sG
;
651 b
= Bd
* dB
- Bs
* sB
;
652 a
= Ad
* dA
- As
* sA
;
654 else if (ctx
->Color
.BlendEquationRGB
==GL_MIN
) {
659 else if (ctx
->Color
.BlendEquationRGB
==GL_MAX
) {
665 /* should never get here */
666 r
= g
= b
= 0.0F
; /* silence uninitialized var warning */
667 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
670 if (ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
) {
671 a
= As
* sA
+ Ad
* dA
;
673 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_SUBTRACT
) {
674 a
= As
* sA
- Ad
* dA
;
676 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_REVERSE_SUBTRACT
) {
677 a
= Ad
* dA
- As
* sA
;
679 else if (ctx
->Color
.BlendEquationA
==GL_MIN
) {
682 else if (ctx
->Color
.BlendEquationA
==GL_MAX
) {
686 /* should never get here */
687 a
= 0.0F
; /* silence uninitialized var warning */
688 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
692 rgba
[i
][RCOMP
] = MAX2( r
, 0.0F
);
693 rgba
[i
][GCOMP
] = MAX2( g
, 0.0F
);
694 rgba
[i
][BCOMP
] = MAX2( b
, 0.0F
);
695 rgba
[i
][ACOMP
] = CLAMP( a
, 0.0F
, CHAN_MAXF
);
697 if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_ADD
) {
698 r
= Rs
* sR
+ Rd
* dR
+ 0.5F
;
699 g
= Gs
* sG
+ Gd
* dG
+ 0.5F
;
700 b
= Bs
* sB
+ Bd
* dB
+ 0.5F
;
702 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_SUBTRACT
) {
703 r
= Rs
* sR
- Rd
* dR
+ 0.5F
;
704 g
= Gs
* sG
- Gd
* dG
+ 0.5F
;
705 b
= Bs
* sB
- Bd
* dB
+ 0.5F
;
707 else if (ctx
->Color
.BlendEquationRGB
==GL_FUNC_REVERSE_SUBTRACT
) {
708 r
= Rd
* dR
- Rs
* sR
+ 0.5F
;
709 g
= Gd
* dG
- Gs
* sG
+ 0.5F
;
710 b
= Bd
* dB
- Bs
* sB
+ 0.5F
;
712 else if (ctx
->Color
.BlendEquationRGB
==GL_MIN
) {
717 else if (ctx
->Color
.BlendEquationRGB
==GL_MAX
) {
723 /* should never get here */
724 r
= g
= b
= 0.0F
; /* silence uninitialized var warning */
725 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
728 if (ctx
->Color
.BlendEquationA
==GL_FUNC_ADD
) {
729 a
= As
* sA
+ Ad
* dA
+ 0.5F
;
731 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_SUBTRACT
) {
732 a
= As
* sA
- Ad
* dA
+ 0.5F
;
734 else if (ctx
->Color
.BlendEquationA
==GL_FUNC_REVERSE_SUBTRACT
) {
735 a
= Ad
* dA
- As
* sA
+ 0.5F
;
737 else if (ctx
->Color
.BlendEquationA
==GL_MIN
) {
740 else if (ctx
->Color
.BlendEquationA
==GL_MAX
) {
744 /* should never get here */
745 a
= 0.0F
; /* silence uninitialized var warning */
746 _mesa_problem(ctx
, "unexpected BlendEquation in blend_general()");
750 rgba
[i
][RCOMP
] = (GLchan
) (GLint
) CLAMP( r
, 0.0F
, CHAN_MAXF
);
751 rgba
[i
][GCOMP
] = (GLchan
) (GLint
) CLAMP( g
, 0.0F
, CHAN_MAXF
);
752 rgba
[i
][BCOMP
] = (GLchan
) (GLint
) CLAMP( b
, 0.0F
, CHAN_MAXF
);
753 rgba
[i
][ACOMP
] = (GLchan
) (GLint
) CLAMP( a
, 0.0F
, CHAN_MAXF
);
761 * Analyze current blending parameters to pick fastest blending function.
762 * Result: the ctx->Color.BlendFunc pointer is updated.
764 void _swrast_choose_blend_func( GLcontext
*ctx
)
766 const GLenum eq
= ctx
->Color
.BlendEquationRGB
;
767 const GLenum srcRGB
= ctx
->Color
.BlendSrcRGB
;
768 const GLenum dstRGB
= ctx
->Color
.BlendDstRGB
;
769 const GLenum srcA
= ctx
->Color
.BlendSrcA
;
770 const GLenum dstA
= ctx
->Color
.BlendDstA
;
772 if (ctx
->Color
.BlendEquationRGB
!= ctx
->Color
.BlendEquationA
) {
773 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
775 else if (eq
==GL_MIN
) {
776 /* Note: GL_MIN ignores the blending weight factors */
777 #if defined(USE_MMX_ASM)
779 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_min
;
783 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_min
;
785 else if (eq
==GL_MAX
) {
786 /* Note: GL_MAX ignores the blending weight factors */
787 #if defined(USE_MMX_ASM)
789 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_max
;
793 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_max
;
795 else if (srcRGB
!= srcA
|| dstRGB
!= dstA
) {
796 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
798 else if (eq
==GL_FUNC_ADD
&& srcRGB
==GL_SRC_ALPHA
799 && dstRGB
==GL_ONE_MINUS_SRC_ALPHA
) {
800 #if defined(USE_MMX_ASM)
802 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_transparency
;
806 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_transparency
;
808 else if (eq
==GL_FUNC_ADD
&& srcRGB
==GL_ONE
&& dstRGB
==GL_ONE
) {
809 #if defined(USE_MMX_ASM)
811 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_add
;
815 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_add
;
817 else if (((eq
==GL_FUNC_ADD
|| eq
==GL_FUNC_REVERSE_SUBTRACT
)
818 && (srcRGB
==GL_ZERO
&& dstRGB
==GL_SRC_COLOR
))
820 ((eq
==GL_FUNC_ADD
|| eq
==GL_FUNC_SUBTRACT
)
821 && (srcRGB
==GL_DST_COLOR
&& dstRGB
==GL_ZERO
))) {
822 #if defined(USE_MMX_ASM)
824 SWRAST_CONTEXT(ctx
)->BlendFunc
= _mesa_mmx_blend_modulate
;
828 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_modulate
;
830 else if (eq
==GL_FUNC_ADD
&& srcRGB
== GL_ZERO
&& dstRGB
== GL_ONE
) {
831 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_noop
;
833 else if (eq
==GL_FUNC_ADD
&& srcRGB
== GL_ONE
&& dstRGB
== GL_ZERO
) {
834 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_replace
;
837 SWRAST_CONTEXT(ctx
)->BlendFunc
= blend_general
;
844 * Apply the blending operator to a span of pixels.
845 * We can handle horizontal runs of pixels (spans) or arrays of x/y
849 _swrast_blend_span(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
850 const struct sw_span
*span
, GLchan rgba
[][4])
852 GLchan framebuffer
[MAX_WIDTH
][4];
854 ASSERT(span
->end
<= MAX_WIDTH
);
855 ASSERT(span
->arrayMask
& SPAN_RGBA
);
856 ASSERT(!ctx
->Color
._LogicOpEnabled
);
858 /* Read span of current frame buffer pixels */
859 if (span
->arrayMask
& SPAN_XY
) {
860 /* array of x/y pixel coords */
861 rb
->GetValues(ctx
, rb
, span
->end
, span
->array
->x
, span
->array
->y
,
865 /* horizontal run of pixels */
866 _swrast_read_rgba_span(ctx
, rb
, span
->end
, span
->x
, span
->y
,
870 SWRAST_CONTEXT(ctx
)->BlendFunc( ctx
, span
->end
, span
->array
->mask
, rgba
,
871 (const GLchan (*)[4]) framebuffer
);