Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/OGLExtCombiner.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 <algorithm>19#include "osal_opengl.h"2021#if SDL_VIDEO_OPENGL22#include "OGLExtensions.h"23#endif24#include "OGLDebug.h"25#include "OGLExtCombiner.h"26#include "OGLExtRender.h"27#include "OGLDecodedMux.h"28#include "OGLGraphicsContext.h"29#include "OGLTexture.h"30#include "DirectXDecodedMux.h"3132#define GL_MODULATE_ADD_ATI 0x874433#define GL_MODULATE_SUBTRACT_ATI 0x87463435//========================================================================36COGLColorCombiner4::COGLColorCombiner4(CRender *pRender)37:COGLColorCombiner(pRender), m_maxTexUnits(0), m_lastIndex(-1),38m_dwLastMux0(0), m_dwLastMux1(0)39{40m_bOGLExtCombinerSupported=false;41m_bSupportModAdd_ATI = false;42m_bSupportModSub_ATI = false;43delete m_pDecodedMux;44m_pDecodedMux = new COGLExtDecodedMux;45}4647COGLColorCombiner4v2::COGLColorCombiner4v2(CRender *pRender)48:COGLColorCombiner4(pRender)49{50delete m_pDecodedMux;51m_pDecodedMux = new DecodedMuxForOGL14V2;52}5354COGLColorCombiner2::COGLColorCombiner2(CRender *pRender)55:COGLColorCombiner4(pRender)56{57delete m_pDecodedMux;58m_pDecodedMux = new CDirectXDecodedMux; // Use Mux for DirectX because we support only 1 texture for each stage59m_ppGeneralDecodedMux = &m_pDecodedMux;60}6162//////////////////////////////////////////////////////////////////////////63bool COGLColorCombiner4::Initialize(void)64{65m_bOGLExtCombinerSupported = false;66m_bSupportModAdd_ATI = false;67m_bSupportModSub_ATI = false;68m_maxTexUnits = 1;6970#if SDL_VIDEO_OPENGL71if( COGLColorCombiner::Initialize() )72{73m_bSupportMultiTexture = true;74COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);7576if( pcontext->IsExtensionSupported("GL_EXT_texture_env_combine") || pcontext->IsExtensionSupported("GL_ARB_texture_env_combine") )77{78m_bOGLExtCombinerSupported = true;79glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&m_maxTexUnits);80OPENGL_CHECK_ERRORS;81if( m_maxTexUnits > 8 ) m_maxTexUnits = 8;8283TRACE0("Starting Ogl 1.4 multitexture combiner" );84TRACE1("m_maxTexUnits = %d", m_maxTexUnits);85if( pcontext->IsExtensionSupported("ATI_texture_env_combine3") )86{87m_bSupportModAdd_ATI = true;88m_bSupportModSub_ATI = true;89}90}91else92{93DebugMessage(M64MSG_ERROR, "Your video card does not support OpenGL extension combiner, you can only use the basic OpenGL combiner functions");94}95m_supportedStages = m_maxTexUnits;96return true;97}98return false;99100#elif SDL_VIDEO_OPENGL_ES2101return true;102#endif103}104105bool COGLColorCombiner2::Initialize(void)106{107TRACE0("Starting Ogl 1.2/1.3 multitexture combiner" );108if( COGLColorCombiner4::Initialize() )109{110// For general combiner flags111m_dwGeneralMaxStages = m_supportedStages;112113m_bTxtOpAdd = m_bSupportAdd;114m_bTxtOpSub = m_bSupportSubtract;115m_bTxtOpLerp = true;116117m_bTxtOpAddSmooth = true;118m_bTxtOpBlendCurAlpha = true;119m_bTxtOpBlendDifAlpha = true;120m_bTxtOpBlendFacAlpha = true;121m_bTxtOpBlendTxtAlpha = true;122m_bTxtOpMulAdd = m_bSupportModAdd_ATI;123124return true;125}126else127{128return false;129}130}131//========================================================================132void COGLColorCombiner4::InitCombinerCycleFill(void)133{134for( int i=0; i<m_supportedStages; i++ )135{136pglActiveTexture(GL_TEXTURE0_ARB+i);137OPENGL_CHECK_ERRORS;138m_pOGLRender->EnableTexUnit(i,FALSE);139}140141//pglActiveTexture(GL_TEXTURE0_ARB);142//m_pOGLRender->EnableTexUnit(0,FALSE);143//pglActiveTexture(GL_TEXTURE1_ARB);144//m_pOGLRender->EnableTexUnit(1,FALSE);145}146147//////////////////////////////////////////////////////////////////////////148void COGLColorCombiner4::InitCombinerCycle12(void)149{150if( !m_bOGLExtCombinerSupported )151{152COGLColorCombiner::InitCombinerCycle12();153return;154}155156#ifdef DEBUGGER157if( debuggerDropCombiners )158{159UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);160m_vCompiledSettings.clear();161m_dwLastMux0 = m_dwLastMux1 = 0;162debuggerDropCombiners = false;163}164#endif165166m_pOGLRender->EnableMultiTexture();167168bool combinerIsChanged = false;169170if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 )171{172combinerIsChanged = true;173m_lastIndex = FindCompiledMux();174if( m_lastIndex < 0 ) // Can not found175{176m_lastIndex = ParseDecodedMux();177#ifdef DEBUGGER178DisplaySimpleMuxString();179#endif180}181182m_dwLastMux0 = m_pDecodedMux->m_dwMux0;183m_dwLastMux1 = m_pDecodedMux->m_dwMux1;184}185186187if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )188{189if( m_bCycleChanged || combinerIsChanged )190{191GenerateCombinerSettingConstants(m_lastIndex);192GenerateCombinerSetting(m_lastIndex);193}194else if( gRDP.colorsAreReloaded )195{196GenerateCombinerSettingConstants(m_lastIndex);197}198199m_pOGLRender->SetAllTexelRepeatFlag();200201gRDP.colorsAreReloaded = false;202gRDP.texturesAreReloaded = false;203}204else205{206m_pOGLRender->SetAllTexelRepeatFlag();207}208}209210//////////////////////////////////////////////////////////////////////////211int COGLColorCombiner4::ParseDecodedMux()212{213#define nextUnit() {unitNo++;}214#if SDL_VIDEO_OPENGL215if( m_maxTexUnits<3)216return ParseDecodedMux2Units();217218OGLExtCombinerSaveType res;219for( int k=0; k<8; k++ )220res.units[k].tex = -1;221222COGLDecodedMux &mux = *(COGLDecodedMux*)m_pDecodedMux;223224int unitNos[2];225for( int rgbalpha = 0; rgbalpha<2; rgbalpha++ )226{227unitNos[rgbalpha] = 0;228for( int cycle = 0; cycle<2; cycle++ )229{230int &unitNo = unitNos[rgbalpha];231OGLExtCombinerType &unit = res.units[unitNo];232OGLExt1CombType &comb = unit.Combs[rgbalpha];233CombinerFormatType type = m_pDecodedMux->splitType[cycle*2+rgbalpha];234N64CombinerType &m = m_pDecodedMux->m_n64Combiners[cycle*2+rgbalpha];235comb.arg0 = comb.arg1 = comb.arg2 = CM_IGNORE_BYTE;236237switch( type )238{239case CM_FMT_TYPE_NOT_USED:240comb.arg0 = MUX_COMBINED;241unit.ops[rgbalpha] = GL_REPLACE;242nextUnit();243break;244case CM_FMT_TYPE_D: // = A245comb.arg0 = m.d;246unit.ops[rgbalpha] = GL_REPLACE;247nextUnit();248break;249case CM_FMT_TYPE_A_ADD_D: // = A+D250comb.arg0 = m.a;251comb.arg1 = m.d;252unit.ops[rgbalpha] = GL_ADD;253nextUnit();254break;255case CM_FMT_TYPE_A_SUB_B: // = A-B256comb.arg0 = m.a;257comb.arg1 = m.b;258unit.ops[rgbalpha] = GL_SUBTRACT_ARB;259nextUnit();260break;261case CM_FMT_TYPE_A_MOD_C: // = A*C262comb.arg0 = m.a;263comb.arg1 = m.c;264unit.ops[rgbalpha] = GL_MODULATE;265nextUnit();266break;267case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D268if( m_bSupportModAdd_ATI )269{270comb.arg0 = m.a;271comb.arg2 = m.c;272comb.arg1 = m.d;273unit.ops[rgbalpha] = GL_MODULATE_ADD_ATI;274nextUnit();275}276else277{278if( unitNo < m_maxTexUnits-1 )279{280comb.arg0 = m.a;281comb.arg1 = m.c;282unit.ops[rgbalpha] = GL_MODULATE;283nextUnit();284res.units[unitNo].Combs[rgbalpha].arg0 = MUX_COMBINED;285res.units[unitNo].Combs[rgbalpha].arg1 = m.d;286res.units[unitNo].ops[rgbalpha] = GL_ADD;287nextUnit();288}289else290{291comb.arg0 = m.a;292comb.arg1 = m.c;293comb.arg2 = m.d;294unit.ops[rgbalpha] = GL_INTERPOLATE_ARB;295nextUnit();296}297}298break;299case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B300comb.arg0 = m.a;301comb.arg1 = m.b;302comb.arg2 = m.c;303unit.ops[rgbalpha] = GL_INTERPOLATE_ARB;304nextUnit();305break;306case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D307if( unitNo < m_maxTexUnits-1 )308{309comb.arg0 = m.a;310comb.arg1 = m.b;311unit.ops[rgbalpha] = GL_SUBTRACT_ARB;312nextUnit();313res.units[unitNo].Combs[rgbalpha].arg0 = MUX_COMBINED;314res.units[unitNo].Combs[rgbalpha].arg1 = m.d;315res.units[unitNo].ops[rgbalpha] = GL_ADD;316nextUnit();317}318else319{320comb.arg0 = m.a;321comb.arg1 = m.c;322comb.arg2 = m.d;323unit.ops[rgbalpha] = GL_INTERPOLATE_ARB;324nextUnit();325}326break;327case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C328if( unitNo < m_maxTexUnits-1 )329{330comb.arg0 = m.a;331comb.arg1 = m.b;332unit.ops[rgbalpha] = GL_SUBTRACT_ARB;333nextUnit();334res.units[unitNo].Combs[rgbalpha].arg0 = MUX_COMBINED;335res.units[unitNo].Combs[rgbalpha].arg1 = m.c;336res.units[unitNo].ops[rgbalpha] = GL_MODULATE;337nextUnit();338}339else340{341comb.arg0 = m.a;342comb.arg1 = m.c;343comb.arg2 = m.d;344unit.ops[rgbalpha] = GL_INTERPOLATE_ARB;345nextUnit();346}347break;348case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D349default:350if( unitNo < m_maxTexUnits-1 )351{352comb.arg0 = m.a;353comb.arg1 = m.b;354unit.ops[rgbalpha] = GL_SUBTRACT_ARB;355nextUnit();356if( m_bSupportModAdd_ATI )357{358res.units[unitNo].Combs[rgbalpha].arg0 = MUX_COMBINED;359res.units[unitNo].Combs[rgbalpha].arg2 = m.c;360res.units[unitNo].Combs[rgbalpha].arg1 = m.d;361res.units[unitNo].ops[rgbalpha] = GL_MODULATE_ADD_ATI;362nextUnit();363}364else365{366res.units[unitNo].Combs[rgbalpha].arg0 = m.a;367res.units[unitNo].Combs[rgbalpha].arg1 = m.b;368res.units[unitNo].Combs[rgbalpha].arg2 = m.c;369res.units[unitNo].ops[rgbalpha] = GL_INTERPOLATE_ARB;370nextUnit();371}372}373else374{375comb.arg0 = m.a;376comb.arg1 = m.c;377comb.arg2 = m.d;378unit.ops[rgbalpha] = GL_INTERPOLATE_ARB;379nextUnit();380}381break;382}383}384}385386res.numOfUnits = min(m_maxTexUnits, max(unitNos[0],unitNos[1]));387388if( unitNos[0]>m_maxTexUnits || unitNos[1]>m_maxTexUnits )389{390TRACE0("Unit overflows");391}392393for( int j=0; j<2; j++ )394{395if( unitNos[j]<res.numOfUnits )396{397for( int i=unitNos[j]; i<res.numOfUnits; i++ )398{399res.units[i].Combs[j].arg0 = MUX_COMBINED;400res.units[i].ops[j] = GL_REPLACE;401}402}403}404405res.units[0].tex = 0;406res.units[1].tex = 1;407408res.primIsUsed = mux.isUsed(MUX_PRIM);409res.envIsUsed = mux.isUsed(MUX_ENV);410res.lodFracIsUsed = mux.isUsed(MUX_LODFRAC) || mux.isUsed(MUX_PRIMLODFRAC);411412return SaveParsedResult(res);413414#elif SDL_VIDEO_OPENGL_ES2415return 0;416#endif417}418419int COGLColorCombiner4::ParseDecodedMux2Units()420{421OGLExtCombinerSaveType res;422for( int k=0; k<8; k++ )423res.units[k].tex = -1;424425res.numOfUnits = 2;426427for( int i=0; i<res.numOfUnits*2; i++ ) // Set combiner for each texture unit428{429// For each texture unit, set both RGB and Alpha channel430// Keep in mind that the m_pDecodeMux has been reformated and simplified very well431432OGLExtCombinerType &unit = res.units[i/2];433OGLExt1CombType &comb = unit.Combs[i%2];434435CombinerFormatType type = m_pDecodedMux->splitType[i];436N64CombinerType &m = m_pDecodedMux->m_n64Combiners[i];437438comb.arg0 = comb.arg1 = comb.arg2 = MUX_0;439440switch( type )441{442case CM_FMT_TYPE_NOT_USED:443comb.arg0 = MUX_COMBINED;444unit.ops[i%2] = GL_REPLACE;445break;446case CM_FMT_TYPE_D: // = A447comb.arg0 = m.d;448unit.ops[i%2] = GL_REPLACE;449break;450#if SDL_VIDEO_OPENGL451case CM_FMT_TYPE_A_ADD_D: // = A+D452comb.arg0 = m.a;453comb.arg1 = m.d;454unit.ops[i%2] = GL_ADD;455break;456case CM_FMT_TYPE_A_SUB_B: // = A-B457comb.arg0 = m.a;458comb.arg1 = m.b;459unit.ops[i%2] = GL_SUBTRACT_ARB;460break;461case CM_FMT_TYPE_A_MOD_C: // = A*C462comb.arg0 = m.a;463comb.arg1 = m.c;464unit.ops[i%2] = GL_MODULATE;465break;466case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D467comb.arg0 = m.a;468comb.arg1 = m.c;469comb.arg2 = m.d;470unit.ops[i%2] = GL_INTERPOLATE_ARB;471break;472case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B473comb.arg0 = m.a;474comb.arg1 = m.b;475comb.arg2 = m.c;476unit.ops[i%2] = GL_INTERPOLATE_ARB;477break;478case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D479// fix me, to use 2 texture units480comb.arg0 = m.a;481comb.arg1 = m.b;482unit.ops[i%2] = GL_SUBTRACT_ARB;483break;484case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C485// fix me, to use 2 texture units486comb.arg0 = m.a;487comb.arg1 = m.c;488unit.ops[i%2] = GL_MODULATE;489break;490break;491case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D492#endif493default:494comb.arg0 = m.a;495comb.arg1 = m.b;496comb.arg2 = m.c;497unit.ops[i%2] = GL_INTERPOLATE_ARB;498break;499}500}501502if( m_pDecodedMux->splitType[2] == CM_FMT_TYPE_NOT_USED && m_pDecodedMux->splitType[3] == CM_FMT_TYPE_NOT_USED && !m_bTex1Enabled )503{504res.numOfUnits = 1;505}506507res.units[0].tex = 0;508res.units[1].tex = 1;509510return SaveParsedResult(res);511}512513const char* COGLColorCombiner4::GetOpStr(GLenum op)514{515switch( op )516{517case GL_REPLACE:518return "REPLACE";519#if SDL_VIDEO_OPENGL520case GL_MODULATE:521return "MOD";522case GL_ADD:523return "ADD";524case GL_ADD_SIGNED_ARB:525return "ADD_SIGNED";526case GL_INTERPOLATE_ARB:527return "INTERPOLATE";528case GL_SUBTRACT_ARB:529return "SUB";530#endif531case GL_MODULATE_ADD_ATI:532return "MULADD";533default:534return "SUB";535}536}537538int COGLColorCombiner4::SaveParsedResult(OGLExtCombinerSaveType &result)539{540result.dwMux0 = m_pDecodedMux->m_dwMux0;541result.dwMux1 = m_pDecodedMux->m_dwMux1;542543for( int n=0; n<result.numOfUnits; n++ )544{545for( int i=0; i<3; i++ )546{547result.units[n].glRGBArgs[i] = 0;548result.units[n].glRGBFlags[i] = 0;549result.units[n].glAlphaArgs[i] = 0;550result.units[n].glAlphaFlags[i] = 0;551if( result.units[n].rgbComb.args[i] != CM_IGNORE_BYTE )552{553result.units[n].glRGBArgs[i] = MapRGBArgs(result.units[n].rgbComb.args[i]);554result.units[n].glRGBFlags[i] = MapRGBArgFlags(result.units[n].rgbComb.args[i]);555}556if( result.units[n].alphaComb.args[i] != CM_IGNORE_BYTE )557{558result.units[n].glAlphaArgs[i] = MapAlphaArgs(result.units[n].alphaComb.args[i]);559result.units[n].glAlphaFlags[i] = MapAlphaArgFlags(result.units[n].alphaComb.args[i]);560}561}562}563564m_vCompiledSettings.push_back(result);565m_lastIndex = m_vCompiledSettings.size()-1;566567#ifdef DEBUGGER568if( logCombiners )569{570DisplaySimpleMuxString();571}572#endif573574return m_lastIndex;575}576577bool isGLtex(GLint val)578{579if( val >= GL_TEXTURE0_ARB && val <= GL_TEXTURE7_ARB )580return true;581else582return false;583}584585int COGLColorCombiner4v2::SaveParsedResult(OGLExtCombinerSaveType &result)586{587result.dwMux0 = m_pDecodedMux->m_dwMux0;588result.dwMux1 = m_pDecodedMux->m_dwMux1;589590int n;591592for( n=0; n<result.numOfUnits; n++ )593{594for( int i=0; i<3; i++ )595{596result.units[n].glRGBArgs[i] = 0;597result.units[n].glRGBFlags[i] = 0;598result.units[n].glAlphaArgs[i] = 0;599result.units[n].glAlphaFlags[i] = 0;600if( result.units[n].rgbComb.args[i] != CM_IGNORE_BYTE )601{602result.units[n].glRGBArgs[i] = MapRGBArgs(result.units[n].rgbComb.args[i]);603if( result.units[n].glRGBArgs[i] == GL_TEXTURE3_ARB && !result.envIsUsed )604result.units[n].glRGBArgs[i] = GL_TEXTURE2_ARB;605606result.units[n].glRGBFlags[i] = MapRGBArgFlags(result.units[n].rgbComb.args[i]);607}608if( result.units[n].alphaComb.args[i] != CM_IGNORE_BYTE )609{610result.units[n].glAlphaArgs[i] = MapAlphaArgs(result.units[n].alphaComb.args[i]);611if( result.units[n].glAlphaArgs[i] == GL_TEXTURE3_ARB && !result.envIsUsed )612result.units[n].glAlphaArgs[i] = GL_TEXTURE2_ARB;613614result.units[n].glAlphaFlags[i] = MapAlphaArgFlags(result.units[n].alphaComb.args[i]);615}616}617618if( isGLtex(result.units[n].glRGBArgs[0]) && isGLtex(result.units[n].glRGBArgs[1]) && isGLtex(result.units[n].glRGBArgs[2]) )619{620result.units[n].glRGBArgs[2] = GL_CONSTANT_ARB;621}622if( isGLtex(result.units[n].glAlphaArgs[0]) && isGLtex(result.units[n].glAlphaArgs[1]) && isGLtex(result.units[n].glAlphaArgs[2]) )623{624result.units[n].glRGBArgs[2] = GL_CONSTANT_ARB;625}626}627628int extraUnit = 0;629if( result.envIsUsed ) extraUnit++;630if( result.lodFracIsUsed ) extraUnit++;631for( n=result.numOfUnits; n<result.numOfUnits+extraUnit; n++ )632{633for( int i=0; i<3; i++ )634{635result.units[n].rgbComb.args[i]=CM_IGNORE_BYTE;636result.units[n].alphaComb.args[i]=CM_IGNORE_BYTE;637result.units[n].glRGBArgs[i] = 0;638result.units[n].glRGBFlags[i] = 0;639result.units[n].glAlphaArgs[i] = 0;640result.units[n].glAlphaFlags[i] = 0;641}642643result.units[n].rgbComb.args[0]=MUX_COMBINED;644result.units[n].alphaComb.args[0]=MUX_COMBINED;645result.units[n].rgbOp = GL_REPLACE;646result.units[n].alphaOp = GL_REPLACE;647result.units[n].glRGBArgs[0] = GL_PREVIOUS_ARB;648result.units[n].glRGBArgs[1] = GL_PREVIOUS_ARB;649result.units[n].rgbFlag0gl = GL_SRC_COLOR;650result.units[n].rgbFlag1gl = GL_SRC_COLOR;651result.units[n].glAlphaArgs[0] = GL_PREVIOUS_ARB;652result.units[n].glAlphaArgs[1] = GL_PREVIOUS_ARB;653result.units[n].alphaFlag0gl = GL_SRC_ALPHA;654result.units[n].alphaFlag1gl = GL_SRC_ALPHA;655}656657result.numOfUnits += extraUnit;658659m_vCompiledSettings.push_back(result);660m_lastIndex = m_vCompiledSettings.size()-1;661662#ifdef DEBUGGER663if( logCombiners )664{665DisplaySimpleMuxString();666}667#endif668669return m_lastIndex;670}671672673#ifdef DEBUGGER674extern const char *translatedCombTypes[];675void COGLColorCombiner4::DisplaySimpleMuxString(void)676{677char buf0[30], buf1[30], buf2[30];678OGLExtCombinerSaveType &result = m_vCompiledSettings[m_lastIndex];679680COGLColorCombiner::DisplaySimpleMuxString();681DebuggerAppendMsg("OpenGL 1.2: %d Stages", result.numOfUnits);682for( int i=0; i<result.numOfUnits; i++ )683{684DebuggerAppendMsg("//aRGB%d:\t%s: %s, %s, %s\n", i,GetOpStr(result.units[i].rgbOp), DecodedMux::FormatStr(result.units[i].rgbArg0,buf0), DecodedMux::FormatStr(result.units[i].rgbArg1,buf1), DecodedMux::FormatStr(result.units[i].rgbArg2,buf2));685DebuggerAppendMsg("//aAlpha%d:\t%s: %s, %s, %s\n", i,GetOpStr(result.units[i].alphaOp), DecodedMux::FormatStr(result.units[i].alphaArg0,buf0), DecodedMux::FormatStr(result.units[i].alphaArg1,buf1), DecodedMux::FormatStr(result.units[i].alphaArg2,buf2));686}687TRACE0("\n\n");688}689void COGLColorCombiner2::DisplaySimpleMuxString(void)690{691char buf0[30], buf1[30], buf2[30];692OGLExtCombinerSaveType &result = m_vCompiledSettings[m_lastIndex];693694COGLColorCombiner::DisplaySimpleMuxString();695int generalCombinerIndex = CGeneralCombiner::FindCompiledMux();696if( generalCombinerIndex < 0 ) // Can not found697{698generalCombinerIndex = CGeneralCombiner::ParseDecodedMux();699}700DebuggerAppendMsg("Generated general combiners:");701GeneralCombinerInfo &generalRes = m_vCompiledCombinerStages[generalCombinerIndex];702General_DisplayBlendingStageInfo(generalRes);703704DebuggerAppendMsg("OpenGL 1.2: %d Stages", result.numOfUnits);705for( int i=0; i<result.numOfUnits; i++ )706{707DebuggerAppendMsg("//aRGB%d:\t%s: %s, %s, %s\n", i,GetOpStr(result.units[i].rgbOp), DecodedMux::FormatStr(result.units[i].rgbArg0,buf0), DecodedMux::FormatStr(result.units[i].rgbArg1,buf1), DecodedMux::FormatStr(result.units[i].rgbArg2,buf2));708DebuggerAppendMsg("//aAlpha%d:\t%s: %s, %s, %s\n", i,GetOpStr(result.units[i].alphaOp), DecodedMux::FormatStr(result.units[i].alphaArg0,buf0), DecodedMux::FormatStr(result.units[i].alphaArg1,buf1), DecodedMux::FormatStr(result.units[i].alphaArg2,buf2));709}710TRACE0("\n\n");711}712#endif713714715//////////////////////////////////////////////////////////////////////////716int COGLColorCombiner4::FindCompiledMux()717{718#ifdef DEBUGGER719if( debuggerDropCombiners )720{721m_vCompiledSettings.clear();722//m_dwLastMux0 = m_dwLastMux1 = 0;723debuggerDropCombiners = false;724}725#endif726for( uint32 i=0; i<m_vCompiledSettings.size(); i++ )727{728if( m_vCompiledSettings[i].dwMux0 == m_pDecodedMux->m_dwMux0 && m_vCompiledSettings[i].dwMux1 == m_pDecodedMux->m_dwMux1 )729return (int)i;730}731732return -1;733}734735//========================================================================736737GLint COGLColorCombiner4::RGBArgsMap4[] =738{739#if SDL_VIDEO_OPENGL740GL_PRIMARY_COLOR_ARB, //MUX_0741GL_PRIMARY_COLOR_ARB, //MUX_1742GL_PREVIOUS_ARB, //MUX_COMBINED,743#endif744GL_TEXTURE0_ARB, //MUX_TEXEL0,745#if SDL_VIDEO_OPENGL746GL_TEXTURE1_ARB, //MUX_TEXEL1,747GL_CONSTANT_ARB, //MUX_PRIM,748GL_PRIMARY_COLOR_ARB, //MUX_SHADE,749GL_CONSTANT_ARB, //MUX_ENV,750GL_PREVIOUS_ARB, //MUX_COMBALPHA,751#endif752GL_TEXTURE0_ARB, //MUX_T0_ALPHA,753#if SDL_VIDEO_OPENGL754GL_TEXTURE1_ARB, //MUX_T1_ALPHA,755GL_CONSTANT_ARB, //MUX_PRIM_ALPHA,756GL_PRIMARY_COLOR_ARB, //MUX_SHADE_ALPHA,757GL_CONSTANT_ARB, //MUX_ENV_ALPHA,758GL_CONSTANT_ARB, //MUX_LODFRAC,759GL_CONSTANT_ARB, //MUX_PRIMLODFRAC,760GL_PRIMARY_COLOR_ARB, //MUX_K5761GL_PRIMARY_COLOR_ARB //MUX_UNK762#endif763};764765GLint COGLColorCombiner4v2::RGBArgsMap4v2[] =766{767#if SDL_VIDEO_OPENGL768GL_PRIMARY_COLOR_ARB, //MUX_0769GL_PRIMARY_COLOR_ARB, //MUX_1770GL_PREVIOUS_ARB, //MUX_COMBINED,771#endif772GL_TEXTURE0_ARB, //MUX_TEXEL0,773#if SDL_VIDEO_OPENGL774GL_TEXTURE1_ARB, //MUX_TEXEL1,775GL_CONSTANT_ARB, //MUX_PRIM,776GL_PRIMARY_COLOR_ARB, //MUX_SHADE,777GL_TEXTURE2_ARB, //MUX_ENV,778//{GL_TEXTURE1_ARB, }, //MUX_ENV,779GL_PREVIOUS_ARB, //MUX_COMBALPHA,780GL_TEXTURE0_ARB, //MUX_T0_ALPHA,781GL_TEXTURE1_ARB, //MUX_T1_ALPHA,782GL_CONSTANT_ARB, //MUX_PRIM_ALPHA,783GL_PRIMARY_COLOR_ARB, //MUX_SHADE_ALPHA,784GL_TEXTURE2_ARB, //MUX_ENV_ALPHA,785//{GL_TEXTURE1_ARB, }, //MUX_ENV_ALPHA,786//{GL_TEXTURE3_ARB, }, //MUX_LODFRAC,787//{GL_TEXTURE3_ARB, }, //MUX_PRIMLODFRAC,788GL_TEXTURE1_ARB, //MUX_LODFRAC,789GL_TEXTURE1_ARB, //MUX_PRIMLODFRAC,790GL_PRIMARY_COLOR_ARB, //MUX_K5791GL_PRIMARY_COLOR_ARB //MUX_UNK792#endif793};794795GLint COGLColorCombiner2::RGBArgsMap2[] =796{797#if SDL_VIDEO_OPENGL798GL_PRIMARY_COLOR_ARB, //MUX_0799GL_PRIMARY_COLOR_ARB, //MUX_1800GL_PREVIOUS_ARB, //MUX_COMBINED,801//{GL_TEXTURE, }, //MUX_TEXEL0,802//{GL_TEXTURE, }, //MUX_TEXEL1,803#endif804GL_TEXTURE0_ARB, //MUX_TEXEL0,805#if SDL_VIDEO_OPENGL806GL_TEXTURE1_ARB, //MUX_TEXEL1,807GL_CONSTANT_ARB, //MUX_PRIM,808GL_PRIMARY_COLOR_ARB, //MUX_SHADE,809GL_CONSTANT_ARB, //MUX_ENV,810GL_PREVIOUS_ARB, //MUX_COMBALPHA,811//{GL_TEXTURE, }, //MUX_T0_ALPHA,812//{GL_TEXTURE, }, //MUX_T1_ALPHA,813GL_TEXTURE0_ARB, //MUX_TEXEL0,814GL_TEXTURE1_ARB, //MUX_TEXEL1,815GL_CONSTANT_ARB, //MUX_PRIM_ALPHA,816GL_PRIMARY_COLOR_ARB, //MUX_SHADE_ALPHA,817GL_CONSTANT_ARB, //MUX_ENV_ALPHA,818GL_CONSTANT_ARB, //MUX_LODFRAC,819GL_CONSTANT_ARB, //MUX_PRIMLODFRAC,820GL_PRIMARY_COLOR_ARB, //MUX_K5821GL_PRIMARY_COLOR_ARB //MUX_UNK822#endif823};824825//========================================================================826827GLint COGLColorCombiner4::MapRGBArgs(uint8 arg)828{829return RGBArgsMap4[arg&MUX_MASK];830}831832GLint COGLColorCombiner4v2::MapRGBArgs(uint8 arg)833{834return RGBArgsMap4v2[arg&MUX_MASK];835}836837GLint COGLColorCombiner2::MapRGBArgs(uint8 arg)838{839return RGBArgsMap2[arg&MUX_MASK];840}841842GLint COGLColorCombiner4::MapRGBArgFlags(uint8 arg)843{844if( (arg & MUX_ALPHAREPLICATE) && (arg & MUX_COMPLEMENT) )845{846return GL_ONE_MINUS_SRC_ALPHA;847}848else if( (arg & MUX_ALPHAREPLICATE) )849{850return GL_SRC_ALPHA;851}852else if(arg & MUX_COMPLEMENT)853{854return GL_ONE_MINUS_SRC_COLOR;855}856else857return GL_SRC_COLOR;858}859860GLint COGLColorCombiner4::MapAlphaArgs(uint8 arg)861{862return RGBArgsMap4[arg&MUX_MASK];863}864865GLint COGLColorCombiner4v2::MapAlphaArgs(uint8 arg)866{867return RGBArgsMap4v2[arg&MUX_MASK];868}869870GLint COGLColorCombiner2::MapAlphaArgs(uint8 arg)871{872return RGBArgsMap2[arg&MUX_MASK];873}874875GLint COGLColorCombiner4::MapAlphaArgFlags(uint8 arg)876{877if(arg & MUX_COMPLEMENT)878{879return GL_ONE_MINUS_SRC_ALPHA;880}881else882return GL_SRC_ALPHA;883}884885//========================================================================886887void ApplyFor1Unit(OGLExtCombinerType &unit)888{889#if SDL_VIDEO_OPENGL890glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit.rgbOp);891OPENGL_CHECK_ERRORS;892893if( unit.rgbArg0 != CM_IGNORE_BYTE )894{895glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, (unit.rgbArg0gl));896OPENGL_CHECK_ERRORS;897glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, (unit.rgbFlag0gl));898OPENGL_CHECK_ERRORS;899}900901if( unit.rgbArg1 != CM_IGNORE_BYTE )902{903glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, (unit.rgbArg1gl));904OPENGL_CHECK_ERRORS;905glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, (unit.rgbFlag1gl));906OPENGL_CHECK_ERRORS;907}908909if( unit.rgbArg2 != CM_IGNORE_BYTE )910{911glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, (unit.rgbArg2gl));912OPENGL_CHECK_ERRORS;913glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, (unit.rgbFlag2gl));914OPENGL_CHECK_ERRORS;915}916917if( unit.alphaArg0 != CM_IGNORE_BYTE )918{919glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, (unit.alphaArg0gl));920OPENGL_CHECK_ERRORS;921glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, (unit.alphaFlag0gl));922OPENGL_CHECK_ERRORS;923}924925if( unit.alphaArg1 != CM_IGNORE_BYTE )926{927glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, (unit.alphaArg1gl));928OPENGL_CHECK_ERRORS;929glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, (unit.alphaFlag1gl));930OPENGL_CHECK_ERRORS;931}932933if( unit.alphaArg2 != CM_IGNORE_BYTE )934{935glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, (unit.alphaArg2gl));936OPENGL_CHECK_ERRORS;937glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, (unit.alphaFlag2gl));938OPENGL_CHECK_ERRORS;939}940#endif941}942943//////////////////////////////////////////////////////////////////////////944945void COGLColorCombiner4::GenerateCombinerSetting(int index)946{947OGLExtCombinerSaveType &res = m_vCompiledSettings[index];948949// Texture unit 0950COGLTexture* pTexture = NULL;951COGLTexture* pTexture1 = NULL;952953if( m_bTex0Enabled || m_bTex1Enabled || gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY )954{955if( m_bTex0Enabled || gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY )956{957pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;958if( pTexture ) m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);959}960if( m_bTex1Enabled )961{962pTexture1 = g_textures[(gRSP.curTile+1)&7].m_pCOGLTexture;963if( pTexture1 ) m_pOGLRender->BindTexture(pTexture1->m_dwTextureName, 1);964}965}966967968969for( int i=0; i<res.numOfUnits; i++ )970{971pglActiveTexture(GL_TEXTURE0_ARB+i);972OPENGL_CHECK_ERRORS;973m_pOGLRender->EnableTexUnit(i,TRUE);974glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);975OPENGL_CHECK_ERRORS;976ApplyFor1Unit(res.units[i]);977}978979if( res.numOfUnits < m_maxTexUnits )980{981for( int i=res.numOfUnits; i<m_maxTexUnits; i++ )982{983pglActiveTexture(GL_TEXTURE0_ARB+i);984OPENGL_CHECK_ERRORS;985m_pOGLRender->DisBindTexture(0, i);986m_pOGLRender->EnableTexUnit(i,FALSE);987}988}989}990991992void COGLColorCombiner4::GenerateCombinerSettingConstants(int index)993{994OGLExtCombinerSaveType &res = m_vCompiledSettings[index];995996float *fv;997float tempf[4];998999bool isused = true;10001001if( res.primIsUsed )1002{1003fv = GetPrimitiveColorfv(); // CONSTANT COLOR1004}1005else if( res.envIsUsed )1006{1007fv = GetEnvColorfv(); // CONSTANT COLOR1008}1009else if( res.lodFracIsUsed )1010{1011float frac = gRDP.LODFrac / 255.0f;1012tempf[0] = tempf[1] = tempf[2] = tempf[3] = frac;1013fv = &tempf[0];1014}1015else1016{1017isused = false;1018}10191020if( isused )1021{1022for( int i=0; i<res.numOfUnits; i++ )1023{1024pglActiveTexture(GL_TEXTURE0_ARB+i);1025OPENGL_CHECK_ERRORS;1026glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv);1027OPENGL_CHECK_ERRORS;1028}1029}1030}103110321033void COGLColorCombiner4v2::GenerateCombinerSettingConstants(int index)1034{1035//COGLColorCombiner4::GenerateCombinerSettingConstants(index);1036//return;10371038OGLExtCombinerSaveType &res = m_vCompiledSettings[index];1039COGLExtRender *prender = (COGLExtRender *)m_pRender;10401041if( res.primIsUsed )1042{1043float *fv = GetPrimitiveColorfv(); // CONSTANT COLOR1044for( int i=0; i<res.numOfUnits; i++ )1045{1046pglActiveTexture(GL_TEXTURE0_ARB+i);1047OPENGL_CHECK_ERRORS;1048glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv);1049OPENGL_CHECK_ERRORS;1050}1051}10521053if( res.envIsUsed )1054{1055// Set Texture unit 2 to ENV1056pglActiveTexture(GL_TEXTURE2_ARB);1057OPENGL_CHECK_ERRORS;1058prender->EnableTexUnit(2,TRUE);1059TxtrCacheEntry *pEntry = gTextureManager.GetConstantColorTexture(MUX_ENV);1060prender->SetCurrentTexture( (gRSP.curTile+2)%7, pEntry->pTexture, 4, 4, pEntry);1061prender->SetTexelRepeatFlags((gRSP.curTile+2)%7);1062}10631064if( res.lodFracIsUsed)1065{1066int unit = 3;1067if( !res.envIsUsed )1068unit = 2;10691070// Set Texture unit 3 to LODFRAC1071pglActiveTexture(GL_TEXTURE0_ARB+unit);1072OPENGL_CHECK_ERRORS;1073prender->EnableTexUnit(unit,TRUE);1074TxtrCacheEntry *pEntry = gTextureManager.GetConstantColorTexture(MUX_LODFRAC);1075prender->SetCurrentTexture( (gRSP.curTile+unit)%7, pEntry->pTexture, 4, 4, pEntry);1076prender->SetTexelRepeatFlags((gRSP.curTile+unit)%7);1077}1078else1079{1080int unit = 3;1081if( !res.envIsUsed )1082unit = 2;10831084// Disable texture unit 31085pglActiveTexture(GL_TEXTURE0_ARB+unit);1086OPENGL_CHECK_ERRORS;1087prender->EnableTexUnit(unit,FALSE);1088prender->SetTextureToTextureUnitMap(-1,unit);1089}1090}109110921093GLenum GeneralToGLMaps[]=1094{1095GL_REPLACE, //CM_REPLACE,1096#if SDL_VIDEO_OPENGL1097GL_MODULATE, //CM_MODULATE,1098GL_ADD, //CM_ADD,1099GL_SUBTRACT_ARB, //CM_SUBTRACT,1100GL_INTERPOLATE_ARB, //CM_INTERPOLATE,1101GL_INTERPOLATE_ARB, //CM_ADDSMOOTH,1102GL_INTERPOLATE_ARB, //CM_BLENDCURRENTALPHA1103GL_INTERPOLATE_ARB, //CM_BLENDDIFFUSEALPHA1104GL_INTERPOLATE_ARB, //CM_BLENDFACTORALPHA,1105GL_INTERPOLATE_ARB, //CM_BLENDTEXTUREALPHA1106#endif1107GL_MODULATE_ADD_ATI, //CM_MULTIPLYADD,1108};110911101111//////////////////////////////////////////////////////////////////////////1112int COGLColorCombiner2::ParseDecodedMux()1113{1114//return COGLColorCombiner4::ParseDecodedMux();11151116int generalCombinerIndex = CGeneralCombiner::FindCompiledMux();1117if( generalCombinerIndex < 0 ) // Can not found1118{1119generalCombinerIndex = CGeneralCombiner::ParseDecodedMux();1120}11211122GeneralCombinerInfo &generalRes = m_vCompiledCombinerStages[generalCombinerIndex];1123OGLExtCombinerSaveType res;11241125// Convert generalRes to OGLExtCombinerSaveType1126for( int unitNo=0; unitNo<generalRes.nStages; unitNo++ )1127{1128OGLExtCombinerType &unit = res.units[unitNo];1129//OGLExt1CombType &colorComb = unit.Combs[0];1130//OGLExt1CombType &alphaComb = unit.Combs[1];11311132unit.rgbArg0 = (uint8)generalRes.stages[unitNo].colorOp.Arg1;1133unit.rgbArg1 = (uint8)generalRes.stages[unitNo].colorOp.Arg2;1134unit.rgbArg2 = (uint8)generalRes.stages[unitNo].colorOp.Arg0;1135unit.alphaArg0 = (uint8)generalRes.stages[unitNo].alphaOp.Arg1;1136unit.alphaArg1 = (uint8)generalRes.stages[unitNo].alphaOp.Arg2;1137unit.alphaArg2 = (uint8)generalRes.stages[unitNo].alphaOp.Arg0;11381139unit.rgbOp = GeneralToGLMaps[generalRes.stages[unitNo].colorOp.op];1140if( unit.rgbOp == GL_MODULATE_ADD_ATI && !m_bTxtOpMulAdd )1141{1142if( (unit.rgbArg0&MUX_MASK) == (unit.rgbArg2&MUX_MASK) && (unit.rgbArg0&MUX_COMPLEMENT) )1143{1144unit.rgbOp = GL_ADD;1145unit.rgbArg0 &= ~MUX_COMPLEMENT;1146}1147else1148{1149unit.rgbOp = GL_MODULATE;1150}1151}1152unit.alphaOp = GeneralToGLMaps[generalRes.stages[unitNo].alphaOp.op];1153if( unit.alphaOp == GL_MODULATE_ADD_ATI && !m_bTxtOpMulAdd )1154{1155if( (unit.alphaArg0&MUX_MASK) == (unit.alphaArg2&MUX_MASK) && (unit.alphaArg0&MUX_COMPLEMENT) )1156{1157unit.alphaOp = GL_ADD;1158unit.alphaArg0 &= ~MUX_COMPLEMENT;1159}1160else1161{1162unit.alphaOp = GL_MODULATE;1163}1164}11651166unit.tex = generalRes.stages[unitNo].dwTexture;1167unit.textureIsUsed = generalRes.stages[unitNo].bTextureUsed;1168}11691170res.numOfUnits = generalRes.nStages;1171res.constantColor = generalRes.TFactor;1172return SaveParsedResult(res);1173}117411751176void COGLColorCombiner2::GenerateCombinerSettingConstants(int index)1177{1178OGLExtCombinerSaveType &res = m_vCompiledSettings[index];11791180bool isused = true;11811182float *fv;1183float tempf[4];11841185if( res.primIsUsed )1186{1187fv = GetPrimitiveColorfv(); // CONSTANT COLOR1188}1189else if( res.envIsUsed )1190{1191fv = GetEnvColorfv(); // CONSTANT COLOR1192}1193else if( res.lodFracIsUsed )1194{1195float frac = gRDP.LODFrac / 255.0f;1196tempf[0] = tempf[1] = tempf[2] = tempf[3] = frac;1197fv = &tempf[0];1198}1199else1200{1201isused = false;1202}12031204if( isused )1205{1206for( int i=0; i<res.numOfUnits; i++ )1207{1208pglActiveTextureARB(GL_TEXTURE0_ARB+i);1209OPENGL_CHECK_ERRORS;1210glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv);1211OPENGL_CHECK_ERRORS;1212}1213}1214}1215void COGLColorCombiner2::GenerateCombinerSetting(int index)1216{1217OGLExtCombinerSaveType &res = m_vCompiledSettings[index];1218COGLExtRender *prender = (COGLExtRender *)m_pRender;12191220for( int i=0; i<res.numOfUnits; i++ )1221{1222pglActiveTextureARB(GL_TEXTURE0_ARB+i);1223OPENGL_CHECK_ERRORS;1224//if(res.units[i].textureIsUsed)1225{1226prender->SetTextureToTextureUnitMap(res.units[i].tex,i);1227m_pOGLRender->EnableTexUnit(i,TRUE);1228COGLTexture* pTexture = g_textures[(gRSP.curTile+res.units[i].tex)&7].m_pCOGLTexture;1229if( pTexture ) m_pOGLRender->BindTexture(pTexture->m_dwTextureName, i);1230}1231/*1232else1233{1234m_pOGLRender->EnableTexUnit(i,TRUE);1235prender->SetTextureToTextureUnitMap(-1,i);1236//m_pOGLRender->EnableTexUnit(i,FALSE);1237//m_pOGLRender->DisBindTexture(0, i);1238}1239*/12401241glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);1242OPENGL_CHECK_ERRORS;1243ApplyFor1Unit(res.units[i]);1244}12451246if( res.numOfUnits < m_maxTexUnits )1247{1248for( int i=res.numOfUnits; i<m_maxTexUnits; i++ )1249{1250pglActiveTextureARB(GL_TEXTURE0_ARB+i);1251OPENGL_CHECK_ERRORS;1252m_pOGLRender->EnableTexUnit(i,FALSE);1253prender->SetTextureToTextureUnitMap(-1,i);1254}1255}1256}1257125812591260