Subversion Repositories shark

Rev

Rev 57 | Details | Compare with Previous | Last modification | View Log | RSS feed

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