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

Last change on this file since 2965 was 2962, checked in by jeroen, 25 years ago

* empty log message *

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