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