1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg/** 27848b8605Smrg * \file swrast/s_blend.c 28848b8605Smrg * \brief software blending. 29848b8605Smrg * \author Brian Paul 30848b8605Smrg * 31848b8605Smrg * Only a few blend modes have been optimized (min, max, transparency, add) 32848b8605Smrg * more optimized cases can easily be added if needed. 33848b8605Smrg * Celestia uses glBlendFunc(GL_SRC_ALPHA, GL_ONE), for example. 34848b8605Smrg */ 35848b8605Smrg 36848b8605Smrg 37848b8605Smrg 38848b8605Smrg#include "main/glheader.h" 39848b8605Smrg#include "main/context.h" 40848b8605Smrg#include "main/colormac.h" 41848b8605Smrg#include "main/macros.h" 42848b8605Smrg 43848b8605Smrg#include "s_blend.h" 44848b8605Smrg#include "s_context.h" 45848b8605Smrg#include "s_span.h" 46848b8605Smrg 47848b8605Smrg 48848b8605Smrg#if defined(USE_MMX_ASM) 49848b8605Smrg#include "x86/mmx.h" 50848b8605Smrg#include "x86/common_x86_asm.h" 51848b8605Smrg#endif 52848b8605Smrg 53848b8605Smrg 54848b8605Smrg/** 55848b8605Smrg * Integer divide by 255 56848b8605Smrg * Declare "int divtemp" before using. 57848b8605Smrg * This satisfies Glean and should be reasonably fast. 58848b8605Smrg * Contributed by Nathan Hand. 59848b8605Smrg */ 60848b8605Smrg#define DIV255(X) (divtemp = (X), ((divtemp << 8) + divtemp + 256) >> 16) 61848b8605Smrg 62848b8605Smrg 63848b8605Smrg 64848b8605Smrg/** 65848b8605Smrg * Special case for glBlendFunc(GL_ZERO, GL_ONE). 66848b8605Smrg * No-op means the framebuffer values remain unchanged. 67848b8605Smrg * Any chanType ok. 68848b8605Smrg */ 69b8e80941Smrgstatic void 70848b8605Smrgblend_noop(struct gl_context *ctx, GLuint n, const GLubyte mask[], 71848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 72848b8605Smrg{ 73848b8605Smrg GLint bytes; 74848b8605Smrg 75b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 76b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 77b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_ZERO); 78b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ONE); 79848b8605Smrg (void) ctx; 80848b8605Smrg 81848b8605Smrg /* just memcpy */ 82848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) 83848b8605Smrg bytes = 4 * n * sizeof(GLubyte); 84848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) 85848b8605Smrg bytes = 4 * n * sizeof(GLushort); 86848b8605Smrg else 87848b8605Smrg bytes = 4 * n * sizeof(GLfloat); 88848b8605Smrg 89848b8605Smrg memcpy(src, dst, bytes); 90848b8605Smrg} 91848b8605Smrg 92848b8605Smrg 93848b8605Smrg/** 94848b8605Smrg * Special case for glBlendFunc(GL_ONE, GL_ZERO) 95848b8605Smrg * Any chanType ok. 96848b8605Smrg */ 97b8e80941Smrgstatic void 98848b8605Smrgblend_replace(struct gl_context *ctx, GLuint n, const GLubyte mask[], 99848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 100848b8605Smrg{ 101b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 102b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 103b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_ONE); 104b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ZERO); 105848b8605Smrg (void) ctx; 106848b8605Smrg (void) n; 107848b8605Smrg (void) mask; 108848b8605Smrg (void) src; 109848b8605Smrg (void) dst; 110848b8605Smrg} 111848b8605Smrg 112848b8605Smrg 113848b8605Smrg/** 114848b8605Smrg * Common transparency blending mode: 115848b8605Smrg * glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). 116848b8605Smrg */ 117b8e80941Smrgstatic void 118848b8605Smrgblend_transparency_ubyte(struct gl_context *ctx, GLuint n, const GLubyte mask[], 119848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 120848b8605Smrg{ 121848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 122848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 123848b8605Smrg GLuint i; 124848b8605Smrg 125b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 126b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 127b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 128b8e80941Smrg assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 129b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 130b8e80941Smrg assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 131b8e80941Smrg assert(chanType == GL_UNSIGNED_BYTE); 132848b8605Smrg 133848b8605Smrg (void) ctx; 134848b8605Smrg 135848b8605Smrg for (i = 0; i < n; i++) { 136848b8605Smrg if (mask[i]) { 137848b8605Smrg const GLint t = rgba[i][ACOMP]; /* t is in [0, 255] */ 138848b8605Smrg if (t == 0) { 139848b8605Smrg /* 0% alpha */ 140848b8605Smrg COPY_4UBV(rgba[i], dest[i]); 141848b8605Smrg } 142848b8605Smrg else if (t != 255) { 143848b8605Smrg GLint divtemp; 144848b8605Smrg const GLint r = DIV255((rgba[i][RCOMP] - dest[i][RCOMP]) * t) + dest[i][RCOMP]; 145848b8605Smrg const GLint g = DIV255((rgba[i][GCOMP] - dest[i][GCOMP]) * t) + dest[i][GCOMP]; 146848b8605Smrg const GLint b = DIV255((rgba[i][BCOMP] - dest[i][BCOMP]) * t) + dest[i][BCOMP]; 147848b8605Smrg const GLint a = DIV255((rgba[i][ACOMP] - dest[i][ACOMP]) * t) + dest[i][ACOMP]; 148b8e80941Smrg assert(r <= 255); 149b8e80941Smrg assert(g <= 255); 150b8e80941Smrg assert(b <= 255); 151b8e80941Smrg assert(a <= 255); 152848b8605Smrg rgba[i][RCOMP] = (GLubyte) r; 153848b8605Smrg rgba[i][GCOMP] = (GLubyte) g; 154848b8605Smrg rgba[i][BCOMP] = (GLubyte) b; 155848b8605Smrg rgba[i][ACOMP] = (GLubyte) a; 156848b8605Smrg } 157848b8605Smrg } 158848b8605Smrg } 159848b8605Smrg} 160848b8605Smrg 161848b8605Smrg 162b8e80941Smrgstatic void 163848b8605Smrgblend_transparency_ushort(struct gl_context *ctx, GLuint n, const GLubyte mask[], 164848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 165848b8605Smrg{ 166848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 167848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 168848b8605Smrg GLuint i; 169848b8605Smrg 170b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 171b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 172b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 173b8e80941Smrg assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 174b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 175b8e80941Smrg assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 176b8e80941Smrg assert(chanType == GL_UNSIGNED_SHORT); 177848b8605Smrg 178848b8605Smrg (void) ctx; 179848b8605Smrg 180848b8605Smrg for (i = 0; i < n; i++) { 181848b8605Smrg if (mask[i]) { 182848b8605Smrg const GLint t = rgba[i][ACOMP]; 183848b8605Smrg if (t == 0) { 184848b8605Smrg /* 0% alpha */ 185848b8605Smrg COPY_4V(rgba[i], dest[i]); 186848b8605Smrg } 187848b8605Smrg else if (t != 65535) { 188848b8605Smrg const GLfloat tt = (GLfloat) t / 65535.0F; 189848b8605Smrg GLushort r = (GLushort) ((rgba[i][RCOMP] - dest[i][RCOMP]) * tt + dest[i][RCOMP]); 190848b8605Smrg GLushort g = (GLushort) ((rgba[i][GCOMP] - dest[i][GCOMP]) * tt + dest[i][GCOMP]); 191848b8605Smrg GLushort b = (GLushort) ((rgba[i][BCOMP] - dest[i][BCOMP]) * tt + dest[i][BCOMP]); 192848b8605Smrg GLushort a = (GLushort) ((rgba[i][ACOMP] - dest[i][ACOMP]) * tt + dest[i][ACOMP]); 193848b8605Smrg ASSIGN_4V(rgba[i], r, g, b, a); 194848b8605Smrg } 195848b8605Smrg } 196848b8605Smrg } 197848b8605Smrg} 198848b8605Smrg 199848b8605Smrg 200b8e80941Smrgstatic void 201848b8605Smrgblend_transparency_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], 202848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 203848b8605Smrg{ 204848b8605Smrg GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 205848b8605Smrg const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 206848b8605Smrg GLuint i; 207848b8605Smrg 208b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 209b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 210b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_SRC_ALPHA); 211b8e80941Smrg assert(ctx->Color.Blend[0].SrcA == GL_SRC_ALPHA); 212b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ONE_MINUS_SRC_ALPHA); 213b8e80941Smrg assert(ctx->Color.Blend[0].DstA == GL_ONE_MINUS_SRC_ALPHA); 214b8e80941Smrg assert(chanType == GL_FLOAT); 215848b8605Smrg 216848b8605Smrg (void) ctx; 217848b8605Smrg 218848b8605Smrg for (i = 0; i < n; i++) { 219848b8605Smrg if (mask[i]) { 220848b8605Smrg const GLfloat t = rgba[i][ACOMP]; /* t in [0, 1] */ 221848b8605Smrg if (t == 0.0F) { 222848b8605Smrg /* 0% alpha */ 223848b8605Smrg COPY_4V(rgba[i], dest[i]); 224848b8605Smrg } 225848b8605Smrg else if (t != 1.0F) { 226848b8605Smrg GLfloat r = (rgba[i][RCOMP] - dest[i][RCOMP]) * t + dest[i][RCOMP]; 227848b8605Smrg GLfloat g = (rgba[i][GCOMP] - dest[i][GCOMP]) * t + dest[i][GCOMP]; 228848b8605Smrg GLfloat b = (rgba[i][BCOMP] - dest[i][BCOMP]) * t + dest[i][BCOMP]; 229848b8605Smrg GLfloat a = (rgba[i][ACOMP] - dest[i][ACOMP]) * t + dest[i][ACOMP]; 230848b8605Smrg ASSIGN_4V(rgba[i], r, g, b, a); 231848b8605Smrg } 232848b8605Smrg } 233848b8605Smrg } 234848b8605Smrg} 235848b8605Smrg 236848b8605Smrg 237848b8605Smrg 238848b8605Smrg/** 239848b8605Smrg * Add src and dest: glBlendFunc(GL_ONE, GL_ONE). 240848b8605Smrg * Any chanType ok. 241848b8605Smrg */ 242b8e80941Smrgstatic void 243848b8605Smrgblend_add(struct gl_context *ctx, GLuint n, const GLubyte mask[], 244848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 245848b8605Smrg{ 246848b8605Smrg GLuint i; 247848b8605Smrg 248b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_FUNC_ADD); 249b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_FUNC_ADD); 250b8e80941Smrg assert(ctx->Color.Blend[0].SrcRGB == GL_ONE); 251b8e80941Smrg assert(ctx->Color.Blend[0].DstRGB == GL_ONE); 252848b8605Smrg (void) ctx; 253848b8605Smrg 254848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) { 255848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 256848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 257848b8605Smrg for (i=0;i<n;i++) { 258848b8605Smrg if (mask[i]) { 259848b8605Smrg GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; 260848b8605Smrg GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; 261848b8605Smrg GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; 262848b8605Smrg GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; 263848b8605Smrg rgba[i][RCOMP] = (GLubyte) MIN2( r, 255 ); 264848b8605Smrg rgba[i][GCOMP] = (GLubyte) MIN2( g, 255 ); 265848b8605Smrg rgba[i][BCOMP] = (GLubyte) MIN2( b, 255 ); 266848b8605Smrg rgba[i][ACOMP] = (GLubyte) MIN2( a, 255 ); 267848b8605Smrg } 268848b8605Smrg } 269848b8605Smrg } 270848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) { 271848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 272848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 273848b8605Smrg for (i=0;i<n;i++) { 274848b8605Smrg if (mask[i]) { 275848b8605Smrg GLint r = rgba[i][RCOMP] + dest[i][RCOMP]; 276848b8605Smrg GLint g = rgba[i][GCOMP] + dest[i][GCOMP]; 277848b8605Smrg GLint b = rgba[i][BCOMP] + dest[i][BCOMP]; 278848b8605Smrg GLint a = rgba[i][ACOMP] + dest[i][ACOMP]; 279848b8605Smrg rgba[i][RCOMP] = (GLshort) MIN2( r, 255 ); 280848b8605Smrg rgba[i][GCOMP] = (GLshort) MIN2( g, 255 ); 281848b8605Smrg rgba[i][BCOMP] = (GLshort) MIN2( b, 255 ); 282848b8605Smrg rgba[i][ACOMP] = (GLshort) MIN2( a, 255 ); 283848b8605Smrg } 284848b8605Smrg } 285848b8605Smrg } 286848b8605Smrg else { 287848b8605Smrg GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 288848b8605Smrg const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 289b8e80941Smrg assert(chanType == GL_FLOAT); 290848b8605Smrg for (i=0;i<n;i++) { 291848b8605Smrg if (mask[i]) { 292848b8605Smrg /* don't RGB clamp to max */ 293848b8605Smrg rgba[i][RCOMP] += dest[i][RCOMP]; 294848b8605Smrg rgba[i][GCOMP] += dest[i][GCOMP]; 295848b8605Smrg rgba[i][BCOMP] += dest[i][BCOMP]; 296848b8605Smrg rgba[i][ACOMP] += dest[i][ACOMP]; 297848b8605Smrg } 298848b8605Smrg } 299848b8605Smrg } 300848b8605Smrg} 301848b8605Smrg 302848b8605Smrg 303848b8605Smrg 304848b8605Smrg/** 305848b8605Smrg * Blend min function. 306848b8605Smrg * Any chanType ok. 307848b8605Smrg */ 308b8e80941Smrgstatic void 309848b8605Smrgblend_min(struct gl_context *ctx, GLuint n, const GLubyte mask[], 310848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 311848b8605Smrg{ 312848b8605Smrg GLuint i; 313b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_MIN); 314b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_MIN); 315848b8605Smrg (void) ctx; 316848b8605Smrg 317848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) { 318848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 319848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 320848b8605Smrg for (i=0;i<n;i++) { 321848b8605Smrg if (mask[i]) { 322848b8605Smrg rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 323848b8605Smrg rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 324848b8605Smrg rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 325848b8605Smrg rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 326848b8605Smrg } 327848b8605Smrg } 328848b8605Smrg } 329848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) { 330848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 331848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 332848b8605Smrg for (i=0;i<n;i++) { 333848b8605Smrg if (mask[i]) { 334848b8605Smrg rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 335848b8605Smrg rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 336848b8605Smrg rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 337848b8605Smrg rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 338848b8605Smrg } 339848b8605Smrg } 340848b8605Smrg } 341848b8605Smrg else { 342848b8605Smrg GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 343848b8605Smrg const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 344b8e80941Smrg assert(chanType == GL_FLOAT); 345848b8605Smrg for (i=0;i<n;i++) { 346848b8605Smrg if (mask[i]) { 347848b8605Smrg rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] ); 348848b8605Smrg rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] ); 349848b8605Smrg rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] ); 350848b8605Smrg rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] ); 351848b8605Smrg } 352848b8605Smrg } 353848b8605Smrg } 354848b8605Smrg} 355848b8605Smrg 356848b8605Smrg 357848b8605Smrg/** 358848b8605Smrg * Blend max function. 359848b8605Smrg * Any chanType ok. 360848b8605Smrg */ 361b8e80941Smrgstatic void 362848b8605Smrgblend_max(struct gl_context *ctx, GLuint n, const GLubyte mask[], 363848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 364848b8605Smrg{ 365848b8605Smrg GLuint i; 366b8e80941Smrg assert(ctx->Color.Blend[0].EquationRGB == GL_MAX); 367b8e80941Smrg assert(ctx->Color.Blend[0].EquationA == GL_MAX); 368848b8605Smrg (void) ctx; 369848b8605Smrg 370848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) { 371848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 372848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 373848b8605Smrg for (i=0;i<n;i++) { 374848b8605Smrg if (mask[i]) { 375848b8605Smrg rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 376848b8605Smrg rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 377848b8605Smrg rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 378848b8605Smrg rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 379848b8605Smrg } 380848b8605Smrg } 381848b8605Smrg } 382848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) { 383848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 384848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 385848b8605Smrg for (i=0;i<n;i++) { 386848b8605Smrg if (mask[i]) { 387848b8605Smrg rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 388848b8605Smrg rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 389848b8605Smrg rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 390848b8605Smrg rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 391848b8605Smrg } 392848b8605Smrg } 393848b8605Smrg } 394848b8605Smrg else { 395848b8605Smrg GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 396848b8605Smrg const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 397b8e80941Smrg assert(chanType == GL_FLOAT); 398848b8605Smrg for (i=0;i<n;i++) { 399848b8605Smrg if (mask[i]) { 400848b8605Smrg rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] ); 401848b8605Smrg rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] ); 402848b8605Smrg rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] ); 403848b8605Smrg rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] ); 404848b8605Smrg } 405848b8605Smrg } 406848b8605Smrg } 407848b8605Smrg} 408848b8605Smrg 409848b8605Smrg 410848b8605Smrg 411848b8605Smrg/** 412848b8605Smrg * Modulate: result = src * dest 413848b8605Smrg * Any chanType ok. 414848b8605Smrg */ 415b8e80941Smrgstatic void 416848b8605Smrgblend_modulate(struct gl_context *ctx, GLuint n, const GLubyte mask[], 417848b8605Smrg GLvoid *src, const GLvoid *dst, GLenum chanType) 418848b8605Smrg{ 419848b8605Smrg GLuint i; 420848b8605Smrg (void) ctx; 421848b8605Smrg 422848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) { 423848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 424848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 425848b8605Smrg for (i=0;i<n;i++) { 426848b8605Smrg if (mask[i]) { 427848b8605Smrg GLint divtemp; 428848b8605Smrg rgba[i][RCOMP] = DIV255(rgba[i][RCOMP] * dest[i][RCOMP]); 429848b8605Smrg rgba[i][GCOMP] = DIV255(rgba[i][GCOMP] * dest[i][GCOMP]); 430848b8605Smrg rgba[i][BCOMP] = DIV255(rgba[i][BCOMP] * dest[i][BCOMP]); 431848b8605Smrg rgba[i][ACOMP] = DIV255(rgba[i][ACOMP] * dest[i][ACOMP]); 432848b8605Smrg } 433848b8605Smrg } 434848b8605Smrg } 435848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) { 436848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 437848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 438848b8605Smrg for (i=0;i<n;i++) { 439848b8605Smrg if (mask[i]) { 440848b8605Smrg rgba[i][RCOMP] = (rgba[i][RCOMP] * dest[i][RCOMP] + 65535) >> 16; 441848b8605Smrg rgba[i][GCOMP] = (rgba[i][GCOMP] * dest[i][GCOMP] + 65535) >> 16; 442848b8605Smrg rgba[i][BCOMP] = (rgba[i][BCOMP] * dest[i][BCOMP] + 65535) >> 16; 443848b8605Smrg rgba[i][ACOMP] = (rgba[i][ACOMP] * dest[i][ACOMP] + 65535) >> 16; 444848b8605Smrg } 445848b8605Smrg } 446848b8605Smrg } 447848b8605Smrg else { 448848b8605Smrg GLfloat (*rgba)[4] = (GLfloat (*)[4]) src; 449848b8605Smrg const GLfloat (*dest)[4] = (const GLfloat (*)[4]) dst; 450b8e80941Smrg assert(chanType == GL_FLOAT); 451848b8605Smrg for (i=0;i<n;i++) { 452848b8605Smrg if (mask[i]) { 453848b8605Smrg rgba[i][RCOMP] = rgba[i][RCOMP] * dest[i][RCOMP]; 454848b8605Smrg rgba[i][GCOMP] = rgba[i][GCOMP] * dest[i][GCOMP]; 455848b8605Smrg rgba[i][BCOMP] = rgba[i][BCOMP] * dest[i][BCOMP]; 456848b8605Smrg rgba[i][ACOMP] = rgba[i][ACOMP] * dest[i][ACOMP]; 457848b8605Smrg } 458848b8605Smrg } 459848b8605Smrg } 460848b8605Smrg} 461848b8605Smrg 462848b8605Smrg 463848b8605Smrg/** 464848b8605Smrg * Do any blending operation, using floating point. 465848b8605Smrg * \param n number of pixels 466848b8605Smrg * \param mask fragment writemask array 467848b8605Smrg * \param rgba array of incoming (and modified) pixels 468848b8605Smrg * \param dest array of pixels from the dest color buffer 469848b8605Smrg */ 470848b8605Smrgstatic void 471848b8605Smrgblend_general_float(struct gl_context *ctx, GLuint n, const GLubyte mask[], 472848b8605Smrg GLfloat rgba[][4], GLfloat dest[][4], 473848b8605Smrg GLenum chanType) 474848b8605Smrg{ 475848b8605Smrg GLuint i; 476848b8605Smrg 477848b8605Smrg for (i = 0; i < n; i++) { 478848b8605Smrg if (mask[i]) { 479848b8605Smrg /* Incoming/source Color */ 480848b8605Smrg const GLfloat Rs = rgba[i][RCOMP]; 481848b8605Smrg const GLfloat Gs = rgba[i][GCOMP]; 482848b8605Smrg const GLfloat Bs = rgba[i][BCOMP]; 483848b8605Smrg const GLfloat As = rgba[i][ACOMP]; 484848b8605Smrg 485848b8605Smrg /* Frame buffer/dest color */ 486848b8605Smrg const GLfloat Rd = dest[i][RCOMP]; 487848b8605Smrg const GLfloat Gd = dest[i][GCOMP]; 488848b8605Smrg const GLfloat Bd = dest[i][BCOMP]; 489848b8605Smrg const GLfloat Ad = dest[i][ACOMP]; 490848b8605Smrg 491848b8605Smrg GLfloat sR, sG, sB, sA; /* Source factor */ 492848b8605Smrg GLfloat dR, dG, dB, dA; /* Dest factor */ 493848b8605Smrg GLfloat r, g, b, a; /* result color */ 494848b8605Smrg 495848b8605Smrg /* XXX for the case of constant blend terms we could init 496848b8605Smrg * the sX and dX variables just once before the loop. 497848b8605Smrg */ 498848b8605Smrg 499848b8605Smrg /* Source RGB factor */ 500848b8605Smrg switch (ctx->Color.Blend[0].SrcRGB) { 501848b8605Smrg case GL_ZERO: 502848b8605Smrg sR = sG = sB = 0.0F; 503848b8605Smrg break; 504848b8605Smrg case GL_ONE: 505848b8605Smrg sR = sG = sB = 1.0F; 506848b8605Smrg break; 507848b8605Smrg case GL_DST_COLOR: 508848b8605Smrg sR = Rd; 509848b8605Smrg sG = Gd; 510848b8605Smrg sB = Bd; 511848b8605Smrg break; 512848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 513848b8605Smrg sR = 1.0F - Rd; 514848b8605Smrg sG = 1.0F - Gd; 515848b8605Smrg sB = 1.0F - Bd; 516848b8605Smrg break; 517848b8605Smrg case GL_SRC_ALPHA: 518848b8605Smrg sR = sG = sB = As; 519848b8605Smrg break; 520848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 521848b8605Smrg sR = sG = sB = 1.0F - As; 522848b8605Smrg break; 523848b8605Smrg case GL_DST_ALPHA: 524848b8605Smrg sR = sG = sB = Ad; 525848b8605Smrg break; 526848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 527848b8605Smrg sR = sG = sB = 1.0F - Ad; 528848b8605Smrg break; 529848b8605Smrg case GL_SRC_ALPHA_SATURATE: 530848b8605Smrg if (As < 1.0F - Ad) { 531848b8605Smrg sR = sG = sB = As; 532848b8605Smrg } 533848b8605Smrg else { 534848b8605Smrg sR = sG = sB = 1.0F - Ad; 535848b8605Smrg } 536848b8605Smrg break; 537848b8605Smrg case GL_CONSTANT_COLOR: 538848b8605Smrg sR = ctx->Color.BlendColor[0]; 539848b8605Smrg sG = ctx->Color.BlendColor[1]; 540848b8605Smrg sB = ctx->Color.BlendColor[2]; 541848b8605Smrg break; 542848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 543848b8605Smrg sR = 1.0F - ctx->Color.BlendColor[0]; 544848b8605Smrg sG = 1.0F - ctx->Color.BlendColor[1]; 545848b8605Smrg sB = 1.0F - ctx->Color.BlendColor[2]; 546848b8605Smrg break; 547848b8605Smrg case GL_CONSTANT_ALPHA: 548848b8605Smrg sR = sG = sB = ctx->Color.BlendColor[3]; 549848b8605Smrg break; 550848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 551848b8605Smrg sR = sG = sB = 1.0F - ctx->Color.BlendColor[3]; 552848b8605Smrg break; 553848b8605Smrg case GL_SRC_COLOR: 554848b8605Smrg sR = Rs; 555848b8605Smrg sG = Gs; 556848b8605Smrg sB = Bs; 557848b8605Smrg break; 558848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 559848b8605Smrg sR = 1.0F - Rs; 560848b8605Smrg sG = 1.0F - Gs; 561848b8605Smrg sB = 1.0F - Bs; 562848b8605Smrg break; 563848b8605Smrg default: 564848b8605Smrg /* this should never happen */ 565848b8605Smrg _mesa_problem(ctx, "Bad blend source RGB factor in blend_general_float"); 566848b8605Smrg return; 567848b8605Smrg } 568848b8605Smrg 569848b8605Smrg /* Source Alpha factor */ 570848b8605Smrg switch (ctx->Color.Blend[0].SrcA) { 571848b8605Smrg case GL_ZERO: 572848b8605Smrg sA = 0.0F; 573848b8605Smrg break; 574848b8605Smrg case GL_ONE: 575848b8605Smrg sA = 1.0F; 576848b8605Smrg break; 577848b8605Smrg case GL_DST_COLOR: 578848b8605Smrg sA = Ad; 579848b8605Smrg break; 580848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 581848b8605Smrg sA = 1.0F - Ad; 582848b8605Smrg break; 583848b8605Smrg case GL_SRC_ALPHA: 584848b8605Smrg sA = As; 585848b8605Smrg break; 586848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 587848b8605Smrg sA = 1.0F - As; 588848b8605Smrg break; 589848b8605Smrg case GL_DST_ALPHA: 590848b8605Smrg sA = Ad; 591848b8605Smrg break; 592848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 593848b8605Smrg sA = 1.0F - Ad; 594848b8605Smrg break; 595848b8605Smrg case GL_SRC_ALPHA_SATURATE: 596848b8605Smrg sA = 1.0; 597848b8605Smrg break; 598848b8605Smrg case GL_CONSTANT_COLOR: 599848b8605Smrg sA = ctx->Color.BlendColor[3]; 600848b8605Smrg break; 601848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 602848b8605Smrg sA = 1.0F - ctx->Color.BlendColor[3]; 603848b8605Smrg break; 604848b8605Smrg case GL_CONSTANT_ALPHA: 605848b8605Smrg sA = ctx->Color.BlendColor[3]; 606848b8605Smrg break; 607848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 608848b8605Smrg sA = 1.0F - ctx->Color.BlendColor[3]; 609848b8605Smrg break; 610848b8605Smrg case GL_SRC_COLOR: 611848b8605Smrg sA = As; 612848b8605Smrg break; 613848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 614848b8605Smrg sA = 1.0F - As; 615848b8605Smrg break; 616848b8605Smrg default: 617848b8605Smrg /* this should never happen */ 618848b8605Smrg sA = 0.0F; 619848b8605Smrg _mesa_problem(ctx, "Bad blend source A factor in blend_general_float"); 620848b8605Smrg return; 621848b8605Smrg } 622848b8605Smrg 623848b8605Smrg /* Dest RGB factor */ 624848b8605Smrg switch (ctx->Color.Blend[0].DstRGB) { 625848b8605Smrg case GL_ZERO: 626848b8605Smrg dR = dG = dB = 0.0F; 627848b8605Smrg break; 628848b8605Smrg case GL_ONE: 629848b8605Smrg dR = dG = dB = 1.0F; 630848b8605Smrg break; 631848b8605Smrg case GL_SRC_COLOR: 632848b8605Smrg dR = Rs; 633848b8605Smrg dG = Gs; 634848b8605Smrg dB = Bs; 635848b8605Smrg break; 636848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 637848b8605Smrg dR = 1.0F - Rs; 638848b8605Smrg dG = 1.0F - Gs; 639848b8605Smrg dB = 1.0F - Bs; 640848b8605Smrg break; 641848b8605Smrg case GL_SRC_ALPHA: 642848b8605Smrg dR = dG = dB = As; 643848b8605Smrg break; 644848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 645848b8605Smrg dR = dG = dB = 1.0F - As; 646848b8605Smrg break; 647848b8605Smrg case GL_DST_ALPHA: 648848b8605Smrg dR = dG = dB = Ad; 649848b8605Smrg break; 650848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 651848b8605Smrg dR = dG = dB = 1.0F - Ad; 652848b8605Smrg break; 653848b8605Smrg case GL_CONSTANT_COLOR: 654848b8605Smrg dR = ctx->Color.BlendColor[0]; 655848b8605Smrg dG = ctx->Color.BlendColor[1]; 656848b8605Smrg dB = ctx->Color.BlendColor[2]; 657848b8605Smrg break; 658848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 659848b8605Smrg dR = 1.0F - ctx->Color.BlendColor[0]; 660848b8605Smrg dG = 1.0F - ctx->Color.BlendColor[1]; 661848b8605Smrg dB = 1.0F - ctx->Color.BlendColor[2]; 662848b8605Smrg break; 663848b8605Smrg case GL_CONSTANT_ALPHA: 664848b8605Smrg dR = dG = dB = ctx->Color.BlendColor[3]; 665848b8605Smrg break; 666848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 667848b8605Smrg dR = dG = dB = 1.0F - ctx->Color.BlendColor[3]; 668848b8605Smrg break; 669848b8605Smrg case GL_DST_COLOR: 670848b8605Smrg dR = Rd; 671848b8605Smrg dG = Gd; 672848b8605Smrg dB = Bd; 673848b8605Smrg break; 674848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 675848b8605Smrg dR = 1.0F - Rd; 676848b8605Smrg dG = 1.0F - Gd; 677848b8605Smrg dB = 1.0F - Bd; 678848b8605Smrg break; 679848b8605Smrg default: 680848b8605Smrg /* this should never happen */ 681848b8605Smrg dR = dG = dB = 0.0F; 682848b8605Smrg _mesa_problem(ctx, "Bad blend dest RGB factor in blend_general_float"); 683848b8605Smrg return; 684848b8605Smrg } 685848b8605Smrg 686848b8605Smrg /* Dest Alpha factor */ 687848b8605Smrg switch (ctx->Color.Blend[0].DstA) { 688848b8605Smrg case GL_ZERO: 689848b8605Smrg dA = 0.0F; 690848b8605Smrg break; 691848b8605Smrg case GL_ONE: 692848b8605Smrg dA = 1.0F; 693848b8605Smrg break; 694848b8605Smrg case GL_SRC_COLOR: 695848b8605Smrg dA = As; 696848b8605Smrg break; 697848b8605Smrg case GL_ONE_MINUS_SRC_COLOR: 698848b8605Smrg dA = 1.0F - As; 699848b8605Smrg break; 700848b8605Smrg case GL_SRC_ALPHA: 701848b8605Smrg dA = As; 702848b8605Smrg break; 703848b8605Smrg case GL_ONE_MINUS_SRC_ALPHA: 704848b8605Smrg dA = 1.0F - As; 705848b8605Smrg break; 706848b8605Smrg case GL_DST_ALPHA: 707848b8605Smrg dA = Ad; 708848b8605Smrg break; 709848b8605Smrg case GL_ONE_MINUS_DST_ALPHA: 710848b8605Smrg dA = 1.0F - Ad; 711848b8605Smrg break; 712848b8605Smrg case GL_CONSTANT_COLOR: 713848b8605Smrg dA = ctx->Color.BlendColor[3]; 714848b8605Smrg break; 715848b8605Smrg case GL_ONE_MINUS_CONSTANT_COLOR: 716848b8605Smrg dA = 1.0F - ctx->Color.BlendColor[3]; 717848b8605Smrg break; 718848b8605Smrg case GL_CONSTANT_ALPHA: 719848b8605Smrg dA = ctx->Color.BlendColor[3]; 720848b8605Smrg break; 721848b8605Smrg case GL_ONE_MINUS_CONSTANT_ALPHA: 722848b8605Smrg dA = 1.0F - ctx->Color.BlendColor[3]; 723848b8605Smrg break; 724848b8605Smrg case GL_DST_COLOR: 725848b8605Smrg dA = Ad; 726848b8605Smrg break; 727848b8605Smrg case GL_ONE_MINUS_DST_COLOR: 728848b8605Smrg dA = 1.0F - Ad; 729848b8605Smrg break; 730848b8605Smrg default: 731848b8605Smrg /* this should never happen */ 732848b8605Smrg dA = 0.0F; 733848b8605Smrg _mesa_problem(ctx, "Bad blend dest A factor in blend_general_float"); 734848b8605Smrg return; 735848b8605Smrg } 736848b8605Smrg 737848b8605Smrg /* compute the blended RGB */ 738848b8605Smrg switch (ctx->Color.Blend[0].EquationRGB) { 739848b8605Smrg case GL_FUNC_ADD: 740848b8605Smrg r = Rs * sR + Rd * dR; 741848b8605Smrg g = Gs * sG + Gd * dG; 742848b8605Smrg b = Bs * sB + Bd * dB; 743848b8605Smrg a = As * sA + Ad * dA; 744848b8605Smrg break; 745848b8605Smrg case GL_FUNC_SUBTRACT: 746848b8605Smrg r = Rs * sR - Rd * dR; 747848b8605Smrg g = Gs * sG - Gd * dG; 748848b8605Smrg b = Bs * sB - Bd * dB; 749848b8605Smrg a = As * sA - Ad * dA; 750848b8605Smrg break; 751848b8605Smrg case GL_FUNC_REVERSE_SUBTRACT: 752848b8605Smrg r = Rd * dR - Rs * sR; 753848b8605Smrg g = Gd * dG - Gs * sG; 754848b8605Smrg b = Bd * dB - Bs * sB; 755848b8605Smrg a = Ad * dA - As * sA; 756848b8605Smrg break; 757848b8605Smrg case GL_MIN: 758848b8605Smrg r = MIN2( Rd, Rs ); 759848b8605Smrg g = MIN2( Gd, Gs ); 760848b8605Smrg b = MIN2( Bd, Bs ); 761848b8605Smrg break; 762848b8605Smrg case GL_MAX: 763848b8605Smrg r = MAX2( Rd, Rs ); 764848b8605Smrg g = MAX2( Gd, Gs ); 765848b8605Smrg b = MAX2( Bd, Bs ); 766848b8605Smrg break; 767848b8605Smrg default: 768848b8605Smrg /* should never get here */ 769848b8605Smrg r = g = b = 0.0F; /* silence uninitialized var warning */ 770848b8605Smrg _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); 771848b8605Smrg return; 772848b8605Smrg } 773848b8605Smrg 774848b8605Smrg /* compute the blended alpha */ 775848b8605Smrg switch (ctx->Color.Blend[0].EquationA) { 776848b8605Smrg case GL_FUNC_ADD: 777848b8605Smrg a = As * sA + Ad * dA; 778848b8605Smrg break; 779848b8605Smrg case GL_FUNC_SUBTRACT: 780848b8605Smrg a = As * sA - Ad * dA; 781848b8605Smrg break; 782848b8605Smrg case GL_FUNC_REVERSE_SUBTRACT: 783848b8605Smrg a = Ad * dA - As * sA; 784848b8605Smrg break; 785848b8605Smrg case GL_MIN: 786848b8605Smrg a = MIN2( Ad, As ); 787848b8605Smrg break; 788848b8605Smrg case GL_MAX: 789848b8605Smrg a = MAX2( Ad, As ); 790848b8605Smrg break; 791848b8605Smrg default: 792848b8605Smrg /* should never get here */ 793848b8605Smrg a = 0.0F; /* silence uninitialized var warning */ 794848b8605Smrg _mesa_problem(ctx, "unexpected BlendEquation in blend_general()"); 795848b8605Smrg return; 796848b8605Smrg } 797848b8605Smrg 798848b8605Smrg /* final clamping */ 799848b8605Smrg#if 0 800848b8605Smrg rgba[i][RCOMP] = MAX2( r, 0.0F ); 801848b8605Smrg rgba[i][GCOMP] = MAX2( g, 0.0F ); 802848b8605Smrg rgba[i][BCOMP] = MAX2( b, 0.0F ); 803848b8605Smrg rgba[i][ACOMP] = CLAMP( a, 0.0F, 1.0F ); 804848b8605Smrg#else 805848b8605Smrg ASSIGN_4V(rgba[i], r, g, b, a); 806848b8605Smrg#endif 807848b8605Smrg } 808848b8605Smrg } 809848b8605Smrg} 810848b8605Smrg 811848b8605Smrg 812848b8605Smrg/** 813848b8605Smrg * Do any blending operation, any chanType. 814848b8605Smrg */ 815848b8605Smrgstatic void 816848b8605Smrgblend_general(struct gl_context *ctx, GLuint n, const GLubyte mask[], 817848b8605Smrg void *src, const void *dst, GLenum chanType) 818848b8605Smrg{ 819848b8605Smrg GLfloat (*rgbaF)[4], (*destF)[4]; 820848b8605Smrg 821848b8605Smrg rgbaF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); 822848b8605Smrg destF = (GLfloat (*)[4]) malloc(4 * n * sizeof(GLfloat)); 823848b8605Smrg if (!rgbaF || !destF) { 824848b8605Smrg free(rgbaF); 825848b8605Smrg free(destF); 826848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "blending"); 827848b8605Smrg return; 828848b8605Smrg } 829848b8605Smrg 830848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) { 831848b8605Smrg GLubyte (*rgba)[4] = (GLubyte (*)[4]) src; 832848b8605Smrg const GLubyte (*dest)[4] = (const GLubyte (*)[4]) dst; 833848b8605Smrg GLuint i; 834848b8605Smrg /* convert ubytes to floats */ 835848b8605Smrg for (i = 0; i < n; i++) { 836848b8605Smrg if (mask[i]) { 837848b8605Smrg rgbaF[i][RCOMP] = UBYTE_TO_FLOAT(rgba[i][RCOMP]); 838848b8605Smrg rgbaF[i][GCOMP] = UBYTE_TO_FLOAT(rgba[i][GCOMP]); 839848b8605Smrg rgbaF[i][BCOMP] = UBYTE_TO_FLOAT(rgba[i][BCOMP]); 840848b8605Smrg rgbaF[i][ACOMP] = UBYTE_TO_FLOAT(rgba[i][ACOMP]); 841848b8605Smrg destF[i][RCOMP] = UBYTE_TO_FLOAT(dest[i][RCOMP]); 842848b8605Smrg destF[i][GCOMP] = UBYTE_TO_FLOAT(dest[i][GCOMP]); 843848b8605Smrg destF[i][BCOMP] = UBYTE_TO_FLOAT(dest[i][BCOMP]); 844848b8605Smrg destF[i][ACOMP] = UBYTE_TO_FLOAT(dest[i][ACOMP]); 845848b8605Smrg } 846848b8605Smrg } 847848b8605Smrg /* do blend */ 848848b8605Smrg blend_general_float(ctx, n, mask, rgbaF, destF, chanType); 849848b8605Smrg /* convert back to ubytes */ 850848b8605Smrg for (i = 0; i < n; i++) { 851848b8605Smrg if (mask[i]) 852848b8605Smrg _mesa_unclamped_float_rgba_to_ubyte(rgba[i], rgbaF[i]); 853848b8605Smrg } 854848b8605Smrg } 855848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) { 856848b8605Smrg GLushort (*rgba)[4] = (GLushort (*)[4]) src; 857848b8605Smrg const GLushort (*dest)[4] = (const GLushort (*)[4]) dst; 858848b8605Smrg GLuint i; 859848b8605Smrg /* convert ushorts to floats */ 860848b8605Smrg for (i = 0; i < n; i++) { 861848b8605Smrg if (mask[i]) { 862848b8605Smrg rgbaF[i][RCOMP] = USHORT_TO_FLOAT(rgba[i][RCOMP]); 863848b8605Smrg rgbaF[i][GCOMP] = USHORT_TO_FLOAT(rgba[i][GCOMP]); 864848b8605Smrg rgbaF[i][BCOMP] = USHORT_TO_FLOAT(rgba[i][BCOMP]); 865848b8605Smrg rgbaF[i][ACOMP] = USHORT_TO_FLOAT(rgba[i][ACOMP]); 866848b8605Smrg destF[i][RCOMP] = USHORT_TO_FLOAT(dest[i][RCOMP]); 867848b8605Smrg destF[i][GCOMP] = USHORT_TO_FLOAT(dest[i][GCOMP]); 868848b8605Smrg destF[i][BCOMP] = USHORT_TO_FLOAT(dest[i][BCOMP]); 869848b8605Smrg destF[i][ACOMP] = USHORT_TO_FLOAT(dest[i][ACOMP]); 870848b8605Smrg } 871848b8605Smrg } 872848b8605Smrg /* do blend */ 873848b8605Smrg blend_general_float(ctx, n, mask, rgbaF, destF, chanType); 874848b8605Smrg /* convert back to ushorts */ 875848b8605Smrg for (i = 0; i < n; i++) { 876848b8605Smrg if (mask[i]) { 877848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(rgba[i][RCOMP], rgbaF[i][RCOMP]); 878848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(rgba[i][GCOMP], rgbaF[i][GCOMP]); 879848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(rgba[i][BCOMP], rgbaF[i][BCOMP]); 880848b8605Smrg UNCLAMPED_FLOAT_TO_USHORT(rgba[i][ACOMP], rgbaF[i][ACOMP]); 881848b8605Smrg } 882848b8605Smrg } 883848b8605Smrg } 884848b8605Smrg else { 885848b8605Smrg blend_general_float(ctx, n, mask, (GLfloat (*)[4]) src, 886848b8605Smrg (GLfloat (*)[4]) dst, chanType); 887848b8605Smrg } 888848b8605Smrg 889848b8605Smrg free(rgbaF); 890848b8605Smrg free(destF); 891848b8605Smrg} 892848b8605Smrg 893848b8605Smrg 894848b8605Smrg 895848b8605Smrg/** 896848b8605Smrg * Analyze current blending parameters to pick fastest blending function. 897848b8605Smrg * Result: the ctx->Color.BlendFunc pointer is updated. 898848b8605Smrg */ 899848b8605Smrgvoid 900848b8605Smrg_swrast_choose_blend_func(struct gl_context *ctx, GLenum chanType) 901848b8605Smrg{ 902848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 903848b8605Smrg const GLenum eq = ctx->Color.Blend[0].EquationRGB; 904848b8605Smrg const GLenum srcRGB = ctx->Color.Blend[0].SrcRGB; 905848b8605Smrg const GLenum dstRGB = ctx->Color.Blend[0].DstRGB; 906848b8605Smrg const GLenum srcA = ctx->Color.Blend[0].SrcA; 907848b8605Smrg const GLenum dstA = ctx->Color.Blend[0].DstA; 908848b8605Smrg 909848b8605Smrg if (ctx->Color.Blend[0].EquationRGB != ctx->Color.Blend[0].EquationA) { 910848b8605Smrg swrast->BlendFunc = blend_general; 911848b8605Smrg } 912848b8605Smrg else if (eq == GL_MIN) { 913848b8605Smrg /* Note: GL_MIN ignores the blending weight factors */ 914848b8605Smrg#if defined(USE_MMX_ASM) 915848b8605Smrg if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 916848b8605Smrg swrast->BlendFunc = _mesa_mmx_blend_min; 917848b8605Smrg } 918848b8605Smrg else 919848b8605Smrg#endif 920848b8605Smrg swrast->BlendFunc = blend_min; 921848b8605Smrg } 922848b8605Smrg else if (eq == GL_MAX) { 923848b8605Smrg /* Note: GL_MAX ignores the blending weight factors */ 924848b8605Smrg#if defined(USE_MMX_ASM) 925848b8605Smrg if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 926848b8605Smrg swrast->BlendFunc = _mesa_mmx_blend_max; 927848b8605Smrg } 928848b8605Smrg else 929848b8605Smrg#endif 930848b8605Smrg swrast->BlendFunc = blend_max; 931848b8605Smrg } 932848b8605Smrg else if (srcRGB != srcA || dstRGB != dstA) { 933848b8605Smrg swrast->BlendFunc = blend_general; 934848b8605Smrg } 935848b8605Smrg else if (eq == GL_FUNC_ADD && srcRGB == GL_SRC_ALPHA 936848b8605Smrg && dstRGB == GL_ONE_MINUS_SRC_ALPHA) { 937848b8605Smrg#if defined(USE_MMX_ASM) 938848b8605Smrg if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 939848b8605Smrg swrast->BlendFunc = _mesa_mmx_blend_transparency; 940848b8605Smrg } 941848b8605Smrg else 942848b8605Smrg#endif 943848b8605Smrg { 944848b8605Smrg if (chanType == GL_UNSIGNED_BYTE) 945848b8605Smrg swrast->BlendFunc = blend_transparency_ubyte; 946848b8605Smrg else if (chanType == GL_UNSIGNED_SHORT) 947848b8605Smrg swrast->BlendFunc = blend_transparency_ushort; 948848b8605Smrg else 949848b8605Smrg swrast->BlendFunc = blend_transparency_float; 950848b8605Smrg } 951848b8605Smrg } 952848b8605Smrg else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ONE) { 953848b8605Smrg#if defined(USE_MMX_ASM) 954848b8605Smrg if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 955848b8605Smrg swrast->BlendFunc = _mesa_mmx_blend_add; 956848b8605Smrg } 957848b8605Smrg else 958848b8605Smrg#endif 959848b8605Smrg swrast->BlendFunc = blend_add; 960848b8605Smrg } 961848b8605Smrg else if (((eq == GL_FUNC_ADD || eq == GL_FUNC_REVERSE_SUBTRACT) 962848b8605Smrg && (srcRGB == GL_ZERO && dstRGB == GL_SRC_COLOR)) 963848b8605Smrg || 964848b8605Smrg ((eq == GL_FUNC_ADD || eq == GL_FUNC_SUBTRACT) 965848b8605Smrg && (srcRGB == GL_DST_COLOR && dstRGB == GL_ZERO))) { 966848b8605Smrg#if defined(USE_MMX_ASM) 967848b8605Smrg if (cpu_has_mmx && chanType == GL_UNSIGNED_BYTE) { 968848b8605Smrg swrast->BlendFunc = _mesa_mmx_blend_modulate; 969848b8605Smrg } 970848b8605Smrg else 971848b8605Smrg#endif 972848b8605Smrg swrast->BlendFunc = blend_modulate; 973848b8605Smrg } 974848b8605Smrg else if (eq == GL_FUNC_ADD && srcRGB == GL_ZERO && dstRGB == GL_ONE) { 975848b8605Smrg swrast->BlendFunc = blend_noop; 976848b8605Smrg } 977848b8605Smrg else if (eq == GL_FUNC_ADD && srcRGB == GL_ONE && dstRGB == GL_ZERO) { 978848b8605Smrg swrast->BlendFunc = blend_replace; 979848b8605Smrg } 980848b8605Smrg else { 981848b8605Smrg swrast->BlendFunc = blend_general; 982848b8605Smrg } 983848b8605Smrg} 984848b8605Smrg 985848b8605Smrg 986848b8605Smrg 987848b8605Smrg/** 988848b8605Smrg * Apply the blending operator to a span of pixels. 989848b8605Smrg * We can handle horizontal runs of pixels (spans) or arrays of x/y 990848b8605Smrg * pixel coordinates. 991848b8605Smrg */ 992848b8605Smrgvoid 993848b8605Smrg_swrast_blend_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span) 994848b8605Smrg{ 995848b8605Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 996848b8605Smrg void *rbPixels; 997848b8605Smrg 998b8e80941Smrg assert(span->end <= SWRAST_MAX_WIDTH); 999b8e80941Smrg assert(span->arrayMask & SPAN_RGBA); 1000b8e80941Smrg assert(!ctx->Color.ColorLogicOpEnabled); 1001848b8605Smrg 1002848b8605Smrg rbPixels = _swrast_get_dest_rgba(ctx, rb, span); 1003848b8605Smrg 1004848b8605Smrg swrast->BlendFunc(ctx, span->end, span->array->mask, 1005848b8605Smrg span->array->rgba, rbPixels, span->array->ChanType); 1006848b8605Smrg} 1007