added memory macros
[mesa.git] / src / mesa / main / blend.c
1 /* $Id: blend.c,v 1.4 1999/10/08 09:27:10 keithw 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 gl_problem(ctx, "Bad blend source A factor in do_blend");
555 }
556
557 /* Dest RGB factor */
558 switch (ctx->Color.BlendDstRGB) {
559 case GL_ZERO:
560 dR = dG = dB = 0.0F;
561 break;
562 case GL_ONE:
563 dR = dG = dB = 1.0F;
564 break;
565 case GL_SRC_COLOR:
566 dR = (GLfloat) Rs * rscale;
567 dG = (GLfloat) Gs * gscale;
568 dB = (GLfloat) Bs * bscale;
569 break;
570 case GL_ONE_MINUS_SRC_COLOR:
571 dR = 1.0F - (GLfloat) Rs * rscale;
572 dG = 1.0F - (GLfloat) Gs * gscale;
573 dB = 1.0F - (GLfloat) Bs * bscale;
574 break;
575 case GL_SRC_ALPHA:
576 dR = dG = dB = (GLfloat) As * ascale;
577 break;
578 case GL_ONE_MINUS_SRC_ALPHA:
579 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
580 break;
581 case GL_DST_ALPHA:
582 dR = dG = dB = (GLfloat) Ad * ascale;
583 break;
584 case GL_ONE_MINUS_DST_ALPHA:
585 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
586 break;
587 case GL_CONSTANT_COLOR:
588 dR = ctx->Color.BlendColor[0];
589 dG = ctx->Color.BlendColor[1];
590 dB = ctx->Color.BlendColor[2];
591 break;
592 case GL_ONE_MINUS_CONSTANT_COLOR:
593 dR = 1.0F - ctx->Color.BlendColor[0];
594 dG = 1.0F - ctx->Color.BlendColor[1];
595 dB = 1.0F - ctx->Color.BlendColor[2];
596 break;
597 case GL_CONSTANT_ALPHA:
598 dR = dG = dB = ctx->Color.BlendColor[3];
599 break;
600 case GL_ONE_MINUS_CONSTANT_ALPHA:
601 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
602 break;
603 default:
604 /* this should never happen */
605 gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
606 }
607
608 /* Dest Alpha factor */
609 switch (ctx->Color.BlendDstA) {
610 case GL_ZERO:
611 dA = 0.0F;
612 break;
613 case GL_ONE:
614 dA = 1.0F;
615 break;
616 case GL_SRC_COLOR:
617 dA = (GLfloat) As * ascale;
618 break;
619 case GL_ONE_MINUS_SRC_COLOR:
620 dA = 1.0F - (GLfloat) As * ascale;
621 break;
622 case GL_SRC_ALPHA:
623 dA = (GLfloat) As * ascale;
624 break;
625 case GL_ONE_MINUS_SRC_ALPHA:
626 dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
627 break;
628 case GL_DST_ALPHA:
629 dA = (GLfloat) Ad * ascale;
630 break;
631 case GL_ONE_MINUS_DST_ALPHA:
632 dA = 1.0F - (GLfloat) Ad * ascale;
633 break;
634 case GL_CONSTANT_COLOR:
635 dA = ctx->Color.BlendColor[3];
636 break;
637 case GL_ONE_MINUS_CONSTANT_COLOR:
638 dA = 1.0F - ctx->Color.BlendColor[3];
639 break;
640 case GL_CONSTANT_ALPHA:
641 dA = ctx->Color.BlendColor[3];
642 break;
643 case GL_ONE_MINUS_CONSTANT_ALPHA:
644 dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
645 break;
646 default:
647 /* this should never happen */
648 gl_problem(ctx, "Bad blend dest A factor in do_blend");
649 return;
650 }
651
652 /* Due to round-off problems we have to clamp against zero. */
653 /* Optimization: we don't have to do this for all src & dst factors */
654 if (dA < 0.0F) dA = 0.0F;
655 if (dR < 0.0F) dR = 0.0F;
656 if (dG < 0.0F) dG = 0.0F;
657 if (dB < 0.0F) dB = 0.0F;
658 if (sA < 0.0F) sA = 0.0F;
659 if (sR < 0.0F) sR = 0.0F;
660 if (sG < 0.0F) sG = 0.0F;
661 if (sB < 0.0F) sB = 0.0F;
662
663 ASSERT( sR <= 1.0 );
664 ASSERT( sG <= 1.0 );
665 ASSERT( sB <= 1.0 );
666 ASSERT( sA <= 1.0 );
667 ASSERT( dR <= 1.0 );
668 ASSERT( dG <= 1.0 );
669 ASSERT( dB <= 1.0 );
670 ASSERT( dA <= 1.0 );
671
672 /* compute blended color */
673 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
674 r = Rs * sR + Rd * dR;
675 g = Gs * sG + Gd * dG;
676 b = Bs * sB + Bd * dB;
677 a = As * sA + Ad * dA;
678 }
679 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
680 r = Rs * sR - Rd * dR;
681 g = Gs * sG - Gd * dG;
682 b = Bs * sB - Bd * dB;
683 a = As * sA - Ad * dA;
684 }
685 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
686 r = Rd * dR - Rs * sR;
687 g = Gd * dG - Gs * sG;
688 b = Bd * dB - Bs * sB;
689 a = Ad * dA - As * sA;
690 }
691
692 /* final clamping */
693 rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F );
694 rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F );
695 rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F );
696 rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F );
697 }
698 }
699 }
700
701
702
703 #if defined(USE_MMX_ASM)
704 #include "X86/mmx.h"
705 #include "X86/common_x86asm.h"
706 #endif
707
708
709 /*
710 * Analyze current blending parameters to pick fastest blending function.
711 * Result: the ctx->Color.BlendFunc pointer is updated.
712 */
713 static void set_blend_function( GLcontext *ctx )
714 {
715 const GLenum eq = ctx->Color.BlendEquation;
716 const GLenum srcRGB = ctx->Color.BlendSrcRGB;
717 const GLenum dstRGB = ctx->Color.BlendDstRGB;
718 const GLenum srcA = ctx->Color.BlendSrcA;
719 const GLenum dstA = ctx->Color.BlendDstA;
720
721 #if defined(USE_MMX_ASM)
722 /* Hmm. A table here would have 12^4 == way too many entries.
723 * Provide a hook for MMX instead.
724 */
725 if (gl_x86_cpu_features & GL_CPU_MMX) {
726 gl_mmx_set_blend_function (ctx);
727 } else
728 #endif
729 if (srcRGB != srcA || dstRGB != dstA) {
730 ctx->Color.BlendFunc = blend_general;
731 }
732 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
733 && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
734 ctx->Color.BlendFunc = blend_transparency;
735 }
736 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
737 ctx->Color.BlendFunc = blend_add;
738 }
739 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
740 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
741 ||
742 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
743 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
744 ctx->Color.BlendFunc = blend_modulate;
745 }
746 else if (eq==GL_MIN_EXT) {
747 ctx->Color.BlendFunc = blend_min;
748 }
749 else if (eq==GL_MAX_EXT) {
750 ctx->Color.BlendFunc = blend_max;
751 }
752 else {
753 ctx->Color.BlendFunc = blend_general;
754 }
755 }
756
757
758
759 /*
760 * Apply the blending operator to a span of pixels.
761 * Input: n - number of pixels in span
762 * x, y - location of leftmost pixel in span in window coords.
763 * mask - boolean mask indicating which pixels to blend.
764 * In/Out: rgba - pixel values
765 */
766 void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
767 GLubyte rgba[][4], const GLubyte mask[] )
768 {
769 GLubyte dest[MAX_WIDTH][4];
770
771 /* Check if device driver can do the work */
772 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
773 return;
774 }
775
776 /* Read span of current frame buffer pixels */
777 gl_read_rgba_span( ctx, n, x, y, dest );
778
779 if (!ctx->Color.BlendFunc)
780 set_blend_function(ctx);
781
782 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
783 }
784
785
786
787
788
789 /*
790 * Apply the blending operator to an array of pixels.
791 * Input: n - number of pixels in span
792 * x, y - array of pixel locations
793 * mask - boolean mask indicating which pixels to blend.
794 * In/Out: rgba - pixel values
795 */
796 void gl_blend_pixels( GLcontext *ctx,
797 GLuint n, const GLint x[], const GLint y[],
798 GLubyte rgba[][4], const GLubyte mask[] )
799 {
800 GLubyte dest[PB_SIZE][4];
801
802 /* Check if device driver can do the work */
803 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
804 return;
805 }
806
807 /* Read pixels from current color buffer */
808 (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
809 if (ctx->RasterMask & ALPHABUF_BIT) {
810 gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
811 }
812
813 if (!ctx->Color.BlendFunc)
814 set_blend_function(ctx);
815
816 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
817 }