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

Last change on this file since 2959 was 2938, checked in by sandervl, 25 years ago

created

File size: 25.2 KB
Line 
1/* $Id: blend.c,v 1.1 2000-02-29 00:49:59 sandervl 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 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 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 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 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 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 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 if (As < 1.0F - (GLfloat) Ad * ascale) {
484 sR = sG = sB = (GLfloat) As * ascale;
485 }
486 else {
487 sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
488 }
489 break;
490 case GL_CONSTANT_COLOR:
491 sR = ctx->Color.BlendColor[0];
492 sG = ctx->Color.BlendColor[1];
493 sB = ctx->Color.BlendColor[2];
494 break;
495 case GL_ONE_MINUS_CONSTANT_COLOR:
496 sR = 1.0F - ctx->Color.BlendColor[0];
497 sG = 1.0F - ctx->Color.BlendColor[1];
498 sB = 1.0F - ctx->Color.BlendColor[2];
499 break;
500 case GL_CONSTANT_ALPHA:
501 sR = sG = sB = ctx->Color.BlendColor[3];
502 break;
503 case GL_ONE_MINUS_CONSTANT_ALPHA:
504 sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
505 break;
506 default:
507 /* this should never happen */
508 gl_problem(ctx, "Bad blend source RGB factor in do_blend");
509 return;
510 }
511
512 /* Source Alpha factor */
513 switch (ctx->Color.BlendSrcA) {
514 case GL_ZERO:
515 sA = 0.0F;
516 break;
517 case GL_ONE:
518 sA = 1.0F;
519 break;
520 case GL_DST_COLOR:
521 sA = (GLfloat) Ad * ascale;
522 break;
523 case GL_ONE_MINUS_DST_COLOR:
524 sA = 1.0F - (GLfloat) Ad * ascale;
525 break;
526 case GL_SRC_ALPHA:
527 sA = (GLfloat) As * ascale;
528 break;
529 case GL_ONE_MINUS_SRC_ALPHA:
530 sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
531 break;
532 case GL_DST_ALPHA:
533 sA =(GLfloat) Ad * ascale;
534 break;
535 case GL_ONE_MINUS_DST_ALPHA:
536 sA = 1.0F - (GLfloat) Ad * ascale;
537 break;
538 case GL_SRC_ALPHA_SATURATE:
539 sA = 1.0;
540 break;
541 case GL_CONSTANT_COLOR:
542 sA = ctx->Color.BlendColor[3];
543 break;
544 case GL_ONE_MINUS_CONSTANT_COLOR:
545 sA = 1.0F - ctx->Color.BlendColor[3];
546 break;
547 case GL_CONSTANT_ALPHA:
548 sA = ctx->Color.BlendColor[3];
549 break;
550 case GL_ONE_MINUS_CONSTANT_ALPHA:
551 sA = 1.0F - ctx->Color.BlendColor[3];
552 break;
553 default:
554 /* this should never happen */
555 sA = 0.0F;
556 gl_problem(ctx, "Bad blend source A factor in do_blend");
557 }
558
559 /* Dest RGB factor */
560 switch (ctx->Color.BlendDstRGB) {
561 case GL_ZERO:
562 dR = dG = dB = 0.0F;
563 break;
564 case GL_ONE:
565 dR = dG = dB = 1.0F;
566 break;
567 case GL_SRC_COLOR:
568 dR = (GLfloat) Rs * rscale;
569 dG = (GLfloat) Gs * gscale;
570 dB = (GLfloat) Bs * bscale;
571 break;
572 case GL_ONE_MINUS_SRC_COLOR:
573 dR = 1.0F - (GLfloat) Rs * rscale;
574 dG = 1.0F - (GLfloat) Gs * gscale;
575 dB = 1.0F - (GLfloat) Bs * bscale;
576 break;
577 case GL_SRC_ALPHA:
578 dR = dG = dB = (GLfloat) As * ascale;
579 break;
580 case GL_ONE_MINUS_SRC_ALPHA:
581 dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
582 break;
583 case GL_DST_ALPHA:
584 dR = dG = dB = (GLfloat) Ad * ascale;
585 break;
586 case GL_ONE_MINUS_DST_ALPHA:
587 dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
588 break;
589 case GL_CONSTANT_COLOR:
590 dR = ctx->Color.BlendColor[0];
591 dG = ctx->Color.BlendColor[1];
592 dB = ctx->Color.BlendColor[2];
593 break;
594 case GL_ONE_MINUS_CONSTANT_COLOR:
595 dR = 1.0F - ctx->Color.BlendColor[0];
596 dG = 1.0F - ctx->Color.BlendColor[1];
597 dB = 1.0F - ctx->Color.BlendColor[2];
598 break;
599 case GL_CONSTANT_ALPHA:
600 dR = dG = dB = ctx->Color.BlendColor[3];
601 break;
602 case GL_ONE_MINUS_CONSTANT_ALPHA:
603 dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
604 break;
605 default:
606 /* this should never happen */
607 dR = dG = dB = 0.0F;
608 gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
609 }
610
611 /* Dest Alpha factor */
612 switch (ctx->Color.BlendDstA) {
613 case GL_ZERO:
614 dA = 0.0F;
615 break;
616 case GL_ONE:
617 dA = 1.0F;
618 break;
619 case GL_SRC_COLOR:
620 dA = (GLfloat) As * ascale;
621 break;
622 case GL_ONE_MINUS_SRC_COLOR:
623 dA = 1.0F - (GLfloat) As * ascale;
624 break;
625 case GL_SRC_ALPHA:
626 dA = (GLfloat) As * ascale;
627 break;
628 case GL_ONE_MINUS_SRC_ALPHA:
629 dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
630 break;
631 case GL_DST_ALPHA:
632 dA = (GLfloat) Ad * ascale;
633 break;
634 case GL_ONE_MINUS_DST_ALPHA:
635 dA = 1.0F - (GLfloat) Ad * ascale;
636 break;
637 case GL_CONSTANT_COLOR:
638 dA = ctx->Color.BlendColor[3];
639 break;
640 case GL_ONE_MINUS_CONSTANT_COLOR:
641 dA = 1.0F - ctx->Color.BlendColor[3];
642 break;
643 case GL_CONSTANT_ALPHA:
644 dA = ctx->Color.BlendColor[3];
645 break;
646 case GL_ONE_MINUS_CONSTANT_ALPHA:
647 dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
648 break;
649 default:
650 /* this should never happen */
651 dA = 0.0F;
652 gl_problem(ctx, "Bad blend dest A factor in do_blend");
653 return;
654 }
655
656 /* Due to round-off problems we have to clamp against zero. */
657 /* Optimization: we don't have to do this for all src & dst factors */
658 if (dA < 0.0F) dA = 0.0F;
659 if (dR < 0.0F) dR = 0.0F;
660 if (dG < 0.0F) dG = 0.0F;
661 if (dB < 0.0F) dB = 0.0F;
662 if (sA < 0.0F) sA = 0.0F;
663 if (sR < 0.0F) sR = 0.0F;
664 if (sG < 0.0F) sG = 0.0F;
665 if (sB < 0.0F) sB = 0.0F;
666
667 ASSERT( sR <= 1.0 );
668 ASSERT( sG <= 1.0 );
669 ASSERT( sB <= 1.0 );
670 ASSERT( sA <= 1.0 );
671 ASSERT( dR <= 1.0 );
672 ASSERT( dG <= 1.0 );
673 ASSERT( dB <= 1.0 );
674 ASSERT( dA <= 1.0 );
675
676 /* compute blended color */
677 if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
678 r = Rs * sR + Rd * dR;
679 g = Gs * sG + Gd * dG;
680 b = Bs * sB + Bd * dB;
681 a = As * sA + Ad * dA;
682 }
683 else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
684 r = Rs * sR - Rd * dR;
685 g = Gs * sG - Gd * dG;
686 b = Bs * sB - Bd * dB;
687 a = As * sA - Ad * dA;
688 }
689 else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
690 r = Rd * dR - Rs * sR;
691 g = Gd * dG - Gs * sG;
692 b = Bd * dB - Bs * sB;
693 a = Ad * dA - As * sA;
694 }
695 else {
696 /* should never get here */
697 r = g = b = a = 0.0F; /* silence uninitialized var warning */
698 gl_problem(ctx, "unexpected BlendEquation in blend_general()");
699 }
700
701 /* final clamping */
702 rgba[i][RCOMP] = (GLubyte) (GLint) CLAMP( r, 0.0F, 255.0F );
703 rgba[i][GCOMP] = (GLubyte) (GLint) CLAMP( g, 0.0F, 255.0F );
704 rgba[i][BCOMP] = (GLubyte) (GLint) CLAMP( b, 0.0F, 255.0F );
705 rgba[i][ACOMP] = (GLubyte) (GLint) CLAMP( a, 0.0F, 255.0F );
706 }
707 }
708}
709
710
711
712#if defined(USE_MMX_ASM)
713#include "mmx.h"
714#include "common_x86asm.h"
715#endif
716
717
718/*
719 * Analyze current blending parameters to pick fastest blending function.
720 * Result: the ctx->Color.BlendFunc pointer is updated.
721 */
722static void set_blend_function( GLcontext *ctx )
723{
724 const GLenum eq = ctx->Color.BlendEquation;
725 const GLenum srcRGB = ctx->Color.BlendSrcRGB;
726 const GLenum dstRGB = ctx->Color.BlendDstRGB;
727 const GLenum srcA = ctx->Color.BlendSrcA;
728 const GLenum dstA = ctx->Color.BlendDstA;
729
730#if defined(USE_MMX_ASM)
731 /* Hmm. A table here would have 12^4 == way too many entries.
732 * Provide a hook for MMX instead.
733 */
734#ifdef __WIN32OS2__
735 if (CPUFeatures & CPUID_MMX) {
736 gl_mmx_set_blend_function (ctx);
737 } else
738#else
739 if (gl_x86_cpu_features & GL_CPU_MMX) {
740 gl_mmx_set_blend_function (ctx);
741 } else
742#endif
743#endif
744 if (srcRGB != srcA || dstRGB != dstA) {
745 ctx->Color.BlendFunc = blend_general;
746 }
747 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
748 && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
749 ctx->Color.BlendFunc = blend_transparency;
750 }
751 else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
752 ctx->Color.BlendFunc = blend_add;
753 }
754 else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
755 && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
756 ||
757 ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
758 && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
759 ctx->Color.BlendFunc = blend_modulate;
760 }
761 else if (eq==GL_MIN_EXT) {
762 ctx->Color.BlendFunc = blend_min;
763 }
764 else if (eq==GL_MAX_EXT) {
765 ctx->Color.BlendFunc = blend_max;
766 }
767 else {
768 ctx->Color.BlendFunc = blend_general;
769 }
770}
771
772
773
774/*
775 * Apply the blending operator to a span of pixels.
776 * Input: n - number of pixels in span
777 * x, y - location of leftmost pixel in span in window coords.
778 * mask - boolean mask indicating which pixels to blend.
779 * In/Out: rgba - pixel values
780 */
781void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
782 GLubyte rgba[][4], const GLubyte mask[] )
783{
784 GLubyte dest[MAX_WIDTH][4];
785
786 /* Check if device driver can do the work */
787 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
788 return;
789 }
790
791 /* Read span of current frame buffer pixels */
792 gl_read_rgba_span( ctx, n, x, y, dest );
793
794 if (!ctx->Color.BlendFunc)
795 set_blend_function(ctx);
796
797 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
798}
799
800
801
802
803
804/*
805 * Apply the blending operator to an array of pixels.
806 * Input: n - number of pixels in span
807 * x, y - array of pixel locations
808 * mask - boolean mask indicating which pixels to blend.
809 * In/Out: rgba - pixel values
810 */
811void gl_blend_pixels( GLcontext *ctx,
812 GLuint n, const GLint x[], const GLint y[],
813 GLubyte rgba[][4], const GLubyte mask[] )
814{
815 GLubyte dest[PB_SIZE][4];
816
817 /* Check if device driver can do the work */
818 if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
819 return;
820 }
821
822 /* Read pixels from current color buffer */
823 (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
824 if (ctx->RasterMask & ALPHABUF_BIT) {
825 gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
826 }
827
828 if (!ctx->Color.BlendFunc)
829 set_blend_function(ctx);
830
831 (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
832}
Note: See TracBrowser for help on using the repository browser.