source: trunk/src/opengl/mesa/blend.c@ 3721

Last change on this file since 3721 was 3598, checked in by jeroen, 25 years ago

* empty log message *

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