rearranged order of some functions
[mesa.git] / src / mesa / main / blend.c
1 /* $Id: blend.c,v 1.13 2000/02/24 22:04:03 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 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 #ifdef PC_HEADER
30 #include "all.h"
31 #else
32 #include "glheader.h"
33 #include "alphabuf.h"
34 #include "blend.h"
35 #include "context.h"
36 #include "enums.h"
37 #include "macros.h"
38 #include "pb.h"
39 #include "span.h"
40 #include "types.h"
41 #endif
42
43
44 void
45 _mesa_BlendFunc( GLenum sfactor, GLenum dfactor )
46 {
47 GET_CURRENT_CONTEXT(ctx);
48 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc");
49
50 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
51 fprintf(stderr, "glBlendFunc %s %s\n",
52 gl_lookup_enum_by_nr(sfactor),
53 gl_lookup_enum_by_nr(dfactor));
54
55 switch (sfactor) {
56 case GL_ZERO:
57 case GL_ONE:
58 case GL_DST_COLOR:
59 case GL_ONE_MINUS_DST_COLOR:
60 case GL_SRC_ALPHA:
61 case GL_ONE_MINUS_SRC_ALPHA:
62 case GL_DST_ALPHA:
63 case GL_ONE_MINUS_DST_ALPHA:
64 case GL_SRC_ALPHA_SATURATE:
65 case GL_CONSTANT_COLOR:
66 case GL_ONE_MINUS_CONSTANT_COLOR:
67 case GL_CONSTANT_ALPHA:
68 case GL_ONE_MINUS_CONSTANT_ALPHA:
69 ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
70 break;
71 default:
72 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
73 return;
74 }
75
76 switch (dfactor) {
77 case GL_ZERO:
78 case GL_ONE:
79 case GL_SRC_COLOR:
80 case GL_ONE_MINUS_SRC_COLOR:
81 case GL_SRC_ALPHA:
82 case GL_ONE_MINUS_SRC_ALPHA:
83 case GL_DST_ALPHA:
84 case GL_ONE_MINUS_DST_ALPHA:
85 case GL_CONSTANT_COLOR:
86 case GL_ONE_MINUS_CONSTANT_COLOR:
87 case GL_CONSTANT_ALPHA:
88 case GL_ONE_MINUS_CONSTANT_ALPHA:
89 ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
90 break;
91 default:
92 gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
93 return;
94 }
95
96 if (ctx->Driver.BlendFunc) {
97 (*ctx->Driver.BlendFunc)( ctx, sfactor, dfactor );
98 }
99
100 ctx->Color.BlendFunc = NULL;
101 ctx->NewState |= NEW_RASTER_OPS;
102 }
103
104
105 /* GL_EXT_blend_func_separate */
106 void
107 _mesa_BlendFuncSeparateEXT( GLenum sfactorRGB, GLenum dfactorRGB,
108 GLenum sfactorA, GLenum dfactorA )
109 {
110 GET_CURRENT_CONTEXT(ctx);
111 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate");
112
113 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
114 fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
115 gl_lookup_enum_by_nr(sfactorRGB),
116 gl_lookup_enum_by_nr(dfactorRGB),
117 gl_lookup_enum_by_nr(sfactorA),
118 gl_lookup_enum_by_nr(dfactorA));
119
120 switch (sfactorRGB) {
121 case GL_ZERO:
122 case GL_ONE:
123 case GL_DST_COLOR:
124 case GL_ONE_MINUS_DST_COLOR:
125 case GL_SRC_ALPHA:
126 case GL_ONE_MINUS_SRC_ALPHA:
127 case GL_DST_ALPHA:
128 case GL_ONE_MINUS_DST_ALPHA:
129 case GL_SRC_ALPHA_SATURATE:
130 case GL_CONSTANT_COLOR:
131 case GL_ONE_MINUS_CONSTANT_COLOR:
132 case GL_CONSTANT_ALPHA:
133 case GL_ONE_MINUS_CONSTANT_ALPHA:
134 ctx->Color.BlendSrcRGB = sfactorRGB;
135 break;
136 default:
137 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" );
138 return;
139 }
140
141 switch (dfactorRGB) {
142 case GL_ZERO:
143 case GL_ONE:
144 case GL_SRC_COLOR:
145 case GL_ONE_MINUS_SRC_COLOR:
146 case GL_SRC_ALPHA:
147 case GL_ONE_MINUS_SRC_ALPHA:
148 case GL_DST_ALPHA:
149 case GL_ONE_MINUS_DST_ALPHA:
150 case GL_CONSTANT_COLOR:
151 case GL_ONE_MINUS_CONSTANT_COLOR:
152 case GL_CONSTANT_ALPHA:
153 case GL_ONE_MINUS_CONSTANT_ALPHA:
154 ctx->Color.BlendDstRGB = dfactorRGB;
155 break;
156 default:
157 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" );
158 return;
159 }
160
161 switch (sfactorA) {
162 case GL_ZERO:
163 case GL_ONE:
164 case GL_DST_COLOR:
165 case GL_ONE_MINUS_DST_COLOR:
166 case GL_SRC_ALPHA:
167 case GL_ONE_MINUS_SRC_ALPHA:
168 case GL_DST_ALPHA:
169 case GL_ONE_MINUS_DST_ALPHA:
170 case GL_SRC_ALPHA_SATURATE:
171 case GL_CONSTANT_COLOR:
172 case GL_ONE_MINUS_CONSTANT_COLOR:
173 case GL_CONSTANT_ALPHA:
174 case GL_ONE_MINUS_CONSTANT_ALPHA:
175 ctx->Color.BlendSrcA = sfactorA;
176 break;
177 default:
178 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" );
179 return;
180 }
181
182 switch (dfactorA) {
183 case GL_ZERO:
184 case GL_ONE:
185 case GL_SRC_COLOR:
186 case GL_ONE_MINUS_SRC_COLOR:
187 case GL_SRC_ALPHA:
188 case GL_ONE_MINUS_SRC_ALPHA:
189 case GL_DST_ALPHA:
190 case GL_ONE_MINUS_DST_ALPHA:
191 case GL_CONSTANT_COLOR:
192 case GL_ONE_MINUS_CONSTANT_COLOR:
193 case GL_CONSTANT_ALPHA:
194 case GL_ONE_MINUS_CONSTANT_ALPHA:
195 ctx->Color.BlendDstA = dfactorA;
196 break;
197 default:
198 gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
199 return;
200 }
201
202 ctx->Color.BlendFunc = NULL;
203 ctx->NewState |= NEW_RASTER_OPS;
204
205 if (ctx->Driver.BlendFuncSeparate) {
206 (*ctx->Driver.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
207 sfactorA, dfactorA );
208 }
209 }
210
211
212
213 /* This is really an extension function! */
214 void
215 _mesa_BlendEquation( GLenum mode )
216 {
217 GET_CURRENT_CONTEXT(ctx);
218 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation");
219
220 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
221 fprintf(stderr, "glBlendEquation %s\n",
222 gl_lookup_enum_by_nr(mode));
223
224
225 switch (mode) {
226 case GL_MIN_EXT:
227 case GL_MAX_EXT:
228 case GL_LOGIC_OP:
229 case GL_FUNC_ADD_EXT:
230 case GL_FUNC_SUBTRACT_EXT:
231 case GL_FUNC_REVERSE_SUBTRACT_EXT:
232 ctx->Color.BlendEquation = mode;
233 break;
234 default:
235 gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
236 return;
237 }
238
239 /* This is needed to support 1.1's RGB logic ops AND
240 * 1.0's blending logicops.
241 */
242 if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) {
243 ctx->Color.ColorLogicOpEnabled = GL_TRUE;
244 }
245 else {
246 ctx->Color.ColorLogicOpEnabled = GL_FALSE;
247 }
248
249 ctx->Color.BlendFunc = NULL;
250 ctx->NewState |= NEW_RASTER_OPS;
251
252 if (ctx->Driver.BlendEquation)
253 ctx->Driver.BlendEquation( ctx, mode );
254 }
255
256
257
258 void
259 _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
260 {
261 GET_CURRENT_CONTEXT(ctx);
262 ctx->Color.BlendColor[0] = CLAMP( red, 0.0F, 1.0F );
263 ctx->Color.BlendColor[1] = CLAMP( green, 0.0F, 1.0F );
264 ctx->Color.BlendColor[2] = CLAMP( blue, 0.0F, 1.0F );
265 ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0F, 1.0F );
266 }
267
268 #ifdef USE_MMX_ASM
269 #define _BLENDAPI _ASMAPI
270 #else
271 #define _BLENDAPI
272 #endif
273
274 /*
275 * Common transparency blending mode.
276 */
277 static void _BLENDAPI
278 blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
279 GLubyte rgba[][4], CONST GLubyte dest[][4] )
280 {
281 GLuint i;
282 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
283 ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
284 ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
285 (void) ctx;
286
287 for (i=0;i<n;i++) {
288 if (mask[i]) {
289 const GLint t = rgba[i][ACOMP]; /* t in [0,255] */
290 if (t == 0) {
291 /* 0% alpha */
292 rgba[i][RCOMP] = dest[i][RCOMP];
293 rgba[i][GCOMP] = dest[i][GCOMP];
294 rgba[i][BCOMP] = dest[i][BCOMP];
295 rgba[i][ACOMP] = dest[i][ACOMP];
296 }
297 else if (t == CHAN_MAX) {
298 /* 100% alpha, no-op */
299 }
300 else {
301 const GLint s = CHAN_MAX - t;
302 const GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
303 const GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
304 const GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
305 const GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
306 ASSERT(r <= CHAN_MAX);
307 ASSERT(g <= CHAN_MAX);
308 ASSERT(b <= CHAN_MAX);
309 ASSERT(a <= CHAN_MAX);
310 rgba[i][RCOMP] = (GLubyte) r;
311 rgba[i][GCOMP] = (GLubyte) g;
312 rgba[i][BCOMP] = (GLubyte) b;
313 rgba[i][ACOMP] = (GLubyte) a;
314 }
315 }
316 }
317 }
318
319
320
321 /*
322 * Add src and dest.
323 */
324 static void _BLENDAPI
325 blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
326 GLubyte rgba[][4], CONST GLubyte dest[][4] )
327 {
328 GLuint i;
329 ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
330 ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
331 ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
332 (void) ctx;
333
334 for (i=0;i<n;i++) {
335 if (mask[i]) {
336 GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
337 GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
338 GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
339 GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
340 rgba[i][RCOMP] = (GLubyte) MIN2( r, CHAN_MAX );
341 rgba[i][GCOMP] = (GLubyte) MIN2( g, CHAN_MAX );
342 rgba[i][BCOMP] = (GLubyte) MIN2( b, CHAN_MAX );
343 rgba[i][ACOMP] = (GLubyte) MIN2( a, CHAN_MAX );
344 }
345 }
346 }
347
348
349
350 /*
351 * Blend min function (for GL_EXT_blend_minmax)
352 */
353 static void _BLENDAPI
354 blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
355 GLubyte rgba[][4], CONST GLubyte dest[][4] )
356 {
357 GLuint i;
358 ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
359 (void) ctx;
360
361 for (i=0;i<n;i++) {
362 if (mask[i]) {
363 rgba[i][RCOMP] = (GLubyte) MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
364 rgba[i][GCOMP] = (GLubyte) MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
365 rgba[i][BCOMP] = (GLubyte) MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
366 rgba[i][ACOMP] = (GLubyte) MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
367 }
368 }
369 }
370
371
372
373 /*
374 * Blend max function (for GL_EXT_blend_minmax)
375 */
376 static void _BLENDAPI
377 blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
378 GLubyte rgba[][4], CONST GLubyte dest[][4] )
379 {
380 GLuint i;
381 ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
382 (void) ctx;
383
384 for (i=0;i<n;i++) {
385 if (mask[i]) {
386 rgba[i][RCOMP] = (GLubyte) MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
387 rgba[i][GCOMP] = (GLubyte) MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
388 rgba[i][BCOMP] = (GLubyte) MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
389 rgba[i][ACOMP] = (GLubyte) MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
390 }
391 }
392 }
393
394
395
396 /*
397 * Modulate: result = src * dest
398 */
399 static void _BLENDAPI
400 blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
401 GLubyte rgba[][4], CONST GLubyte dest[][4] )
402 {
403 GLuint i;
404 (void) ctx;
405
406 for (i=0;i<n;i++) {
407 if (mask[i]) {
408 GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
409 GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
410 GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
411 GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
412 rgba[i][RCOMP] = (GLubyte) r;
413 rgba[i][GCOMP] = (GLubyte) g;
414 rgba[i][BCOMP] = (GLubyte) b;
415 rgba[i][ACOMP] = (GLubyte) a;
416 }
417 }
418 }
419
420
421
422 /*
423 * General case blend pixels.
424 * Input: n - number of pixels
425 * mask - the usual write mask
426 * In/Out: rgba - the incoming and modified pixels
427 * Input: dest - the pixels from the dest color buffer
428 */
429 static void _BLENDAPI
430 blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
431 GLubyte rgba[][4], CONST GLubyte dest[][4] )
432 {
433 GLfloat rscale = 1.0F / CHAN_MAXF;
434 GLfloat gscale = 1.0F / CHAN_MAXF;
435 GLfloat bscale = 1.0F / CHAN_MAXF;
436 GLfloat ascale = 1.0F / CHAN_MAXF;
437 GLuint i;
438
439 for (i=0;i<n;i++) {
440 if (mask[i]) {
441 GLint Rs, Gs, Bs, As; /* Source colors */
442 GLint Rd, Gd, Bd, Ad; /* Dest colors */
443 GLfloat sR, sG, sB, sA; /* Source scaling */
444 GLfloat dR, dG, dB, dA; /* Dest scaling */
445 GLfloat r, g, b, a;
446
447 /* Source Color */
448 Rs = rgba[i][RCOMP];
449 Gs = rgba[i][GCOMP];
450 Bs = rgba[i][BCOMP];
451 As = rgba[i][ACOMP];
452
453 /* Frame buffer color */
454 Rd = dest[i][RCOMP];
455 Gd = dest[i][GCOMP];
456 Bd = dest[i][BCOMP];
457 Ad = dest[i][ACOMP];
458
459 /* Source RGB factor */
460 switch (ctx->Color.BlendSrcRGB) {
461 case GL_ZERO:
462 sR = sG = sB = 0.0F;
463 break;
464 case GL_ONE:
465 sR = sG = sB = 1.0F;
466 break;
467 case GL_DST_COLOR:
468 sR = (GLfloat) Rd * rscale;
469 sG = (GLfloat) Gd * gscale;
470 sB = (GLfloat) Bd * bscale;
471 break;
472 case GL_ONE_MINUS_DST_COLOR:
473 sR = 1.0F - (GLfloat) Rd * rscale;
474 sG = 1.0F - (GLfloat) Gd * gscale;
475 sB = 1.0F - (GLfloat) Bd * bscale;
476 break;
477 case GL_SRC_ALPHA:
478 sR = sG = sB = (GLfloat) As * ascale;
479 break;
480 case GL_ONE_MINUS_SRC_ALPHA:
481 sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale;
482 break;
483 case GL_DST_ALPHA:
484 sR = sG = sB = (GLfloat) Ad * ascale;
485 break;
486 case GL_ONE_MINUS_DST_ALPHA:
487 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
488 break;
489 case GL_SRC_ALPHA_SATURATE:
490 if (As < CHAN_MAX - Ad) {
491 sR = sG = sB = (GLfloat) As * ascale;
492 }
493 else {
494 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
495 }
496 break;
497 case GL_CONSTANT_COLOR:
498 sR = ctx->Color.BlendColor[0];
499 sG = ctx->Color.BlendColor[1];
500 sB = ctx->Color.BlendColor[2];
501 break;
502 case GL_ONE_MINUS_CONSTANT_COLOR:
503 sR = 1.0F - ctx->Color.BlendColor[0];
504 sG = 1.0F - ctx->Color.BlendColor[1];
505 sB = 1.0F - ctx->Color.BlendColor[2];
506 break;
507 case GL_CONSTANT_ALPHA:
508 sR = sG = sB = ctx->Color.BlendColor[3];
509 break;
510 case GL_ONE_MINUS_CONSTANT_ALPHA:
511 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
512 break;
513 default:
514 /* this should never happen */
515 gl_problem(ctx, "Bad blend source RGB factor in do_blend");
516 return;
517 }
518
519 /* Source Alpha factor */
520 switch (ctx->Color.BlendSrcA) {
521 case GL_ZERO:
522 sA = 0.0F;
523 break;
524 case GL_ONE:
525 sA = 1.0F;
526 break;
527 case GL_DST_COLOR:
528 sA = (GLfloat) Ad * ascale;
529 break;
530 case GL_ONE_MINUS_DST_COLOR:
531 sA = 1.0F - (GLfloat) Ad * ascale;
532 break;
533 case GL_SRC_ALPHA:
534 sA = (GLfloat) As * ascale;
535 break;
536 case GL_ONE_MINUS_SRC_ALPHA:
537 sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
538 break;
539 case GL_DST_ALPHA:
540 sA =(GLfloat) Ad * ascale;
541 break;
542 case GL_ONE_MINUS_DST_ALPHA:
543 sA = 1.0F - (GLfloat) Ad * ascale;
544 break;
545 case GL_SRC_ALPHA_SATURATE:
546 sA = 1.0;
547 break;
548 case GL_CONSTANT_COLOR:
549 sA = ctx->Color.BlendColor[3];
550 break;
551 case GL_ONE_MINUS_CONSTANT_COLOR:
552 sA = 1.0F - ctx->Color.BlendColor[3];
553 break;
554 case GL_CONSTANT_ALPHA:
555 sA = ctx->Color.BlendColor[3];
556 break;
557 case GL_ONE_MINUS_CONSTANT_ALPHA:
558 sA = 1.0F - ctx->Color.BlendColor[3];
559 break;
560 default:
561 /* this should never happen */
562 sA = 0.0F;
563 gl_problem(ctx, "Bad blend source A factor in do_blend");
564 }
565
566 /* Dest RGB factor */
567 switch (ctx->Color.BlendDstRGB) {
568 case GL_ZERO:
569 dR = dG = dB = 0.0F;
570 break;
571 case GL_ONE:
572 dR = dG = dB = 1.0F;
573 break;
574 case GL_SRC_COLOR:
575 dR = (GLfloat) Rs * rscale;
576 dG = (GLfloat) Gs * gscale;
577 dB = (GLfloat) Bs * bscale;
578 break;
579 case GL_ONE_MINUS_SRC_COLOR:
580 dR = 1.0F - (GLfloat) Rs * rscale;
581 dG = 1.0F - (GLfloat) Gs * gscale;
582 dB = 1.0F - (GLfloat) Bs * bscale;
583 break;
584 case GL_SRC_ALPHA:
585 dR = dG = dB = (GLfloat) As * ascale;
586 break;
587 case GL_ONE_MINUS_SRC_ALPHA:
588 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
589 break;
590 case GL_DST_ALPHA:
591 dR = dG = dB = (GLfloat) Ad * ascale;
592 break;
593 case GL_ONE_MINUS_DST_ALPHA:
594 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
595 break;
596 case GL_CONSTANT_COLOR:
597 dR = ctx->Color.BlendColor[0];
598 dG = ctx->Color.BlendColor[1];
599 dB = ctx->Color.BlendColor[2];
600 break;
601 case GL_ONE_MINUS_CONSTANT_COLOR:
602 dR = 1.0F - ctx->Color.BlendColor[0];
603 dG = 1.0F - ctx->Color.BlendColor[1];
604 dB = 1.0F - ctx->Color.BlendColor[2];
605 break;
606 case GL_CONSTANT_ALPHA:
607 dR = dG = dB = ctx->Color.BlendColor[3];
608 break;
609 case GL_ONE_MINUS_CONSTANT_ALPHA:
610 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
611 break;
612 default:
613 /* this should never happen */
614 dR = dG = dB = 0.0F;
615 gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
616 }
617
618 /* Dest Alpha factor */
619 switch (ctx->Color.BlendDstA) {
620 case GL_ZERO:
621 dA = 0.0F;
622 break;
623 case GL_ONE:
624 dA = 1.0F;
625 break;
626 case GL_SRC_COLOR:
627 dA = (GLfloat) As * ascale;
628 break;
629 case GL_ONE_MINUS_SRC_COLOR:
630 dA = 1.0F - (GLfloat) As * ascale;
631 break;
632 case GL_SRC_ALPHA:
633 dA = (GLfloat) As * ascale;
634 break;
635 case GL_ONE_MINUS_SRC_ALPHA:
636 dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
637 break;
638 case GL_DST_ALPHA:
639 dA = (GLfloat) Ad * ascale;
640 break;
641 case GL_ONE_MINUS_DST_ALPHA:
642 dA = 1.0F - (GLfloat) Ad * ascale;
643 break;
644 case GL_CONSTANT_COLOR:
645 dA = ctx->Color.BlendColor[3];
646 break;
647 case GL_ONE_MINUS_CONSTANT_COLOR:
648 dA = 1.0F - ctx->Color.BlendColor[3];
649 break;
650 case GL_CONSTANT_ALPHA:
651 dA = ctx->Color.BlendColor[3];
652 break;
653 case GL_ONE_MINUS_CONSTANT_ALPHA:
654 dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
655 break;
656 default:
657 /* this should never happen */
658 dA = 0.0F;
659 gl_problem(ctx, "Bad blend dest A factor in do_blend");
660 return;
661 }
662
663 /* Due to round-off problems we have to clamp against zero. */
664 /* Optimization: we don't have to do this for all src & dst factors */
665 if (dA < 0.0F) dA = 0.0F;
666 if (dR < 0.0F) dR = 0.0F;
667 if (dG < 0.0F) dG = 0.0F;
668 if (dB < 0.0F) dB = 0.0F;
669 if (sA < 0.0F) sA = 0.0F;
670 if (sR < 0.0F) sR = 0.0F;
671 if (sG < 0.0F) sG = 0.0F;
672 if (sB < 0.0F) sB = 0.0F;
673
674 ASSERT( sR <= 1.0 );
675 ASSERT( sG <= 1.0 );
676 ASSERT( sB <= 1.0 );
677 ASSERT( sA <= 1.0 );
678 ASSERT( dR <= 1.0 );
679 ASSERT( dG <= 1.0 );
680 ASSERT( dB <= 1.0 );
681 ASSERT( dA <= 1.0 );
682
683 /* compute blended color */
684 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
685 r = Rs * sR + Rd * dR;
686 g = Gs * sG + Gd * dG;
687 b = Bs * sB + Bd * dB;
688 a = As * sA + Ad * dA;
689 }
690 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
691 r = Rs * sR - Rd * dR;
692 g = Gs * sG - Gd * dG;
693 b = Bs * sB - Bd * dB;
694 a = As * sA - Ad * dA;
695 }
696 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
697 r = Rd * dR - Rs * sR;
698 g = Gd * dG - Gs * sG;
699 b = Bd * dB - Bs * sB;
700 a = Ad * dA - As * sA;
701 }
702 else {
703 /* should never get here */
704 r = g = b = a = 0.0F; /* silence uninitialized var warning */
705 gl_problem(ctx, "unexpected BlendEquation in blend_general()");
706 }
707
708 /* final clamping */
709 rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, CHAN_MAXF );
710 rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, CHAN_MAXF );
711 rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, CHAN_MAXF );
712 rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, CHAN_MAXF );
713 }
714 }
715 }
716
717
718
719 #if defined(USE_MMX_ASM)
720 #include "X86/mmx.h"
721 #include "X86/common_x86asm.h"
722 #endif
723
724
725 /*
726 * Analyze current blending parameters to pick fastest blending function.
727 * Result: the ctx->Color.BlendFunc pointer is updated.
728 */
729 static void set_blend_function( GLcontext *ctx )
730 {
731 const GLenum eq = ctx->Color.BlendEquation;
732 const GLenum srcRGB = ctx->Color.BlendSrcRGB;
733 const GLenum dstRGB = ctx->Color.BlendDstRGB;
734 const GLenum srcA = ctx->Color.BlendSrcA;
735 const GLenum dstA = ctx->Color.BlendDstA;
736
737 #if defined(USE_MMX_ASM)
738 /* Hmm. A table here would have 12^4 == way too many entries.
739 * Provide a hook for MMX instead.
740 */
741 if (gl_x86_cpu_features & GL_CPU_MMX) {
742 gl_mmx_set_blend_function (ctx);
743 }
744 else
745 #endif
746 if (srcRGB != srcA || dstRGB != dstA) {
747 ctx->Color.BlendFunc = blend_general;
748 }
749 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
750 && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
751 ctx->Color.BlendFunc = blend_transparency;
752 }
753 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
754 ctx->Color.BlendFunc = blend_add;
755 }
756 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
757 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
758 ||
759 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
760 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
761 ctx->Color.BlendFunc = blend_modulate;
762 }
763 else if (eq==GL_MIN_EXT) {
764 ctx->Color.BlendFunc = blend_min;
765 }
766 else if (eq==GL_MAX_EXT) {
767 ctx->Color.BlendFunc = blend_max;
768 }
769 else {
770 ctx->Color.BlendFunc = blend_general;
771 }
772 }
773
774
775
776 /*
777 * Apply the blending operator to a span of pixels.
778 * Input: n - number of pixels in span
779 * x, y - location of leftmost pixel in span in window coords.
780 * mask - boolean mask indicating which pixels to blend.
781 * In/Out: rgba - pixel values
782 */
783 void
784 _mesa_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
785 GLubyte rgba[][4], const GLubyte mask[] )
786 {
787 GLubyte dest[MAX_WIDTH][4];
788
789 /* Check if device driver can do the work */
790 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
791 return;
792 }
793
794 /* Read span of current frame buffer pixels */
795 gl_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
796
797 if (!ctx->Color.BlendFunc)
798 set_blend_function(ctx);
799
800 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
801 }
802
803
804
805
806
807 /*
808 * Apply the blending operator to an array of pixels.
809 * Input: n - number of pixels in span
810 * x, y - array of pixel locations
811 * mask - boolean mask indicating which pixels to blend.
812 * In/Out: rgba - pixel values
813 */
814 void
815 _mesa_blend_pixels( GLcontext *ctx,
816 GLuint n, const GLint x[], const GLint y[],
817 GLubyte rgba[][4], const GLubyte mask[] )
818 {
819 GLubyte dest[PB_SIZE][4];
820
821 /* Check if device driver can do the work */
822 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
823 return;
824 }
825
826 /* Read pixels from current color buffer */
827 (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
828 if (ctx->RasterMask & ALPHABUF_BIT) {
829 gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
830 }
831
832 if (!ctx->Color.BlendFunc)
833 set_blend_function(ctx);
834
835 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
836 }