📄 mga_texcombine.c
字号:
/* * Copyright (c) 2003 Ville Syrjala * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Ville Syrjala <syrjala@sci.fi> */#include "glheader.h"#include "mgacontext.h"#include "mgatex.h"#include "mgaregs.h"/* * GL_ARB_texture_env_combine * GL_EXT_texture_env_combine * GL_ARB_texture_env_crossbar * GL_ATI_texture_env_combine3 */#define ARG_DISABLE 0xffffffff#define MGA_ARG1 0#define MGA_ARG2 1#define MGA_ALPHA 2GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit ){ mgaContextPtr mmesa = MGA_CONTEXT(ctx); const int source = mmesa->tmu_source[unit]; const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); GLuint numColorArgs = 0, numAlphaArgs = 0; GLuint arg1[3], arg2[3], alpha[3]; int args[3]; int i; switch (texUnit->Combine.ModeRGB) { case GL_REPLACE: numColorArgs = 1; break; case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_SUBTRACT: numColorArgs = 2; break; case GL_INTERPOLATE: case GL_MODULATE_ADD_ATI: case GL_MODULATE_SIGNED_ADD_ATI: case GL_MODULATE_SUBTRACT_ATI: numColorArgs = 3; break; default: return GL_FALSE; } switch (texUnit->Combine.ModeA) { case GL_REPLACE: numAlphaArgs = 1; break; case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_SUBTRACT: numAlphaArgs = 2; break; default: return GL_FALSE; } /* Start fresh :) */ *reg = 0; /* COLOR */ for (i = 0; i < 3; i++) { arg1[i] = 0; arg2[i] = 0; alpha[i] = 0; } for (i = 0;i < numColorArgs; i++) { switch (texUnit->Combine.SourceRGB[i]) { case GL_TEXTURE: arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; break; case GL_TEXTURE0: if (source == 0) { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; } else { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_prevtex; } break; case GL_TEXTURE1: if (source == 0) { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; /* G400 specs (TDUALSTAGE0) */ arg2[i] |= TD0_color_arg2_prevstage; alpha[i] |= TD0_color_alpha_prevstage; } else { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; } break; case GL_CONSTANT: if (mmesa->fcol_used && mmesa->envcolor[source] != mmesa->envcolor[!source]) return GL_FALSE; arg1[i] |= ARG_DISABLE; arg2[i] |= TD0_color_arg2_fcol; alpha[i] |= TD0_color_alpha_fcol; mmesa->setup.fcol = mmesa->envcolor[source]; mmesa->fcol_used = GL_TRUE; break; case GL_PRIMARY_COLOR: arg1[i] |= ARG_DISABLE; /* G400 specs (TDUALSTAGE1) */ if (unit == 0 || (mmesa->setup.tdualstage0 & ((TD0_color_sel_mul & TD0_color_sel_add) | (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) { arg2[i] |= TD0_color_arg2_diffuse; alpha[i] |= TD0_color_alpha_diffuse; } else { arg2[i] |= ARG_DISABLE; alpha[i] |= ARG_DISABLE; } break; case GL_PREVIOUS: arg1[i] |= ARG_DISABLE; if (unit == 0) { arg2[i] |= TD0_color_arg2_diffuse; alpha[i] |= TD0_color_alpha_diffuse; } else { arg2[i] |= TD0_color_arg2_prevstage; alpha[i] |= TD0_color_alpha_prevstage; } break; default: return GL_FALSE; } switch (texUnit->Combine.OperandRGB[i]) { case GL_SRC_COLOR: arg1[i] |= 0; arg2[i] |= 0; if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT && RGBA_EQUAL( mmesa->envcolor[source] )) { alpha[i] |= 0; } else { alpha[i] |= ARG_DISABLE; } break; case GL_ONE_MINUS_SRC_COLOR: arg1[i] |= TD0_color_arg1_inv_enable; arg2[i] |= TD0_color_arg2_inv_enable; if (texUnit->Combine.SourceRGB[i] == GL_CONSTANT && RGBA_EQUAL( mmesa->envcolor[source] )) { alpha[i] |= (TD0_color_alpha1inv_enable | TD0_color_alpha2inv_enable); } else { alpha[i] |= ARG_DISABLE; } break; case GL_SRC_ALPHA: arg1[i] |= TD0_color_arg1_replicatealpha_enable; arg2[i] |= TD0_color_arg2_replicatealpha_enable; alpha[i] |= 0; break; case GL_ONE_MINUS_SRC_ALPHA: arg1[i] |= (TD0_color_arg1_replicatealpha_enable | TD0_color_arg1_inv_enable); arg2[i] |= (TD0_color_arg2_replicatealpha_enable | TD0_color_arg2_inv_enable); alpha[i] |= (TD0_color_alpha1inv_enable | TD0_color_alpha2inv_enable); break; } } switch (texUnit->Combine.ModeRGB) { case GL_MODULATE_ADD_ATI: case GL_MODULATE_SIGNED_ADD_ATI: /* Special handling for ATI_texture_env_combine3. * If Arg1 == Arg0 or Arg1 == Arg2 we can use arg1 or arg2 as input for * both multiplier and adder. */ /* Arg1 == arg1 */ if (arg1[1] == arg1[0]) { if ((arg1[1] | arg2[2]) != ARG_DISABLE) { *reg |= arg1[1] | arg2[2]; args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ARG2; break; } else if ((arg1[1] | alpha[2]) != ARG_DISABLE) { *reg |= arg1[1] | alpha[2]; args[0] = MGA_ARG1; args[1] = MGA_ARG1; args[2] = MGA_ALPHA; break; } } if (arg1[1] == arg1[2]) { if ((arg1[1] | arg2[0]) != ARG_DISABLE) { *reg |= arg1[1] | arg2[0]; args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ARG1; break; } else if ((arg1[1] | alpha[0]) != ARG_DISABLE) { *reg |= arg1[1] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG1; break; } } /* fallthrough */ case GL_MODULATE_SUBTRACT_ATI: /* Arg1 == arg2 */ if (arg2[1] == arg2[0]) { if ((arg2[1] | arg1[2]) != ARG_DISABLE) { *reg |= arg2[1] | arg1[2]; args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ARG1; break; } else if ((arg2[1] | alpha[2]) != ARG_DISABLE) { *reg |= arg2[1] | alpha[2]; args[0] = MGA_ARG2; args[1] = MGA_ARG2; args[2] = MGA_ALPHA; break; } } if (arg2[1] == arg2[2]) { if ((arg2[1] | arg1[0]) != ARG_DISABLE) { *reg |= arg2[1] | arg1[0]; args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ARG2; break; } else if ((arg2[1] | alpha[0]) != ARG_DISABLE) { *reg |= arg2[1] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG2; break; } } /* fallthrough */ default: /* Find working combo of arg1, arg2 and alpha. * * Keep the Arg0 != alpha cases first since there's * no way to get alpha out by itself (GL_REPLACE). * * Keep the Arg2 == alpha cases first because only alpha has the * capabilities to function as Arg2 (GL_INTERPOLATE). Also good for * GL_ADD, GL_ADD_SIGNED, GL_SUBTRACT since we can't get alpha to the * adder. * * Keep the Arg1 == alpha cases last for GL_MODULATE_ADD_ATI, * GL_MODULATE_SIGNED_ADD_ATI. Again because we can't get alpha to the * adder. * * GL_MODULATE_SUBTRACT_ATI needs special treatment since it requires * that Arg1 == arg2. This requirement clashes with those of other modes. */ if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) { *reg |= arg1[0] | arg2[1] | alpha[2]; args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA; } else if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE && texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) { *reg |= arg1[1] | arg2[0] | alpha[2]; args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA; } else if ((arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE && texUnit->Combine.ModeRGB != GL_MODULATE_SUBTRACT_ATI) { *reg |= arg1[1] | arg2[2] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2; } else if ((arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) { *reg |= arg1[2] | arg2[1] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1; } else if ((arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) { *reg |= arg1[0] | arg2[2] | alpha[1]; args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2; } else if ((arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) { *reg |= arg1[2] | arg2[0] | alpha[1]; args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1; } else { /* nothing suitable */ return GL_FALSE; } } switch (texUnit->Combine.ModeRGB) { case GL_REPLACE: if (texUnit->Combine.ScaleShiftRGB) { return GL_FALSE; } if (args[0] == MGA_ARG1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -