OSDN Git Service

4423d5b17eeb0ddc70f7658be2d9ce05fe222794
[android-x86/external-mesa.git] / src / mesa / swrast / s_blend.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26
27 /**
28  * \file swrast/s_blend.c
29  * \brief software blending.
30  * \author Brian Paul
31  *
32  * Only a few blend modes have been optimized (min, max, transparency, add)
33  * more optimized cases can easily be added if needed.
34  * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example.
35  */
36
37
38
39 #include "main/glheader.h"
40 #include "main/context.h"
41 #include "main/colormac.h"
42 #include "main/macros.h"
43
44 #include "s_blend.h"
45 #include "s_context.h"
46 #include "s_span.h"
47
48
49 #if defined(USE_MMX_ASM)
50 #include "x86/mmx.h"
51 #include "x86/common_x86_asm.h"
52 #define _BLENDAPI _ASMAPI
53 #else
54 #define _BLENDAPI
55 #endif
56
57
58 /**
59  * Integer divide by 255
60  * Declare "int divtemp" before using.
61  * This satisfies Glean and should be reasonably fast.
62  * Contributed by Nathan Hand.
63  */
64 #define DIV255(X)  (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16)
65
66
67
68 /**
69  * Special case for glBlendFunc(GL_ZERO, GL_ONE).
70  * No-op means the framebuffer values remain unchanged.
71  * Any chanType ok.
72  */
73 static void _BLENDAPI
74 blend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[],
75            GLvoid *src, const GLvoid *dst, GLenum chanType)
76 {
77    GLint bytes;
78
79    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
80    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
81    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ZERO);
82    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
83    (void) ctx;
84
85    /* just memcpy */
86    if (chanType == GL_UNSIGNED_BYTE)
87       bytes = 4 * n * sizeof(GLubyte);
88    else if (chanType == GL_UNSIGNED_SHORT)
89       bytes = 4 * n * sizeof(GLushort);
90    else
91       bytes = 4 * n * sizeof(GLfloat);
92
93    memcpy(src, dst, bytes);
94 }
95
96
97 /**
98  * Special case for glBlendFunc(GL_ONE, GL_ZERO)
99  * Any chanType ok.
100  */
101 static void _BLENDAPI
102 blend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[],
103               GLvoid *src, const GLvoid *dst, GLenum chanType)
104 {
105    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
106    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
107    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
108    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ZERO);
109    (void) ctx;
110    (void) n;
111    (void) mask;
112    (void) src;
113    (void) dst;
114 }
115
116
117 /**
118  * Common transparency blending mode:
119  * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
120  */
121 static void _BLENDAPI
122 blend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[],
123                          GLvoid *src, const GLvoid *dst, GLenum chanType)
124 {
125    GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
126    const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
127    GLuint i;
128
129    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
130    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
131    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
132    ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
133    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
134    ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
135    ASSERT(chanType == GL_UNSIGNED_BYTE);
136
137    (void) ctx;
138
139    for (i = 0; i < n; i++) {
140       if (mask[i]) {
141          const GLint t = rgba[i][ACOMP];  /* t is in [0, 255] */
142          if (t == 0) {
143             /* 0% alpha */
144             COPY_4UBV(rgba[i], dest[i]);
145          }
146          else if (t != 255) {
147             GLint divtemp;
148             const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP];
149             const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP];
150             const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP];
151             const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; 
152             ASSERT(r <= 255);
153             ASSERT(g <= 255);
154             ASSERT(b <= 255);
155             ASSERT(a <= 255);
156             rgba[i][RCOMP] = (GLubyte) r;
157             rgba[i][GCOMP] = (GLubyte) g;
158             rgba[i][BCOMP] = (GLubyte) b;
159             rgba[i][ACOMP] = (GLubyte) a;
160          }
161       }
162    }
163 }
164
165
166 static void _BLENDAPI
167 blend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[],
168                           GLvoid *src, const GLvoid *dst, GLenum chanType)
169 {
170    GLushort (*rgba)[4] = (GLushort (*)[4]) src;
171    const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
172    GLuint i;
173
174    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
175    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
176    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
177    ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
178    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
179    ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
180    ASSERT(chanType == GL_UNSIGNED_SHORT);
181
182    (void) ctx;
183
184    for (i = 0; i < n; i++) {
185       if (mask[i]) {
186          const GLint t = rgba[i][ACOMP];
187          if (t == 0) {
188             /* 0% alpha */
189             COPY_4V(rgba[i], dest[i]);
190          }
191          else if (t != 65535) {
192             const GLfloat tt = (GLfloat) t / 65535.0F;
193             GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]);
194             GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]);
195             GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]);
196             GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]);
197             ASSIGN_4V(rgba[i], r, g, b, a);
198          }
199       }
200    }
201 }
202
203
204 static void _BLENDAPI
205 blend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
206                          GLvoid *src, const GLvoid *dst, GLenum chanType)
207 {
208    GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
209    const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
210    GLuint i;
211
212    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
213    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
214    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA);
215    ASSERT(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA);
216    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA);
217    ASSERT(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA);
218    ASSERT(chanType == GL_FLOAT);
219
220    (void) ctx;
221
222    for (i = 0; i < n; i++) {
223       if (mask[i]) {
224          const GLfloat t = rgba[i][ACOMP];  /* t in [0, 1] */
225          if (t == 0.0F) {
226             /* 0% alpha */
227             COPY_4V(rgba[i], dest[i]);
228          }
229          else if (t != 1.0F) {
230             GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP];
231             GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP];
232             GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP];
233             GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP];
234             ASSIGN_4V(rgba[i], r, g, b, a);
235          }
236       }
237    }
238 }
239
240
241
242 /**
243  * Add src and dest: glBlendFunc(GL_ONE, GL_ONE).
244  * Any chanType ok.
245  */
246 static void _BLENDAPI
247 blend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[],
248           GLvoid *src, const GLvoid *dst, GLenum chanType)
249 {
250    GLuint i;
251
252    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD);
253    ASSERT(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD);
254    ASSERT(ctx->Color.Blend[0].SrcRGB == GL_ONE);
255    ASSERT(ctx->Color.Blend[0].DstRGB == GL_ONE);
256    (void) ctx;
257
258    if (chanType == GL_UNSIGNED_BYTE) {
259       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
260       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
261       for (i=0;i<n;i++) {
262          if (mask[i]) {
263             GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
264             GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
265             GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
266             GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
267             rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 );
268             rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 );
269             rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 );
270             rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 );
271          }
272       }
273    }
274    else if (chanType == GL_UNSIGNED_SHORT) {
275       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
276       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
277       for (i=0;i<n;i++) {
278          if (mask[i]) {
279             GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
280             GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
281             GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
282             GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
283             rgba[i][RCOMP] = (GLshort) MIN2( r, 255 );
284             rgba[i][GCOMP] = (GLshort) MIN2( g, 255 );
285             rgba[i][BCOMP] = (GLshort) MIN2( b, 255 );
286             rgba[i][ACOMP] = (GLshort) MIN2( a, 255 );
287          }
288       }
289    }
290    else {
291       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
292       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
293       ASSERT(chanType == GL_FLOAT);
294       for (i=0;i<n;i++) {
295          if (mask[i]) {
296             /* don't RGB clamp to max */
297             rgba[i][RCOMP] += dest[i][RCOMP];
298             rgba[i][GCOMP] += dest[i][GCOMP];
299             rgba[i][BCOMP] += dest[i][BCOMP];
300             rgba[i][ACOMP] += dest[i][ACOMP];
301          }
302       }
303    }
304 }
305
306
307
308 /**
309  * Blend min function.
310  * Any chanType ok.
311  */
312 static void _BLENDAPI
313 blend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[],
314           GLvoid *src, const GLvoid *dst, GLenum chanType)
315 {
316    GLuint i;
317    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MIN);
318    ASSERT(ctx->Color.Blend[0].EquationA == GL_MIN);
319    (void) ctx;
320
321    if (chanType == GL_UNSIGNED_BYTE) {
322       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
323       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
324       for (i=0;i<n;i++) {
325          if (mask[i]) {
326             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
327             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
328             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
329             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
330          }
331       }
332    }
333    else if (chanType == GL_UNSIGNED_SHORT) {
334       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
335       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
336       for (i=0;i<n;i++) {
337          if (mask[i]) {
338             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
339             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
340             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
341             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
342          }
343       }
344    }
345    else {
346       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
347       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
348       ASSERT(chanType == GL_FLOAT);
349       for (i=0;i<n;i++) {
350          if (mask[i]) {
351             rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
352             rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
353             rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
354             rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
355          }
356       }
357    }
358 }
359
360
361 /**
362  * Blend max function.
363  * Any chanType ok.
364  */
365 static void _BLENDAPI
366 blend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[],
367           GLvoid *src, const GLvoid *dst, GLenum chanType)
368 {
369    GLuint i;
370    ASSERT(ctx->Color.Blend[0].EquationRGB == GL_MAX);
371    ASSERT(ctx->Color.Blend[0].EquationA == GL_MAX);
372    (void) ctx;
373
374    if (chanType == GL_UNSIGNED_BYTE) {
375       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
376       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
377       for (i=0;i<n;i++) {
378          if (mask[i]) {
379             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
380             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
381             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
382             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
383          }
384       }
385    }
386    else if (chanType == GL_UNSIGNED_SHORT) {
387       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
388       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
389       for (i=0;i<n;i++) {
390          if (mask[i]) {
391             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
392             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
393             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
394             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
395          }
396       }
397    }
398    else {
399       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
400       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
401       ASSERT(chanType == GL_FLOAT);
402       for (i=0;i<n;i++) {
403          if (mask[i]) {
404             rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
405             rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
406             rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
407             rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
408          }
409       }
410    }
411 }
412
413
414
415 /**
416  * Modulate:  result = src * dest
417  * Any chanType ok.
418  */
419 static void _BLENDAPI
420 blend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[],
421                GLvoid *src, const GLvoid *dst, GLenum chanType)
422 {
423    GLuint i;
424    (void) ctx;
425
426    if (chanType == GL_UNSIGNED_BYTE) {
427       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
428       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
429       for (i=0;i<n;i++) {
430          if (mask[i]) {
431             GLint divtemp;
432             rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]);
433             rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]);
434             rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]);
435             rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]);
436          }
437       }
438    }
439    else if (chanType == GL_UNSIGNED_SHORT) {
440       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
441       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
442       for (i=0;i<n;i++) {
443          if (mask[i]) {
444             rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16;
445             rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16;
446             rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16;
447             rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16;
448          }
449       }
450    }
451    else {
452       GLfloat (*rgba)[4] = (GLfloat (*)[4]) src;
453       const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst;
454       ASSERT(chanType == GL_FLOAT);
455       for (i=0;i<n;i++) {
456          if (mask[i]) {
457             rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP];
458             rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP];
459             rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP];
460             rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP];
461          }
462       }
463    }
464 }
465
466
467 /**
468  * Do any blending operation, using floating point.
469  * \param n  number of pixels
470  * \param mask  fragment writemask array
471  * \param rgba  array of incoming (and modified) pixels
472  * \param dest  array of pixels from the dest color buffer
473  */
474 static void
475 blend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[],
476                     GLfloat rgba[][4], GLfloat dest[][4],
477                     GLenum chanType)
478 {
479    GLuint i;
480
481    for (i = 0; i < n; i++) {
482       if (mask[i]) {
483          /* Incoming/source Color */
484          const GLfloat Rs = rgba[i][RCOMP];
485          const GLfloat Gs = rgba[i][GCOMP];
486          const GLfloat Bs = rgba[i][BCOMP];
487          const GLfloat As = rgba[i][ACOMP];
488
489          /* Frame buffer/dest color */
490          const GLfloat Rd = dest[i][RCOMP];
491          const GLfloat Gd = dest[i][GCOMP];
492          const GLfloat Bd = dest[i][BCOMP];
493          const GLfloat Ad = dest[i][ACOMP];
494
495          GLfloat sR, sG, sB, sA;  /* Source factor */
496          GLfloat dR, dG, dB, dA;  /* Dest factor */
497          GLfloat r, g, b, a;      /* result color */
498
499          /* XXX for the case of constant blend terms we could init
500           * the sX and dX variables just once before the loop.
501           */
502
503          /* Source RGB factor */
504          switch (ctx->Color.Blend[0].SrcRGB) {
505             case GL_ZERO:
506                sR = sG = sB = 0.0F;
507                break;
508             case GL_ONE:
509                sR = sG = sB = 1.0F;
510                break;
511             case GL_DST_COLOR:
512                sR = Rd;
513                sG = Gd;
514                sB = Bd;
515                break;
516             case GL_ONE_MINUS_DST_COLOR:
517                sR = 1.0F - Rd;
518                sG = 1.0F - Gd;
519                sB = 1.0F - Bd;
520                break;
521             case GL_SRC_ALPHA:
522                sR = sG = sB = As;
523                break;
524             case GL_ONE_MINUS_SRC_ALPHA:
525                sR = sG = sB = 1.0F - As;
526                break;
527             case GL_DST_ALPHA:
528                sR = sG = sB = Ad;
529                break;
530             case GL_ONE_MINUS_DST_ALPHA:
531                sR = sG = sB = 1.0F - Ad;
532                break;
533             case GL_SRC_ALPHA_SATURATE:
534                if (As < 1.0F - Ad) {
535                   sR = sG = sB = As;
536                }
537                else {
538                   sR = sG = sB = 1.0F - Ad;
539                }
540                break;
541             case GL_CONSTANT_COLOR:
542                sR = ctx->Color.BlendColor[0];
543                sG = ctx->Color.BlendColor[1];
544                sB = ctx->Color.BlendColor[2];
545                break;
546             case GL_ONE_MINUS_CONSTANT_COLOR:
547                sR = 1.0F - ctx->Color.BlendColor[0];
548                sG = 1.0F - ctx->Color.BlendColor[1];
549                sB = 1.0F - ctx->Color.BlendColor[2];
550                break;
551             case GL_CONSTANT_ALPHA:
552                sR = sG = sB = ctx->Color.BlendColor[3];
553                break;
554             case GL_ONE_MINUS_CONSTANT_ALPHA:
555                sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
556                break;
557             case GL_SRC_COLOR:
558                sR = Rs;
559                sG = Gs;
560                sB = Bs;
561                break;
562             case GL_ONE_MINUS_SRC_COLOR:
563                sR = 1.0F - Rs;
564                sG = 1.0F - Gs;
565                sB = 1.0F - Bs;
566                break;
567             default:
568                /* this should never happen */
569                _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float");
570                return;
571          }
572
573          /* Source Alpha factor */
574          switch (ctx->Color.Blend[0].SrcA) {
575             case GL_ZERO:
576                sA = 0.0F;
577                break;
578             case GL_ONE:
579                sA = 1.0F;
580                break;
581             case GL_DST_COLOR:
582                sA = Ad;
583                break;
584             case GL_ONE_MINUS_DST_COLOR:
585                sA = 1.0F - Ad;
586                break;
587             case GL_SRC_ALPHA:
588                sA = As;
589                break;
590             case GL_ONE_MINUS_SRC_ALPHA:
591                sA = 1.0F - As;
592                break;
593             case GL_DST_ALPHA:
594                sA = Ad;
595                break;
596             case GL_ONE_MINUS_DST_ALPHA:
597                sA = 1.0F - Ad;
598                break;
599             case GL_SRC_ALPHA_SATURATE:
600                sA = 1.0;
601                break;
602             case GL_CONSTANT_COLOR:
603                sA = ctx->Color.BlendColor[3];
604                break;
605             case GL_ONE_MINUS_CONSTANT_COLOR:
606                sA = 1.0F - ctx->Color.BlendColor[3];
607                break;
608             case GL_CONSTANT_ALPHA:
609                sA = ctx->Color.BlendColor[3];
610                break;
611             case GL_ONE_MINUS_CONSTANT_ALPHA:
612                sA = 1.0F - ctx->Color.BlendColor[3];
613                break;
614             case GL_SRC_COLOR:
615                sA = As;
616                break;
617             case GL_ONE_MINUS_SRC_COLOR:
618                sA = 1.0F - As;
619                break;
620             default:
621                /* this should never happen */
622                sA = 0.0F;
623                _mesa_problem(ctx, "Bad blend source A factor in blend_general_float");
624                return;
625          }
626
627          /* Dest RGB factor */
628          switch (ctx->Color.Blend[0].DstRGB) {
629             case GL_ZERO:
630                dR = dG = dB = 0.0F;
631                break;
632             case GL_ONE:
633                dR = dG = dB = 1.0F;
634                break;
635             case GL_SRC_COLOR:
636                dR = Rs;
637                dG = Gs;
638                dB = Bs;
639                break;
640             case GL_ONE_MINUS_SRC_COLOR:
641                dR = 1.0F - Rs;
642                dG = 1.0F - Gs;
643                dB = 1.0F - Bs;
644                break;
645             case GL_SRC_ALPHA:
646                dR = dG = dB = As;
647                break;
648             case GL_ONE_MINUS_SRC_ALPHA:
649                dR = dG = dB = 1.0F - As;
650                break;
651             case GL_DST_ALPHA:
652                dR = dG = dB = Ad;
653                break;
654             case GL_ONE_MINUS_DST_ALPHA:
655                dR = dG = dB = 1.0F - Ad;
656                break;
657             case GL_CONSTANT_COLOR:
658                dR = ctx->Color.BlendColor[0];
659                dG = ctx->Color.BlendColor[1];
660                dB = ctx->Color.BlendColor[2];
661                break;
662             case GL_ONE_MINUS_CONSTANT_COLOR:
663                dR = 1.0F - ctx->Color.BlendColor[0];
664                dG = 1.0F - ctx->Color.BlendColor[1];
665                dB = 1.0F - ctx->Color.BlendColor[2];
666                break;
667             case GL_CONSTANT_ALPHA:
668                dR = dG = dB = ctx->Color.BlendColor[3];
669                break;
670             case GL_ONE_MINUS_CONSTANT_ALPHA:
671                dR = dG = dB = 1.0F - ctx->Color.BlendColor[3];
672                break;
673             case GL_DST_COLOR:
674                dR = Rd;
675                dG = Gd;
676                dB = Bd;
677                break;
678             case GL_ONE_MINUS_DST_COLOR:
679                dR = 1.0F - Rd;
680                dG = 1.0F - Gd;
681                dB = 1.0F - Bd;
682                break;
683             default:
684                /* this should never happen */
685                dR = dG = dB = 0.0F;
686                _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float");
687                return;
688          }
689
690          /* Dest Alpha factor */
691          switch (ctx->Color.Blend[0].DstA) {
692             case GL_ZERO:
693                dA = 0.0F;
694                break;
695             case GL_ONE:
696                dA = 1.0F;
697                break;
698             case GL_SRC_COLOR:
699                dA = As;
700                break;
701             case GL_ONE_MINUS_SRC_COLOR:
702                dA = 1.0F - As;
703                break;
704             case GL_SRC_ALPHA:
705                dA = As;
706                break;
707             case GL_ONE_MINUS_SRC_ALPHA:
708                dA = 1.0F - As;
709                break;
710             case GL_DST_ALPHA:
711                dA = Ad;
712                break;
713             case GL_ONE_MINUS_DST_ALPHA:
714                dA = 1.0F - Ad;
715                break;
716             case GL_CONSTANT_COLOR:
717                dA = ctx->Color.BlendColor[3];
718                break;
719             case GL_ONE_MINUS_CONSTANT_COLOR:
720                dA = 1.0F - ctx->Color.BlendColor[3];
721                break;
722             case GL_CONSTANT_ALPHA:
723                dA = ctx->Color.BlendColor[3];
724                break;
725             case GL_ONE_MINUS_CONSTANT_ALPHA:
726                dA = 1.0F - ctx->Color.BlendColor[3];
727                break;
728             case GL_DST_COLOR:
729                dA = Ad;
730                break;
731             case GL_ONE_MINUS_DST_COLOR:
732                dA = 1.0F - Ad;
733                break;
734             default:
735                /* this should never happen */
736                dA = 0.0F;
737                _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float");
738                return;
739          }
740
741          /* compute the blended RGB */
742          switch (ctx->Color.Blend[0].EquationRGB) {
743          case GL_FUNC_ADD:
744             r = Rs * sR + Rd * dR;
745             g = Gs * sG + Gd * dG;
746             b = Bs * sB + Bd * dB;
747             a = As * sA + Ad * dA;
748             break;
749          case GL_FUNC_SUBTRACT:
750             r = Rs * sR - Rd * dR;
751             g = Gs * sG - Gd * dG;
752             b = Bs * sB - Bd * dB;
753             a = As * sA - Ad * dA;
754             break;
755          case GL_FUNC_REVERSE_SUBTRACT:
756             r = Rd * dR - Rs * sR;
757             g = Gd * dG - Gs * sG;
758             b = Bd * dB - Bs * sB;
759             a = Ad * dA - As * sA;
760             break;
761          case GL_MIN:
762             r = MIN2( Rd, Rs );
763             g = MIN2( Gd, Gs );
764             b = MIN2( Bd, Bs );
765             break;
766          case GL_MAX:
767             r = MAX2( Rd, Rs );
768             g = MAX2( Gd, Gs );
769             b = MAX2( Bd, Bs );
770             break;
771          default:
772             /* should never get here */
773             r = g = b = 0.0F;  /* silence uninitialized var warning */
774             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
775             return;
776          }
777
778          /* compute the blended alpha */
779          switch (ctx->Color.Blend[0].EquationA) {
780          case GL_FUNC_ADD:
781             a = As * sA + Ad * dA;
782             break;
783          case GL_FUNC_SUBTRACT:
784             a = As * sA - Ad * dA;
785             break;
786          case GL_FUNC_REVERSE_SUBTRACT:
787             a = Ad * dA - As * sA;
788             break;
789          case GL_MIN:
790             a = MIN2( Ad, As );
791             break;
792          case GL_MAX:
793             a = MAX2( Ad, As );
794             break;
795          default:
796             /* should never get here */
797             a = 0.0F;  /* silence uninitialized var warning */
798             _mesa_problem(ctx, "unexpected BlendEquation in blend_general()");
799             return;
800          }
801
802          /* final clamping */
803 #if 0
804          rgba[i][RCOMP] = MAX2( r, 0.0F );
805          rgba[i][GCOMP] = MAX2( g, 0.0F );
806          rgba[i][BCOMP] = MAX2( b, 0.0F );
807          rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F );
808 #else
809          ASSIGN_4V(rgba[i], r, g, b, a);
810 #endif
811       }
812    }
813 }
814
815
816 /**
817  * Do any blending operation, any chanType.
818  */
819 static void
820 blend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[],
821               void *src, const void *dst, GLenum chanType)
822 {
823    GLfloat (*rgbaF)[4], (*destF)[4];
824
825    rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
826    destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat));
827    if (!rgbaF || !destF) {
828       free(rgbaF);
829       free(destF);
830       _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending");
831       return;
832    }
833
834    if (chanType == GL_UNSIGNED_BYTE) {
835       GLubyte (*rgba)[4] = (GLubyte (*)[4]) src;
836       const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst;
837       GLuint i;
838       /* convert ubytes to floats */
839       for (i = 0; i < n; i++) {
840          if (mask[i]) {
841             rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]);
842             rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]);
843             rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]);
844             rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]);
845             destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]);
846             destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]);
847             destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]);
848             destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]);
849          }
850       }
851       /* do blend */
852       blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
853       /* convert back to ubytes */
854       for (i = 0; i < n; i++) {
855          if (mask[i])
856            _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]);
857       }
858    }
859    else if (chanType == GL_UNSIGNED_SHORT) {
860       GLushort (*rgba)[4] = (GLushort (*)[4]) src;
861       const GLushort (*dest)[4] = (const GLushort (*)[4]) dst;
862       GLuint i;
863       /* convert ushorts to floats */
864       for (i = 0; i < n; i++) {
865          if (mask[i]) {
866             rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]);
867             rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]);
868             rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]);
869             rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]);
870             destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]);
871             destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]);
872             destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]);
873             destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]);
874          }
875       }
876       /* do blend */
877       blend_general_float(ctx, n, mask, rgbaF, destF, chanType);
878       /* convert back to ushorts */
879       for (i = 0; i < n; i++) {
880          if (mask[i]) {
881             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]);
882             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]);
883             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]);
884             UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]);
885          }
886       }
887    }
888    else {
889       blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src,
890                           (GLfloat (*)[4]) dst, chanType);
891    }
892
893    free(rgbaF);
894    free(destF);
895 }
896
897
898
899 /**
900  * Analyze current blending parameters to pick fastest blending function.
901  * Result: the ctx->Color.BlendFunc pointer is updated.
902  */
903 void
904 _swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType)
905 {
906    SWcontext *swrast = SWRAST_CONTEXT(ctx);
907    const GLenum eq = ctx->Color.Blend[0].EquationRGB;
908    const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB;
909    const GLenum dstRGB = ctx->Color.Blend[0].DstRGB;
910    const GLenum srcA = ctx->Color.Blend[0].SrcA;
911    const GLenum dstA = ctx->Color.Blend[0].DstA;
912
913    if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) {
914       swrast->BlendFunc = blend_general;
915    }
916    else if (eq == GL_MIN) {
917       /* Note: GL_MIN ignores the blending weight factors */
918 #if defined(USE_MMX_ASM)
919       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
920          swrast->BlendFunc = _mesa_mmx_blend_min;
921       }
922       else
923 #endif
924          swrast->BlendFunc = blend_min;
925    }
926    else if (eq == GL_MAX) {
927       /* Note: GL_MAX ignores the blending weight factors */
928 #if defined(USE_MMX_ASM)
929       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
930          swrast->BlendFunc = _mesa_mmx_blend_max;
931       }
932       else
933 #endif
934          swrast->BlendFunc = blend_max;
935    }
936    else if (srcRGB != srcA || dstRGB != dstA) {
937       swrast->BlendFunc = blend_general;
938    }
939    else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA
940             && dstRGB == GL_ONE_MINUS_SRC_ALPHA) {
941 #if defined(USE_MMX_ASM)
942       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
943          swrast->BlendFunc = _mesa_mmx_blend_transparency;
944       }
945       else
946 #endif
947       {
948          if (chanType == GL_UNSIGNED_BYTE)
949             swrast->BlendFunc = blend_transparency_ubyte;
950          else if (chanType == GL_UNSIGNED_SHORT)
951             swrast->BlendFunc = blend_transparency_ushort;
952          else
953             swrast->BlendFunc = blend_transparency_float;
954       }
955    }
956    else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) {
957 #if defined(USE_MMX_ASM)
958       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
959          swrast->BlendFunc = _mesa_mmx_blend_add;
960       }
961       else
962 #endif
963          swrast->BlendFunc = blend_add;
964    }
965    else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT)
966              && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR))
967             ||
968             ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT)
969              && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) {
970 #if defined(USE_MMX_ASM)
971       if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) {
972          swrast->BlendFunc = _mesa_mmx_blend_modulate;
973       }
974       else
975 #endif
976          swrast->BlendFunc = blend_modulate;
977    }
978    else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) {
979       swrast->BlendFunc = blend_noop;
980    }
981    else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) {
982       swrast->BlendFunc = blend_replace;
983    }
984    else {
985       swrast->BlendFunc = blend_general;
986    }
987 }
988
989
990
991 /**
992  * Apply the blending operator to a span of pixels.
993  * We can handle horizontal runs of pixels (spans) or arrays of x/y
994  * pixel coordinates.
995  */
996 void
997 _swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span)
998 {
999    SWcontext *swrast = SWRAST_CONTEXT(ctx);
1000    void *rbPixels;
1001
1002    ASSERT(span->end <= SWRAST_MAX_WIDTH);
1003    ASSERT(span->arrayMask & SPAN_RGBA);
1004    ASSERT(!ctx->Color.ColorLogicOpEnabled);
1005
1006    rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
1007
1008    swrast->BlendFunc(ctx, span->end, span->array->mask,
1009                      span->array->rgba, rbPixels, span->array->ChanType);
1010 }