Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/Blender.cpp
2 views
/*1Copyright (C) 2003 Rice196423This program is free software; you can redistribute it and/or4modify it under the terms of the GNU General Public License5as published by the Free Software Foundation; either version 26of the License, or (at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program; if not, write to the Free Software15Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.16*/1718#include "Render.h"1920const char * sc_szBlClr[4] = { "In", "Mem", "Bl", "Fog" };21const char * sc_szBlA1[4] = { "AIn", "AFog", "AShade", "0" };22const char * sc_szBlA2[4] = { "1-A", "AMem", "1", "0" };2324//========================================================================25void CBlender::InitBlenderMode(void) // Set Alpha Blender mode26{27//1. Z_COMPARE -- Enable / Disable Zbuffer compare28// 1 - Enable ZBuffer29// 0 - Disable ZBuffer3031//2. Z_UPDATE -- Enable / Disable Zbuffer update32// 1 - Enable ZBuffer writeable33// 0 - Zbuffer not writeable3435//3. AA_EN and IM_RD -- Anti-Alias36// AA_EN - Enable anti-aliase37// AA_EN | IM_RD - Reduced anti-aliase38// IM_RD - ??39// - - Disable anti-aliase4041//4. ZMode42// #define ZMODE_OPA 0 -- Usually used with Z_COMPARE and Z_UPDATE43// or used without neither Z_COMPARE or Z_UPDATE44// if used with Z_COMPARE and Z_UPDATE, then this is45// the regular ZBuffer mode, with compare and update46// #define ZMODE_INTER 0x40047// #define ZMODE_XLU 0x800 -- Usually used with Z_COMPARE, but not with Z_UPDATE48// Do only compare, no zbuffer update.49// Not output if the z value is the same50// #define ZMODE_DEC 0xc00 -- Usually used with Z_COMPARE, but not with Z_UPDATE51// Do only compare, no update, but because this is52// decal mode, so image should be updated even53// the z value is the same as compared.5455CRender *render = CRender::g_pRender;5657// Alpha Blender Modes5859/*606. FORCE_BL - Alpha blending at blender stage611 - Enable alpha blending at blender620 - Disable alpha blending at blender6364Alpha blending at blender is usually used to render XLU surface65if enabled, then use the blending setting of C1 and C266677. ALPHA_CVG_SEL - Output full alpha from the color combiner, usually not used together68with FORCE_BL. If it is used together with FORCE_BL, then ignore this69708. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha71729. TEX_EDGE - Ignore this737410.CLR_ON_CVG - Used with XLU surfaces, ignore it757611.CVG_DST77#define CVG_DST_CLAMP 0 - Usually used with OPA surface78#define CVG_DST_WRAP 0x100 - Usually used with XLU surface or OPA line79#define CVG_DST_FULL 0x200 - ?80#define CVG_DST_SAVE 0x300 - ?818283Possible Blending Inputs:8485In - Input from color combiner86Mem - Input from current frame buffer87Fog - Fog generator88BL - Blender8990Possible Blending Factors:91A-IN - Alpha from color combiner92A-MEM - Alpha from current frame buffer93(1-A) -94A-FOG - Alpha of fog color95A-SHADE - Alpha of shade961 - 1970 - 098*/99#define BLEND_NOOP 0x0000100101#define BLEND_NOOP5 0xcc48 // Fog * 0 + Mem * 1102#define BLEND_NOOP4 0xcc08 // Fog * 0 + In * 1103#define BLEND_FOG_ASHADE 0xc800104#define BLEND_FOG_3 0xc000 // Fog * AIn + In * 1-A105#define BLEND_FOG_MEM 0xc440 // Fog * AFog + Mem * 1-A106#define BLEND_FOG_APRIM 0xc400 // Fog * AFog + In * 1-A107108#define BLEND_BLENDCOLOR 0x8c88109#define BLEND_BI_AFOG 0x8400 // Bl * AFog + In * 1-A110#define BLEND_BI_AIN 0x8040 // Bl * AIn + Mem * 1-A111112#define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?!113#define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A114115#define BLEND_NOOP3 0x0c48 // In * 0 + Mem * 1116#define BLEND_PASS 0x0c08 // In * 0 + In * 1117#define BLEND_FOG_MEM_IN_MEM 0x0440 // In * AFog + Mem * 1-A118#define BLEND_FOG_MEM_FOG_MEM 0x04c0 // In * AFog + Fog * 1-A119#define BLEND_OPA 0x0044 // In * AIn + Mem * AMem120#define BLEND_XLU 0x0040121#define BLEND_MEM_ALPHA_IN 0x4044 // Mem * AIn + Mem * AMem122123124uint32 blendmode_1 = (uint32)( gRDP.otherMode.blender & 0xcccc );125uint32 blendmode_2 = (uint32)( gRDP.otherMode.blender & 0x3333 );126uint32 cycletype = gRDP.otherMode.cycle_type;127128switch( cycletype )129{130case CYCLE_TYPE_FILL:131//BlendFunc(BLEND_ONE, BLEND_ZERO);132//Enable();133Disable();134break;135case CYCLE_TYPE_COPY:136//Disable();137BlendFunc(BLEND_ONE, BLEND_ZERO);138Enable();139break;140case CYCLE_TYPE_2:141if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp )142{143BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);144Enable();145break;146}147148/*149if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 )150{151BlendFunc(BLEND_ONE, BLEND_ZERO);152Enable();153break;154}155*/156157switch( blendmode_1+blendmode_2 )158{159case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1160case BLEND_FOG_APRIM+(BLEND_PASS>>2):161BlendFunc(BLEND_ONE, BLEND_ZERO);162if( gRDP.otherMode.alpha_cvg_sel )163{164Enable();165}166else167{168Disable();169}170171render->SetAlphaTestEnable( ((gRDP.otherModeL >> RSP_SETOTHERMODE_SHIFT_ALPHACOMPARE) & 0x3)==1 ? TRUE : FALSE);172break;173case BLEND_PASS+(BLEND_OPA>>2):174// 0x0c19175// Cycle1: In * 0 + In * 1176// Cycle2: In * AIn + Mem * AMem177if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel )178{179BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);180Enable();181}182else183{184BlendFunc(BLEND_ONE, BLEND_ZERO);185Enable();186}187break;188case BLEND_PASS + (BLEND_XLU>>2):189// 0x0c18190// Cycle1: In * 0 + In * 1191// Cycle2: In * AIn + Mem * 1-A192case BLEND_FOG_ASHADE + (BLEND_XLU>>2):193//Cycle1: Fog * AShade + In * 1-A194//Cycle2: In * AIn + Mem * 1-A195case BLEND_FOG_APRIM + (BLEND_XLU>>2):196//Cycle1: Fog * AFog + In * 1-A197//Cycle2: In * AIn + Mem * 1-A198//case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):199//Cycle1: In * AFog + Fog * 1-A200//Cycle2: In * AIn + Mem * AMem201case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):202//Cycle1: In * AFog + Fog * 1-A203//Cycle2: In * 0 + In * 1204case BLEND_XLU + (BLEND_XLU>>2):205//Cycle1: Fog * AFog + In * 1-A206//Cycle2: In * AIn + Mem * 1-A207case BLEND_BI_AFOG + (BLEND_XLU>>2):208//Cycle1: Bl * AFog + In * 1-A209//Cycle2: In * AIn + Mem * 1-A210case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):211//Cycle1: In * AIn + Mem * 1-A212//Cycle2: In * AFog + Mem * 1-A213case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):214//Cycle1: In * 0 + In * 1215//Cycle2: In * AFog + Mem * 1-A216BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);217Enable();218break;219case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):220//Cycle1: In * AFog + Fog * 1-A221//Cycle2: In * AIn + Mem * AMem222BlendFunc(BLEND_ONE, BLEND_ZERO);223Enable();224break;225226case BLEND_FOG_APRIM + (BLEND_OPA>>2):227// For Golden Eye228//Cycle1: Fog * AFog + In * 1-A229//Cycle2: In * AIn + Mem * AMem230case BLEND_FOG_ASHADE + (BLEND_OPA>>2):231//Cycle1: Fog * AShade + In * 1-A232//Cycle2: In * AIn + Mem * AMem233case BLEND_BI_AFOG + (BLEND_OPA>>2):234//Cycle1: Bl * AFog + In * 1-A235//Cycle2: In * AIn + Mem * 1-AMem236case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):237//Cycle1: Fog * AShade + In * 1-A238//Cycle2: In * AIn + In * 1-A239case BLEND_NOOP + (BLEND_OPA>>2):240//Cycle1: In * AIn + In * 1-A241//Cycle2: In * AIn + Mem * AMem242case BLEND_NOOP4 + (BLEND_NOOP>>2):243//Cycle1: Fog * AIn + In * 1-A244//Cycle2: In * 0 + In * 1245case BLEND_FOG_ASHADE+(BLEND_PASS>>2):246//Cycle1: Fog * AShade + In * 1-A247//Cycle2: In * 0 + In * 1248case BLEND_FOG_3+(BLEND_PASS>>2):249BlendFunc(BLEND_ONE, BLEND_ZERO);250Enable();251break;252case BLEND_FOG_ASHADE+0x0301:253// c800 - Cycle1: Fog * AShade + In * 1-A254// 0301 - Cycle2: In * 0 + In * AMem255BlendFunc(BLEND_SRCALPHA, BLEND_ZERO);256Enable();257break;258case 0x0c08+0x1111:259// 0c08 - Cycle1: In * 0 + In * 1260// 1111 - Cycle2: Mem * AFog + Mem * AMem261BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);262Enable();263break;264default:265#ifdef DEBUGGER266if( pauseAtNext )267{268uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;269uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;270uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;271uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;272273uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;274uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;275uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;276uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;277278TRACE0("Unknown Blender Mode: 2 cycle");279DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t%04x - Cycle2:\t%s * %s + %s * %s", blendmode_1,280sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1], blendmode_2,281sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);282283}284#endif285if( blendmode_2 == (BLEND_PASS>>2) )286{287BlendFunc(BLEND_ONE, BLEND_ZERO);288}289else290{291BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);292}293Enable();294break;295}296break;297default: // 1/2 Cycle or Copy298if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp && blendmode_1 != BLEND_FOG_ASHADE )299{300BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);301Enable();302break;303}304if( gRDP.otherMode.force_bl && options.enableHackForGames == HACK_FOR_COMMANDCONQUER )305{306BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);307Enable();308break;309}310311#ifdef DEBUGGER312//if( (blendmode_1>>2) != blendmode_2 )313//{314// DebuggerAppendMsg("Warning: in 1 cycle mode, blend1!=blend2");315//}316#endif317318switch ( blendmode_1 )319//switch ( blendmode_2<<2 )320{321case BLEND_XLU: // IN * A_IN + MEM * (1-A_IN)322case BLEND_BI_AIN: // Bl * AIn + Mem * 1-A323case BLEND_FOG_MEM: // c440 - Cycle1: Fog * AFog + Mem * 1-A324case BLEND_FOG_MEM_IN_MEM: // c440 - Cycle1: In * AFog + Mem * 1-A325case BLEND_BLENDCOLOR: //Bl * 0 + Bl * 1326case 0x00c0: //In * AIn + Fog * 1-A327BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);328Enable();329break;330case BLEND_MEM_ALPHA_IN: // Mem * AIn + Mem * AMem331BlendFunc(BLEND_ZERO, BLEND_DESTALPHA);332Enable();333break;334case BLEND_PASS: // IN * 0 + IN * 1335BlendFunc(BLEND_ONE, BLEND_ZERO);336if( gRDP.otherMode.alpha_cvg_sel )337{338Enable();339}340else341{342Disable();343}344break;345case BLEND_OPA: // IN * A_IN + MEM * A_MEM346if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )347{348BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);349}350else351{352BlendFunc(BLEND_ONE, BLEND_ZERO);353}354Enable();355break;356case BLEND_NOOP: // IN * A_IN + IN * (1 - A_IN)357case BLEND_FOG_ASHADE: // Fog * AShade + In * 1-A358case BLEND_FOG_MEM_3: // Mem * AFog + Fog * 1-A359case BLEND_BI_AFOG: // Bl * AFog + In * 1-A360BlendFunc(BLEND_ONE, BLEND_ZERO);361Enable();362break;363case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A364BlendFunc(BLEND_INVSRCALPHA, BLEND_ZERO);365Enable();366break;367case BLEND_NOOP3: // In * 0 + Mem * 1368case BLEND_NOOP5: // Fog * 0 + Mem * 1369BlendFunc(BLEND_ZERO, BLEND_ONE);370Enable();371break;372case BLEND_MEM: // Mem * 0 + Mem * 1-A373// WaveRace374BlendFunc(BLEND_ZERO, BLEND_ONE);375Enable();376break;377default:378#ifdef DEBUGGER379if( pauseAtNext )380{381uint32 dwM1A_1 = (gRDP.otherMode.blender>>14) & 0x3;382uint32 dwM1B_1 = (gRDP.otherMode.blender>>10) & 0x3;383uint32 dwM2A_1 = (gRDP.otherMode.blender>>6) & 0x3;384uint32 dwM2B_1 = (gRDP.otherMode.blender>>2) & 0x3;385386uint32 dwM1A_2 = (gRDP.otherMode.blender>>12) & 0x3;387uint32 dwM1B_2 = (gRDP.otherMode.blender>>8) & 0x3;388uint32 dwM2A_2 = (gRDP.otherMode.blender>>4) & 0x3;389uint32 dwM2B_2 = (gRDP.otherMode.blender ) & 0x3;390391TRACE0("Unknown Blender Mode: 1 cycle");392DebuggerAppendMsg( "\tblender:\t\t%04x - Cycle1:\t%s * %s + %s * %s\n\t\t\tCycle2:\t%s * %s + %s * %s", blendmode_1,393sc_szBlClr[dwM1A_1], sc_szBlA1[dwM1B_1], sc_szBlClr[dwM2A_1], sc_szBlA2[dwM2B_1],394sc_szBlClr[dwM1A_2], sc_szBlA1[dwM1B_2], sc_szBlClr[dwM2A_2], sc_szBlA2[dwM2B_2]);395}396#endif397BlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);398Enable();399render->SetAlphaTestEnable(TRUE);400break;401}402}403}404405406407