From b65f18fa84ab60d3636d8892c1122ad523ba4fab Mon Sep 17 00:00:00 2001 From: OV2 Date: Thu, 24 Feb 2011 01:26:42 +0100 Subject: [PATCH] Win32: add preliminary CG shader support (D3D + OGL) CG shaders can be found in the ps3 snes9x port. Some of them will not work correctly with all internal filter modes. --- win32/CDirect3D.cpp | 202 +++++++++++++++++++++++++++++++--------- win32/CDirect3D.h | 11 ++- win32/COpenGL.cpp | 148 ++++++++++++++++++++--------- win32/COpenGL.h | 17 +++- win32/rsrc/snes9x.rc | 4 +- win32/wconfig.cpp | 4 +- win32/win32_display.cpp | 25 +++++ win32/win32_display.h | 1 + win32/wsnes9x.cpp | 28 +++--- win32/wsnes9x.h | 4 +- 10 files changed, 334 insertions(+), 110 deletions(-) diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index e60a2bc9..6e418df9 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -178,6 +178,9 @@ #pragma comment( lib, "d3dx9" ) #pragma comment( lib, "DxErr" ) +#pragma comment( lib, "cg.lib" ) +#pragma comment( lib, "cgd3d9.lib" ) + #include "cdirect3d.h" #include "win32_display.h" #include "../snes9x.h" @@ -216,10 +219,12 @@ CDirect3D::CDirect3D() rubyLUT[i] = NULL; } effect=NULL; - shader_compiled=false; + shader_type = D3D_SHADER_NONE; shaderTimer = 1.0f; shaderTimeStart = 0; shaderTimeElapsed = 0; + cgContext = NULL; + cgVertexProgram = cgFragmentProgram = NULL; } /* CDirect3D::~CDirect3D() @@ -273,6 +278,12 @@ bool CDirect3D::Initialize(HWND hWnd) return false; } + cgContext = cgCreateContext(); + hr = cgD3D9SetDevice(pDevice); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); + } + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); init_done = true; @@ -303,6 +314,13 @@ void CDirect3D::DeInitialize() pD3D = NULL; } + if(cgContext) { + cgDestroyContext(cgContext); + cgContext = NULL; + } + + cgD3D9SetDevice(NULL); + init_done = false; afterRenderWidth = 0; afterRenderHeight = 0; @@ -312,6 +330,73 @@ void CDirect3D::DeInitialize() } bool CDirect3D::SetShader(const TCHAR *file) +{ + SetShaderCG(NULL); + SetShaderHLSL(NULL); + shader_type = D3D_SHADER_NONE; + if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) { + return SetShaderCG(file); + } else { + return SetShaderHLSL(file); + } +} + +bool CDirect3D::SetShaderCG(const TCHAR *file) +{ + TCHAR errorMsg[MAX_PATH + 50]; + HRESULT hr; + + if(cgFragmentProgram) { + cgDestroyProgram(cgFragmentProgram); + cgFragmentProgram = NULL; + } + if(cgVertexProgram) { + cgDestroyProgram(cgVertexProgram); + cgVertexProgram = NULL; + } + + if (file == NULL || *file==TEXT('\0')) + return true; + + CGprofile vertexProfile = cgD3D9GetLatestVertexProfile(); + CGprofile pixelProfile = cgD3D9GetLatestPixelProfile(); + + const char** vertexOptions = cgD3D9GetOptimalOptions(vertexProfile); + const char** pixelOptions = cgD3D9GetOptimalOptions(pixelProfile); + + char *fileContents = ReadShaderFileContents(file); + if(!fileContents) + return false; + + cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + vertexProfile, "main_vertex", vertexOptions); + + cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + pixelProfile, "main_fragment", pixelOptions); + + delete [] fileContents; + + if(!cgVertexProgram && !cgFragmentProgram) { + _stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),file); + MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(cgVertexProgram) { + hr = cgD3D9LoadProgram(cgVertexProgram,false,0); + hr = cgD3D9BindProgram(cgVertexProgram); + } + if(cgFragmentProgram) { + hr = cgD3D9LoadProgram(cgFragmentProgram,false,0); + hr = cgD3D9BindProgram(cgFragmentProgram); + } + + shader_type = D3D_SHADER_CG; + + return true; +} + +bool CDirect3D::SetShaderHLSL(const TCHAR *file) { //MUDLORD: the guts //Compiles a shader from files on disc @@ -331,7 +416,6 @@ bool CDirect3D::SetShader(const TCHAR *file) HRESULT hr; - shader_compiled = false; shaderTimer = 1.0f; shaderTimeStart = 0; shaderTimeElapsed = 0; @@ -462,48 +546,77 @@ bool CDirect3D::SetShader(const TCHAR *file) D3DXHANDLE hTech; effect->FindNextValidTechnique(NULL,&hTech); effect->SetTechnique( hTech ); - shader_compiled = true; + shader_type = D3D_SHADER_HLSL; return true; } void CDirect3D::SetShaderVars() { - D3DXVECTOR4 rubyTextureSize; - D3DXVECTOR4 rubyInputSize; - D3DXVECTOR4 rubyOutputSize; - D3DXHANDLE rubyTimer; + if(shader_type == D3D_SHADER_HLSL) { + D3DXVECTOR4 rubyTextureSize; + D3DXVECTOR4 rubyInputSize; + D3DXVECTOR4 rubyOutputSize; + D3DXHANDLE rubyTimer; - int shaderTime = GetTickCount(); - shaderTimeElapsed += shaderTime - shaderTimeStart; - shaderTimeStart = shaderTime; - if(shaderTimeElapsed > 100) { - shaderTimeElapsed = 0; - shaderTimer += 0.01f; - } - rubyTextureSize.x = rubyTextureSize.y = (float)quadTextureSize; - rubyTextureSize.z = rubyTextureSize.w = 1.0 / quadTextureSize; - rubyInputSize.x = (float)afterRenderWidth; - rubyInputSize.y = (float)afterRenderHeight; - rubyInputSize.z = 1.0 / rubyInputSize.y; - rubyInputSize.w = 1.0 / rubyInputSize.z; - rubyOutputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; - rubyOutputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; - rubyOutputSize.z = 1.0 / rubyOutputSize.y; - rubyOutputSize.w = 1.0 / rubyOutputSize.x; - rubyTimer = effect->GetParameterByName(0, "rubyTimer"); - - effect->SetFloat(rubyTimer, shaderTimer); - effect->SetVector("rubyTextureSize", &rubyTextureSize); - effect->SetVector("rubyInputSize", &rubyInputSize); - effect->SetVector("rubyOutputSize", &rubyOutputSize); - - effect->SetTexture("rubyTexture", drawSurface); - for(int i = 0; i < MAX_SHADER_TEXTURES; i++) { - char rubyLUTName[256]; - sprintf(rubyLUTName, "rubyLUT%d", i); - if (rubyLUT[i] != NULL) { - effect->SetTexture( rubyLUTName, rubyLUT[i] ); + int shaderTime = GetTickCount(); + shaderTimeElapsed += shaderTime - shaderTimeStart; + shaderTimeStart = shaderTime; + if(shaderTimeElapsed > 100) { + shaderTimeElapsed = 0; + shaderTimer += 0.01f; } + rubyTextureSize.x = rubyTextureSize.y = (float)quadTextureSize; + rubyTextureSize.z = rubyTextureSize.w = 1.0 / quadTextureSize; + rubyInputSize.x = (float)afterRenderWidth; + rubyInputSize.y = (float)afterRenderHeight; + rubyInputSize.z = 1.0 / rubyInputSize.y; + rubyInputSize.w = 1.0 / rubyInputSize.z; + rubyOutputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; + rubyOutputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; + rubyOutputSize.z = 1.0 / rubyOutputSize.y; + rubyOutputSize.w = 1.0 / rubyOutputSize.x; + rubyTimer = effect->GetParameterByName(0, "rubyTimer"); + + effect->SetFloat(rubyTimer, shaderTimer); + effect->SetVector("rubyTextureSize", &rubyTextureSize); + effect->SetVector("rubyInputSize", &rubyInputSize); + effect->SetVector("rubyOutputSize", &rubyOutputSize); + + effect->SetTexture("rubyTexture", drawSurface); + for(int i = 0; i < MAX_SHADER_TEXTURES; i++) { + char rubyLUTName[256]; + sprintf(rubyLUTName, "rubyLUT%d", i); + if (rubyLUT[i] != NULL) { + effect->SetTexture( rubyLUTName, rubyLUT[i] ); + } + } + } else if(shader_type == D3D_SHADER_CG) { + CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + + CGparameter cgpVideoSize = cgGetNamedParameter(cgFragmentProgram, "IN.video_size"); + CGparameter cgpTextureSize = cgGetNamedParameter(cgFragmentProgram, "IN.texture_size"); + CGparameter cgpOutputSize = cgGetNamedParameter(cgFragmentProgram, "IN.output_size"); + + D3DXMATRIX mvpMat; + D3DXVECTOR2 videoSize; + D3DXVECTOR2 textureSize; + D3DXVECTOR2 outputSize; + videoSize.x = (float)afterRenderWidth; + videoSize.y = (float)afterRenderHeight; + textureSize.x = textureSize.y = (float)quadTextureSize; + outputSize.x = GUI.Stretch?(float)dPresentParams.BackBufferWidth:(float)afterRenderWidth; + outputSize.y = GUI.Stretch?(float)dPresentParams.BackBufferHeight:(float)afterRenderHeight; + + D3DXMatrixIdentity(&mvpMat); + + if(cgpModelViewProj) + cgD3D9SetUniformMatrix(cgpModelViewProj,&mvpMat); + if(cgpVideoSize) + cgD3D9SetUniform(cgpVideoSize,&videoSize); + if(cgpTextureSize) + cgD3D9SetUniform(cgpTextureSize,&textureSize); + if(cgpOutputSize) + cgD3D9SetUniform(cgpOutputSize,&outputSize); } } @@ -579,10 +692,15 @@ void CDirect3D::Render(SSurface Src) pDevice->SetFVF(FVF_COORDS_TEX); pDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERTEX)); - if (shader_compiled) { + if(shader_type == D3D_SHADER_CG) { + cgD3D9BindProgram(cgFragmentProgram); + cgD3D9BindProgram(cgVertexProgram); + } + + SetShaderVars(); + + if (shader_type == D3D_SHADER_HLSL) { UINT passes; - - SetShaderVars(); hr = effect->Begin(&passes, 0); for(UINT pass = 0; pass < passes; pass++ ) { @@ -893,8 +1011,8 @@ returns true if successful, false otherwise */ bool CDirect3D::ApplyDisplayChanges(void) { - if(GUI.shaderEnabled && GUI.HLSLshaderFileName) - SetShader(GUI.HLSLshaderFileName); + if(GUI.shaderEnabled && GUI.D3DshaderFileName) + SetShader(GUI.D3DshaderFileName); else SetShader(NULL); diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 1daf463e..43b94e8b 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -183,6 +183,9 @@ #include #include +#include +#include + #include "render.h" #include "wsnes9x.h" #include "IS9xDisplayOutput.h" @@ -199,6 +202,8 @@ typedef struct _VERTEX { } } VERTEX; //our custom vertex with a constuctor for easier assignment +enum current_d3d_shader_type { D3D_SHADER_NONE, D3D_SHADER_HLSL, D3D_SHADER_CG }; + class CDirect3D: public IS9xDisplayOutput { private: @@ -218,7 +223,9 @@ private: LPD3DXEFFECT effect; LPDIRECT3DTEXTURE9 rubyLUT[MAX_SHADER_TEXTURES]; - bool shader_compiled; + CGcontext cgContext; + CGprogram cgVertexProgram, cgFragmentProgram; + current_d3d_shader_type shader_type; float shaderTimer; int shaderTimeStart; int shaderTimeElapsed; @@ -231,6 +238,8 @@ private: bool ResetDevice(); void SetShaderVars(); bool SetShader(const TCHAR *file); + bool SetShaderHLSL(const TCHAR *file); + bool SetShaderCG(const TCHAR *file); public: CDirect3D(); diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 629980fd..ee2de7da 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -9,6 +9,9 @@ #include "../filter/hq2x.h" #include "../filter/2xsai.h" +#pragma comment( lib, "cg.lib" ) +#pragma comment( lib, "cggl.lib" ) + COpenGL::COpenGL(void) { @@ -23,11 +26,13 @@ COpenGL::COpenGL(void) afterRenderHeight = 0; fullscreen = false; shaderFunctionsLoaded = false; - shaderCompiled = false; + shader_type = OGL_SHADER_NONE; pboFunctionsLoaded = false; shaderProgram = 0; vertexShader = 0; fragmentShader = 0; + cgContext = NULL; + cgVertexProgram = cgFragmentProgram = NULL; } COpenGL::~COpenGL(void) @@ -99,6 +104,8 @@ bool COpenGL::Initialize(HWND hWnd) glVertexPointer(2, GL_FLOAT, 0, vertices); glTexCoordPointer(2, GL_FLOAT, 0, texcoords); + cgContext = cgCreateContext(); + GetClientRect(hWnd,&windowRect); ChangeRenderSize(windowRect.right,windowRect.bottom); @@ -113,8 +120,7 @@ bool COpenGL::Initialize(HWND hWnd) void COpenGL::DeInitialize() { initDone = false; - if(shaderCompiled) - SetShaders(NULL); + SetShaders(NULL); DestroyDrawSurface(); wglMakeCurrent(NULL,NULL); if(hRC) { @@ -132,7 +138,7 @@ void COpenGL::DeInitialize() afterRenderWidth = 0; afterRenderHeight = 0; shaderFunctionsLoaded = false; - shaderCompiled = false; + shader_type = OGL_SHADER_NONE; } void COpenGL::CreateDrawSurface() @@ -254,24 +260,37 @@ void COpenGL::Render(SSurface Src) ApplyDisplayChanges(); } - if (shaderCompiled) { - GLint location; + if (shader_type != OGL_SHADER_NONE) { + GLint location; float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; - location = glGetUniformLocation (shaderProgram, "rubyInputSize"); - glUniform2fv (location, 1, inputSize); - RECT windowSize; GetClientRect(hWnd,&windowSize); - float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; - location = glGetUniformLocation (shaderProgram, "rubyOutputSize"); - glUniform2fv (location, 1, outputSize); - float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; - location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); - glUniform2fv (location, 1, textureSize); + + if(shader_type == OGL_SHADER_GLSL) { + location = glGetUniformLocation (shaderProgram, "rubyInputSize"); + glUniform2fv (location, 1, inputSize); + + location = glGetUniformLocation (shaderProgram, "rubyOutputSize"); + glUniform2fv (location, 1, outputSize); + + location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); + glUniform2fv (location, 1, textureSize); + } else if(shader_type == OGL_SHADER_CG) { + CGparameter cgpModelViewProj = cgGetNamedParameter(cgVertexProgram, "modelViewProj"); + + CGparameter cgpVideoSize = cgGetNamedParameter(cgFragmentProgram, "IN.video_size"); + CGparameter cgpTextureSize = cgGetNamedParameter(cgFragmentProgram, "IN.texture_size"); + CGparameter cgpOutputSize = cgGetNamedParameter(cgFragmentProgram, "IN.output_size"); + + cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); + cgGLSetParameter2fv(cgpVideoSize, inputSize); + cgGLSetParameter2fv(cgpTextureSize, textureSize); + cgGLSetParameter2fv(cgpOutputSize, outputSize); + } } glPixelStorei(GL_UNPACK_ROW_LENGTH, quadTextureSize); @@ -305,8 +324,8 @@ bool COpenGL::ApplyDisplayChanges(void) if(wglSwapIntervalEXT) { wglSwapIntervalEXT(GUI.Vsync?1:0); } - if(GUI.shaderEnabled && GUI.GLSLshaderFileName) - SetShaders(GUI.GLSLshaderFileName); + if(GUI.shaderEnabled && GUI.OGLshaderFileName) + SetShaders(GUI.OGLshaderFileName); else SetShaders(NULL); @@ -456,32 +475,79 @@ bool COpenGL::LoadShaderFunctions() return shaderFunctionsLoaded; } -char *ReadFileContents(const TCHAR *filename) +bool COpenGL::SetShaders(const TCHAR *file) { - HANDLE hFile; - DWORD size; - DWORD bytesRead; - char *contents; - - hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN , 0); - if(hFile == INVALID_HANDLE_VALUE){ - return NULL; + SetShadersCG(NULL); + SetShadersGLSL(NULL); + shader_type = OGL_SHADER_NONE; + if(file!=NULL && lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) { + return SetShadersCG(file); + } else { + return SetShadersGLSL(file); } - size = GetFileSize(hFile,NULL); - contents = new char[size+1]; - if(!ReadFile(hFile,contents,size,&bytesRead,NULL)) { - CloseHandle(hFile); - delete[] contents; - return NULL; - } - CloseHandle(hFile); - contents[size] = '\0'; - return contents; - } -bool COpenGL::SetShaders(const TCHAR *glslFileName) +bool COpenGL::SetShadersCG(const TCHAR *file) +{ + TCHAR errorMsg[MAX_PATH + 50]; + HRESULT hr; + + if(cgFragmentProgram) { + cgDestroyProgram(cgFragmentProgram); + cgFragmentProgram = NULL; + } + if(cgVertexProgram) { + cgDestroyProgram(cgVertexProgram); + cgVertexProgram = NULL; + } + + CGprofile vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); + CGprofile fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); + + cgGLDisableProfile(vertexProfile); + cgGLDisableProfile(fragmentProfile); + + if (file == NULL || *file==TEXT('\0')) + return true; + + cgGLSetOptimalOptions(vertexProfile); + cgGLSetOptimalOptions(fragmentProfile); + + char *fileContents = ReadShaderFileContents(file); + if(!fileContents) + return false; + + cgVertexProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + vertexProfile, "main_vertex", NULL); + + cgFragmentProgram = cgCreateProgram( cgContext, CG_SOURCE, fileContents, + fragmentProfile, "main_fragment", NULL); + + delete [] fileContents; + + if(!cgVertexProgram && !cgFragmentProgram) { + _stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),file); + MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); + return false; + } + + if(cgVertexProgram) { + cgGLEnableProfile(vertexProfile); + cgGLLoadProgram(cgVertexProgram); + cgGLBindProgram(cgVertexProgram); + } + if(cgFragmentProgram) { + cgGLEnableProfile(fragmentProfile); + cgGLLoadProgram(cgFragmentProgram); + cgGLBindProgram(cgFragmentProgram); + } + + shader_type = OGL_SHADER_CG; + + return true; +} + +bool COpenGL::SetShadersGLSL(const TCHAR *glslFileName) { char *fragment=NULL, *vertex=NULL; IXMLDOMDocument * pXMLDoc = NULL; @@ -492,8 +558,6 @@ bool COpenGL::SetShaders(const TCHAR *glslFileName) TCHAR errorMsg[MAX_PATH + 50]; - shaderCompiled = false; - if(fragmentShader) { glDetachShader(shaderProgram,fragmentShader); glDeleteShader(fragmentShader); @@ -631,7 +695,7 @@ bool COpenGL::SetShaders(const TCHAR *glslFileName) glLinkProgram(shaderProgram); glUseProgram(shaderProgram); - shaderCompiled = true; + shader_type = OGL_SHADER_GLSL; return true; } diff --git a/win32/COpenGL.h b/win32/COpenGL.h index edacfc07..1ef32a60 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -181,13 +181,15 @@ #include #include +#include +#include + #include "glext.h" #include "wglext.h" #include "IS9xDisplayOutput.h" -/* IS9xDisplayOutput - Interface for display driver. -*/ +enum current_ogl_shader_type { OGL_SHADER_NONE, OGL_SHADER_GLSL, OGL_SHADER_CG }; + class COpenGL : public IS9xDisplayOutput { private: @@ -207,10 +209,13 @@ private: unsigned int afterRenderWidth, afterRenderHeight; bool shaderFunctionsLoaded; - bool shaderCompiled; bool pboFunctionsLoaded; + CGcontext cgContext; + CGprogram cgVertexProgram, cgFragmentProgram; + current_ogl_shader_type shader_type; + GLuint shaderProgram; GLuint vertexShader; GLuint fragmentShader; @@ -240,7 +245,9 @@ private: PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; - bool SetShaders(const TCHAR *glslFileName); + bool SetShaders(const TCHAR *file); + bool SetShadersCG(const TCHAR *file); + bool SetShadersGLSL(const TCHAR *glslFileName); bool LoadShaderFunctions(); bool LoadPBOFunctions(); void CreateDrawSurface(void); diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc index 314e1890..d8288504 100644 --- a/win32/rsrc/snes9x.rc +++ b/win32/rsrc/snes9x.rc @@ -218,10 +218,10 @@ BEGIN LTEXT "Amount skipped:",IDC_STATIC,62,158,67,8 LTEXT "Output Method",IDC_STATIC,10,19,51,11 CONTROL "Use Shader",IDC_SHADER_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,176,52,9 - LTEXT "HLSL Effect File",IDC_STATIC,13,187,104,8 + LTEXT "Direct3D Shader File",IDC_STATIC,13,187,104,8 EDITTEXT IDC_SHADER_GLSL_FILE,13,227,306,14,ES_AUTOHSCROLL | WS_DISABLED PUSHBUTTON "...",IDC_SHADER_GLSL_BROWSE,322,227,19,14,WS_DISABLED - LTEXT "GLSL shader",IDC_STATIC,13,216,104,8 + LTEXT "OpenGL Shader File",IDC_STATIC,13,216,104,8 CONTROL "Blend Hi-Res Images",IDC_HIRESBLEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,136,82,10 CONTROL "VSync",IDC_VSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,102,37,10 END diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp index e50f1ca0..a532e728 100644 --- a/win32/wconfig.cpp +++ b/win32/wconfig.cpp @@ -865,8 +865,8 @@ void WinRegisterConfigItems() AddUIntC("FilterHiRes", GUI.ScaleHiRes, 0, filterString2); AddBoolC("BlendHiRes", GUI.BlendHiRes, true, "true to horizontally blend Hi-Res images (better transparency effect on filters that do not account for this)"); AddBoolC("ShaderEnabled", GUI.shaderEnabled, false, "true to use pixel shader (if supported by output method)"); - AddStringC("Direct3D:HLSLFileName", GUI.HLSLshaderFileName, MAX_PATH, "", "shader filename for Direct3D mode"); - AddStringC("OpenGL:GLSLFileName", GUI.GLSLshaderFileName, MAX_PATH, "", "shader filename for OpenGL mode (bsnes-style XML shader)"); + AddStringC("Direct3D:D3DShader", GUI.D3DshaderFileName, MAX_PATH, "", "shader filename for Direct3D mode (HLSL effect file or CG shader"); + AddStringC("OpenGL:OGLShader", GUI.OGLshaderFileName, MAX_PATH, "", "shader filename for OpenGL mode (bsnes-style XML shader or CG shader)"); AddBoolC("ExtendHeight", GUI.HeightExtend, false, "true to display an extra 15 pixels at the bottom, which few games use. Also increases AVI output size from 256x224 to 256x240."); AddBoolC("AlwaysCenterImage", GUI.AlwaysCenterImage,false, "true to center the image even if larger than window"); AddIntC("Window:Width", GUI.window_size.right, 512, "256=1x, 512=2x, 768=3x, 1024=4x, etc. (usually)"); diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp index dd845a9e..45c55272 100644 --- a/win32/win32_display.cpp +++ b/win32/win32_display.cpp @@ -430,6 +430,31 @@ void S9xSetWinPixelFormat () S9xDisplayOutput->SetSnes9xColorFormat(); } +char *ReadShaderFileContents(const TCHAR *filename) +{ + HANDLE hFile; + DWORD size; + DWORD bytesRead; + char *contents; + + hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN , 0); + if(hFile == INVALID_HANDLE_VALUE){ + return NULL; + } + size = GetFileSize(hFile,NULL); + contents = new char[size+1]; + if(!ReadFile(hFile,contents,size,&bytesRead,NULL)) { + CloseHandle(hFile); + delete[] contents; + return NULL; + } + CloseHandle(hFile); + contents[size] = '\0'; + return contents; + +} + // TODO: abstract the following functions in some way - only necessary for directdraw /* DirectDraw only begin */ diff --git a/win32/win32_display.h b/win32/win32_display.h index dd9cb635..b7f50fda 100644 --- a/win32/win32_display.h +++ b/win32/win32_display.h @@ -205,5 +205,6 @@ void WinDisplayStringFromBottom (const char *string, int linesFromBottom, int pi void WinSetCustomDisplaySurface(void *screen, int ppl, int width, int height, int scale); template void WinDisplayStringInBuffer (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); +char *ReadShaderFileContents(const TCHAR *filename); #endif diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 3b284544..115ddc30 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -6961,7 +6961,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) static bool prevStretch, prevAspectRatio, prevHeightExtend, prevAutoDisplayMessages, prevBilinearFilter, prevShaderEnabled, prevBlendHires; static int prevAspectWidth; static OutputMethod prevOutputMethod; - static TCHAR prevHLSLShaderFile[MAX_PATH],prevGLSLShaderFile[MAX_PATH]; + static TCHAR prevD3DShaderFile[MAX_PATH],prevOGLShaderFile[MAX_PATH]; switch(msg) { @@ -6990,8 +6990,8 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) prevAutoDisplayMessages = Settings.AutoDisplayMessages != 0; prevShaderEnabled = GUI.shaderEnabled; prevBlendHires = GUI.BlendHiRes; - lstrcpy(prevHLSLShaderFile,GUI.HLSLshaderFileName); - lstrcpy(prevGLSLShaderFile,GUI.GLSLshaderFileName); + lstrcpy(prevD3DShaderFile,GUI.D3DshaderFileName); + lstrcpy(prevOGLShaderFile,GUI.OGLshaderFileName); _stprintf(s,TEXT("Current: %dx%d %dbit %dHz"),GUI.FullscreenMode.width,GUI.FullscreenMode.height,GUI.FullscreenMode.depth,GUI.FullscreenMode.rate); @@ -7068,8 +7068,8 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_FILE),TRUE); EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_BROWSE),TRUE); } - SetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.HLSLshaderFileName); - SetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.GLSLshaderFileName); + SetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName); + SetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.OGLshaderFileName); lpfnOldWndProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hDlg,IDC_SHADER_GROUP),GWLP_WNDPROC,(LONG_PTR)GroupBoxCheckBoxTitle); @@ -7234,8 +7234,8 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_FILE),GUI.shaderEnabled); EnableWindow(GetDlgItem(hDlg, IDC_SHADER_GLSL_BROWSE),GUI.shaderEnabled); - GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.HLSLshaderFileName,MAX_PATH); - GetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.GLSLshaderFileName,MAX_PATH); + GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName,MAX_PATH); + GetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,GUI.OGLshaderFileName,MAX_PATH); WinDisplayApplyChanges(); WinRefreshDisplay(); break; @@ -7245,7 +7245,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; - ofn.lpstrFilter = TEXT("Shader Files\0*.shader\0All Files\0*.*\0\0"); + ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0"); ofn.lpstrFile = openFileName; ofn.lpstrTitle = TEXT("Select Shader"); ofn.lpstrDefExt = TEXT("shader"); @@ -7253,7 +7253,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { SetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,openFileName); - lstrcpy(GUI.HLSLshaderFileName,openFileName); + lstrcpy(GUI.D3DshaderFileName,openFileName); WinDisplayApplyChanges(); WinRefreshDisplay(); } @@ -7264,7 +7264,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; - ofn.lpstrFilter = TEXT("Shader Files\0*.shader\0All Files\0*.*\0\0"); + ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg\0All Files\0*.*\0\0"); ofn.lpstrFile = openFileName; ofn.lpstrTitle = TEXT("Select Shader"); ofn.lpstrDefExt = TEXT("shader"); @@ -7272,7 +7272,7 @@ INT_PTR CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if(GetOpenFileName(&ofn)) { SetDlgItemText(hDlg,IDC_SHADER_GLSL_FILE,openFileName); - lstrcpy(GUI.GLSLshaderFileName,openFileName); + lstrcpy(GUI.OGLshaderFileName,openFileName); WinDisplayApplyChanges(); WinRefreshDisplay(); } @@ -7400,7 +7400,7 @@ updateFilterBox2: GUI.FullscreenMode = dm[index]; - GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.HLSLshaderFileName,MAX_PATH); + GetDlgItemText(hDlg,IDC_SHADER_HLSL_FILE,GUI.D3DshaderFileName,MAX_PATH); // we might've changed the region that the game draws over @@ -7453,8 +7453,8 @@ updateFilterBox2: GUI.HeightExtend = prevHeightExtend; GUI.shaderEnabled = prevShaderEnabled; GUI.BlendHiRes = prevBlendHires; - lstrcpy(GUI.HLSLshaderFileName,prevHLSLShaderFile); - lstrcpy(GUI.GLSLshaderFileName,prevGLSLShaderFile); + lstrcpy(GUI.D3DshaderFileName,prevD3DShaderFile); + lstrcpy(GUI.OGLshaderFileName,prevOGLShaderFile); } EndDialog(hDlg,0); diff --git a/win32/wsnes9x.h b/win32/wsnes9x.h index 409deed2..19213774 100644 --- a/win32/wsnes9x.h +++ b/win32/wsnes9x.h @@ -316,8 +316,8 @@ struct sGUI { bool LocalVidMem; bool Vsync; bool shaderEnabled; - TCHAR HLSLshaderFileName[MAX_PATH]; - TCHAR GLSLshaderFileName[MAX_PATH]; + TCHAR D3DshaderFileName[MAX_PATH]; + TCHAR OGLshaderFileName[MAX_PATH]; bool IgnoreNextMouseMove; RECT window_size;