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  */
69 static void
blend_noop(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)70 blend_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  */
97 static void
blend_replace(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)98 blend_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  */
117 static void
blend_transparency_ubyte(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)118 blend_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 
162 static void
blend_transparency_ushort(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)163 blend_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 
200 static void
blend_transparency_float(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)201 blend_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  */
242 static void
blend_add(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)243 blend_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  */
308 static void
blend_min(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)309 blend_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  */
361 static void
blend_max(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)362 blend_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  */
415 static void
blend_modulate(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLvoid * src,const GLvoid * dst,GLenum chanType)416 blend_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  */
470 static void
blend_general_float(struct gl_context * ctx,GLuint n,const GLubyte mask[],GLfloat rgba[][4],GLfloat dest[][4],GLenum chanType)471 blend_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  */
815 static void
blend_general(struct gl_context * ctx,GLuint n,const GLubyte mask[],void * src,const void * dst,GLenum chanType)816 blend_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  */
899 void
_swrast_choose_blend_func(struct gl_context * ctx,GLenum chanType)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  */
992 void
_swrast_blend_span(struct gl_context * ctx,struct gl_renderbuffer * rb,SWspan * span)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