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