X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=source%2Frice_gles%2Fsrc%2FOGLFragmentShaders.cpp;fp=source%2Frice_gles%2Fsrc%2FOGLFragmentShaders.cpp;h=8c38ba63194263104bde0ec46456377bb64f4934;hb=d07c171fa694cae985ad7045f9ce2b2f1a5699b4;hp=0000000000000000000000000000000000000000;hpb=ca22e7b76883b946060a6b40bb8709c1981e1cf6;p=mupen64plus-pandora.git diff --git a/source/rice_gles/src/OGLFragmentShaders.cpp b/source/rice_gles/src/OGLFragmentShaders.cpp new file mode 100644 index 0000000..8c38ba6 --- /dev/null +++ b/source/rice_gles/src/OGLFragmentShaders.cpp @@ -0,0 +1,487 @@ +/* +Copyright (C) 2003 Rice1964 + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "OGLExtensions.h" +#include "OGLDebug.h" +#include "OGLFragmentShaders.h" +#include "OGLRender.h" +#include "OGLGraphicsContext.h" + +COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender) +: COGLColorCombiner(pRender) +{ + m_bShaderIsSupported = false; +} +COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner() +{ +} + +bool COGLFragmentShaderCombiner::Initialize(void) +{ + if( !COGLColorCombiner::Initialize() ) + return false; + + COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext); + if( pcontext->IsExtensionSupported("GL_ARB_fragment_shader") ) + { + m_bShaderIsSupported = true; + } + + return true; +} + +void COGLFragmentShaderCombiner::InitCombinerCycle12(void) +{ +} +void COGLFragmentShaderCombiner::DisableCombiner(void) +{ + COGLColorCombiner::DisableCombiner(); +} + +void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void) +{ + COGLColorCombiner::InitCombinerCycleCopy(); +} + +void COGLFragmentShaderCombiner::InitCombinerCycleFill(void) +{ + COGLColorCombiner::InitCombinerCycleFill(); +} +void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile) +{ + COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile); +} + +#ifdef DEBUGGER +void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void) +{ + COGLColorCombiner::DisplaySimpleMuxString(); +} +#endif + + + +COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender) +: COGLColorCombiner4(pRender) +{ + delete m_pDecodedMux; + m_pDecodedMux = new DecodedMuxForPixelShader; + m_bFragmentProgramIsSupported = false; +} +COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner() +{ + int size = m_vCompiledShaders.size(); + for (int i=0; iIsExtensionSupported("GL_ARB_fragment_program") ) + { + m_bFragmentProgramIsSupported = true; + } + + return true; +} + + + +void COGL_FragmentProgramCombiner::DisableCombiner(void) +{ + glDisable(GL_FRAGMENT_PROGRAM_ARB); + OPENGL_CHECK_ERRORS; + COGLColorCombiner4::DisableCombiner(); +} + +void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void) +{ + glDisable(GL_FRAGMENT_PROGRAM_ARB); + OPENGL_CHECK_ERRORS; + COGLColorCombiner4::InitCombinerCycleCopy(); +} + +void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void) +{ + glDisable(GL_FRAGMENT_PROGRAM_ARB); + OPENGL_CHECK_ERRORS; + COGLColorCombiner4::InitCombinerCycleFill(); +} + +const char *muxToFP_Maps[][2] = { +//color -- alpha +{"0", "0"}, //MUX_0 = 0, +{"1", "1"}, //MUX_1, +{"comb", "comb.a"}, //MUX_COMBINED, +{"t0", "t0.a"}, //MUX_TEXEL0, +{"t1", "t1.a"}, //MUX_TEXEL1, +{"program.env[2]", "program.env[2].a"}, //MUX_PRIM, +{"fragment.color", "fragment.color.a"}, //MUX_SHADE, +{"program.env[1]", "program.env[1].a"}, //MUX_ENV, +{"comb.a", "comb.a"}, //MUX_COMBALPHA, +{"t0.a", "t0.a"}, //MUX_T0_ALPHA, +{"t1.a", "t1.a"}, //MUX_T1_ALPHA, +{"primcolor.a", "primcolor.a"}, //MUX_PRIM_ALPHA, +{"fragment.color.a", "fragment.color.a"}, //MUX_SHADE_ALPHA, +{"envcolor.a", "envcolor.a"}, //MUX_ENV_ALPHA, +{"program.env[3]", "program.env[3]"}, //MUX_LODFRAC, +{"program.env[4]", "program.env[4]"}, //MUX_PRIMLODFRAC, +{"1", "1"}, //MUX_K5, +{"1", "1"}, //MUX_UNK, // Should not be used +}; + + +const char *oglFPTest = +"!!ARBfp1.0\n" +"#Declarations\n" +"TEMP t0;\n" +"TEMP t1;\n" +"TEMP comb;\n" +"TEMP comb2;\n" +"\n" +"ATTRIB coord0 = fragment.texcoord[0];\n" +"ATTRIB coord1 = fragment.texcoord[1];\n" +"ATTRIB shade = fragment.color;\n" +"ATTRIB fogfactor = fragment.fogcoord;\n" +"\n" +"OUTPUT out = result.color;\n" +"\n" +"#Instructions\n" +"TEX t0, coord0, texture[0], 2D;\n" +"TEX t1, coord1, texture[1], 2D;\n" +"\n" +"MAD_SAT out, t0, program.env[1],program.env[0];\n" +//"SUB comb.rgb, t0, 0;\n" +//"MAD_SAT out.rgb, comb, program.env[1], 0;\n" +//"SUB comb.a, t0, 0;\n" +//"MAD_SAT out.a, comb, program.env[1], 0;\n" +"END\n"; + +char oglNewFP[4092]; + +char* MuxToOC(uint8 val) +{ +// For color channel +if( val&MUX_ALPHAREPLICATE ) + return (char*)muxToFP_Maps[val&0x1F][1]; +else + return (char*)muxToFP_Maps[val&0x1F][0]; +} + +char* MuxToOA(uint8 val) +{ +// For alpha channel +return (char*)muxToFP_Maps[val&0x1F][0]; +} + +static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1) +{ + MuxVar &= 0x1f; + if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA) + bNeedT0 = true; + if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA) + bNeedT1 = true; +} + +void COGL_FragmentProgramCombiner::GenerateProgramStr() +{ + DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; + + mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED; + m_pDecodedMux->Reformat(false); + + char tempstr[500], newFPBody[4092]; + bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false; + newFPBody[0] = 0; + + for( int cycle=0; cycle<2; cycle++ ) + { + for( int channel=0; channel<2; channel++) + { + char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA; + char *dst = channel==0?(char*)"rgb":(char*)"a"; + N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel]; + switch( mux.splitType[cycle*2+channel] ) + { + case CM_FMT_TYPE_NOT_USED: + tempstr[0] = 0; + break; + case CM_FMT_TYPE_D: + sprintf(tempstr, "MOV comb.%s, %s;\n", dst, func(m.d)); + CheckFpVars(m.d, bNeedT0, bNeedT1); + break; + case CM_FMT_TYPE_A_MOD_C: + sprintf(tempstr, "MUL comb.%s, %s, %s;\n", dst, func(m.a), func(m.c)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.c, bNeedT0, bNeedT1); + break; + case CM_FMT_TYPE_A_ADD_D: + sprintf(tempstr, "ADD_SAT comb.%s, %s, %s;\n", dst, func(m.a), func(m.d)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.d, bNeedT0, bNeedT1); + break; + case CM_FMT_TYPE_A_SUB_B: + sprintf(tempstr, "SUB comb.%s, %s, %s;\n", dst, func(m.a), func(m.b)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.b, bNeedT0, bNeedT1); + break; + case CM_FMT_TYPE_A_MOD_C_ADD_D: + sprintf(tempstr, "MAD_SAT comb.%s, %s, %s, %s;\n", dst, func(m.a), func(m.c), func(m.d)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.c, bNeedT0, bNeedT1); + CheckFpVars(m.d, bNeedT0, bNeedT1); + break; + case CM_FMT_TYPE_A_LERP_B_C: + sprintf(tempstr, "LRP_SAT comb.%s, %s, %s, %s;\n", dst, func(m.c), func(m.a), func(m.b)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.b, bNeedT0, bNeedT1); + CheckFpVars(m.c, bNeedT0, bNeedT1); + //sprintf(tempstr, "SUB comb.%s, %s, %s;\nMAD_SAT comb.%s, comb, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.b)); + break; + default: + sprintf(tempstr, "SUB comb2.%s, %s, %s;\nMAD_SAT comb.%s, comb2, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.d)); + CheckFpVars(m.a, bNeedT0, bNeedT1); + CheckFpVars(m.b, bNeedT0, bNeedT1); + CheckFpVars(m.c, bNeedT0, bNeedT1); + CheckFpVars(m.d, bNeedT0, bNeedT1); + bNeedComb2 = true; + break; + } + strcat(newFPBody, tempstr); + } + } + + strcpy(oglNewFP, "!!ARBfp1.0\n"); + strcat(oglNewFP, "#Declarations\n"); + if (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) + strcat(oglNewFP, "OPTION ARB_fog_linear;\n"); + if (bNeedT0) + strcat(oglNewFP, "TEMP t0;\n"); + if (bNeedT1) + strcat(oglNewFP, "TEMP t1;\n"); + strcat(oglNewFP, "TEMP comb;\n"); + if (bNeedComb2) + strcat(oglNewFP, "TEMP comb2;\n"); + strcat(oglNewFP, "#Instructions\n"); + if (bNeedT0) + strcat(oglNewFP, "TEX t0, fragment.texcoord[0], texture[0], 2D;\n"); + if (bNeedT1) + strcat(oglNewFP, "TEX t1, fragment.texcoord[1], texture[1], 2D;\n"); + strcat(oglNewFP, "# N64 cycle 1, result is in comb\n"); + + strcat(oglNewFP, newFPBody); + + strcat(oglNewFP, "MOV result.color, comb;\n"); + strcat(oglNewFP, "END\n\n"); +} + +int COGL_FragmentProgramCombiner::ParseDecodedMux() +{ + if( !m_bFragmentProgramIsSupported ) + return COGLColorCombiner4::ParseDecodedMux(); + + OGLShaderCombinerSaveType res; + + pglGenProgramsARB( 1, &res.programID); + OPENGL_CHECK_ERRORS; + pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, res.programID); + OPENGL_CHECK_ERRORS; + GenerateProgramStr(); + + pglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglNewFP), oglNewFP); + OPENGL_CHECK_ERRORS; + //pglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglFPTest), oglFPTest); + + if (glGetError() != 0) + { + GLint position; +#ifdef DEBUGGER + char *str = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); +#endif + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &position); + if( position >= 0 ) + { +#ifdef DEBUGGER + if( m_lastIndex >= 0 ) COGLColorCombiner4::DisplaySimpleMuxString(); + DebugMessage(M64MSG_ERROR, "%s - %s", str, oglNewFP+position); +#endif + glDisable(GL_FRAGMENT_PROGRAM_ARB); + return COGLColorCombiner4::ParseDecodedMux(); + } + } + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + OPENGL_CHECK_ERRORS; + res.dwMux0 = m_pDecodedMux->m_dwMux0; + res.dwMux1 = m_pDecodedMux->m_dwMux1; + res.fogIsUsed = gRDP.bFogEnableInBlender && gRSP.bFogEnabled; + + m_vCompiledShaders.push_back(res); + m_lastIndex = m_vCompiledShaders.size()-1; + + return m_lastIndex; +} + +void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index) +{ + GLuint ID = m_vCompiledShaders[index].programID; + pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ID ); + OPENGL_CHECK_ERRORS; + glEnable(GL_FRAGMENT_PROGRAM_ARB); + OPENGL_CHECK_ERRORS; +} + +void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index) +{ + float *pf; + pf = GetEnvColorfv(); + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, pf); + OPENGL_CHECK_ERRORS; + pf = GetPrimitiveColorfv(); + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2, pf); + OPENGL_CHECK_ERRORS; + + float frac = gRDP.LODFrac / 255.0f; + float tempf[4] = {frac,frac,frac,frac}; + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 3, tempf); + OPENGL_CHECK_ERRORS; + + float frac2 = gRDP.primLODFrac / 255.0f; + float tempf2[4] = {frac2,frac2,frac2,frac2}; + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 4, tempf2); + OPENGL_CHECK_ERRORS; + + float tempf3[4] = {0,0,0,0}; + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, tempf3); + OPENGL_CHECK_ERRORS; + pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 6, tempf3); + OPENGL_CHECK_ERRORS; +} + +int COGL_FragmentProgramCombiner::FindCompiledMux() +{ +#ifdef DEBUGGER + if( debuggerDropCombiners ) + { + m_vCompiledShaders.clear(); + //m_dwLastMux0 = m_dwLastMux1 = 0; + debuggerDropCombiners = false; + } +#endif + for( uint32 i=0; im_dwMux0 + && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 + && m_vCompiledShaders[i].fogIsUsed == (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) ) + return (int)i; + } + + return -1; +} + +////////////////////////////////////////////////////////////////////////// +void COGL_FragmentProgramCombiner::InitCombinerCycle12(void) +{ + if( !m_bFragmentProgramIsSupported ) + { + COGLColorCombiner4::InitCombinerCycle12(); + return; + } + +#ifdef DEBUGGER + if( debuggerDropCombiners ) + { + UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1); + m_vCompiledShaders.clear(); + m_dwLastMux0 = m_dwLastMux1 = 0; + debuggerDropCombiners = false; + } +#endif + + m_pOGLRender->EnableMultiTexture(); + + bool combinerIsChanged = false; + + if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 ) + { + combinerIsChanged = true; + m_lastIndex = FindCompiledMux(); + if( m_lastIndex < 0 ) // Can not found + { + m_lastIndex = ParseDecodedMux(); + } + + m_dwLastMux0 = m_pDecodedMux->m_dwMux0; + m_dwLastMux1 = m_pDecodedMux->m_dwMux1; + } + + + GenerateCombinerSettingConstants(m_lastIndex); + if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded ) + { + if( m_bCycleChanged || combinerIsChanged ) + { + GenerateCombinerSettingConstants(m_lastIndex); + GenerateCombinerSetting(m_lastIndex); + } + else if( gRDP.colorsAreReloaded ) + { + GenerateCombinerSettingConstants(m_lastIndex); + } + + m_pOGLRender->SetAllTexelRepeatFlag(); + + gRDP.colorsAreReloaded = false; + gRDP.texturesAreReloaded = false; + } + else + { + m_pOGLRender->SetAllTexelRepeatFlag(); + } +} + +#ifdef DEBUGGER +void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void) +{ + COGLColorCombiner::DisplaySimpleMuxString(); + DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; + mux.Reformat(false); + GenerateProgramStr(); + //sprintf(oglNewFP, oglFP, + // MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0), + // MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0), + // MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1), + // MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1) + // ); + + TRACE0("OGL Fragment Program:"); + TRACE0(oglNewFP); +} +#endif +