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