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