From ad2c72d26c0e627f71c3621bdb5768496583e602 Mon Sep 17 00:00:00 2001 From: OV2 Date: Sun, 20 May 2018 19:48:38 +0200 Subject: [PATCH] win32: fist step glsl shaders --- shaders/shader_platform.h | 6 +- win32/COpenGL.cpp | 214 +++++++++------------------------- win32/COpenGL.h | 4 + win32/snes9xw.vcxproj | 5 + win32/snes9xw.vcxproj.filters | 20 +++- win32/wsnes9x.cpp | 2 +- 6 files changed, 88 insertions(+), 163 deletions(-) diff --git a/shaders/shader_platform.h b/shaders/shader_platform.h index 0a3f2396..2c2f004d 100644 --- a/shaders/shader_platform.h +++ b/shaders/shader_platform.h @@ -11,10 +11,14 @@ #ifdef _WIN32 #include #include +#include "gl_core_3_1.h" +#include #define chdir(dir) _chdir(dir) #define realpath(src, resolved) _fullpath(resolved, src, PATH_MAX) -} + + + #endif #endif /* __SHADER_PLATFORM_H */ diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index a09e9546..9eb220c6 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -226,6 +226,7 @@ COpenGL::COpenGL(void) cgAvailable = false; frameCount = 0; cgShader = NULL; + glslShader = NULL; } COpenGL::~COpenGL(void) @@ -305,6 +306,10 @@ bool COpenGL::Initialize(HWND hWnd) cgShader = new CGLCG(cgContext); } + if (ShaderAailable() && NPOTAvailable()) { + glslShader = new GLSLShader(); + } + ApplyDisplayChanges(); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); @@ -337,6 +342,10 @@ void COpenGL::DeInitialize() afterRenderHeight = 0; shaderFunctionsLoaded = false; shader_type = OGL_SHADER_NONE; + if (glslShader) { + delete glslShader; + glslShader = NULL; + } if(cgShader) { delete cgShader; cgShader = NULL; @@ -478,23 +487,10 @@ void COpenGL::Render(SSurface Src) if (shader_type != OGL_SHADER_NONE) { if(shader_type == OGL_SHADER_GLSL) { - GLint location; - - float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; - RECT windowSize; - GetClientRect(hWnd,&windowSize); - float outputSize[2] = {(float)(GUI.Stretch?windowSize.right:afterRenderWidth), - (float)(GUI.Stretch?windowSize.bottom:afterRenderHeight) }; - float textureSize[2] = { (float)quadTextureSize, (float)quadTextureSize }; - float frameCnt = (float)++frameCount; - location = glGetUniformLocation (shaderProgram, "rubyInputSize"); - glUniform2fv (location, 1, inputSize); - - location = glGetUniformLocation (shaderProgram, "rubyOutputSize"); - glUniform2fv (location, 1, outputSize); - - location = glGetUniformLocation (shaderProgram, "rubyTextureSize"); - glUniform2fv (location, 1, textureSize); + RECT windowSize, displayRect; + GetClientRect(hWnd, &windowSize); + displayRect = CalculateDisplayRect(windowSize.right, windowSize.bottom, windowSize.right, windowSize.bottom); + glslShader->render(drawTexture, afterRenderWidth, afterRenderHeight, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top, displayRect.left, displayRect.top); } else if(shader_type == OGL_SHADER_CG) { xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight }; RECT windowSize, displayRect; @@ -732,153 +728,51 @@ bool COpenGL::SetShadersCG(const TCHAR *file) bool COpenGL::SetShadersGLSL(const TCHAR *glslFileName) { - char *fragment=NULL, *vertex=NULL; - IXMLDOMDocument * pXMLDoc = NULL; - IXMLDOMElement * pXDE = NULL; - IXMLDOMNode * pXDN = NULL; - HRESULT hr; - BSTR queryString, nodeContent; - - TCHAR errorMsg[MAX_PATH + 50]; - - if(fragmentShader) { - glDetachShader(shaderProgram,fragmentShader); - glDeleteShader(fragmentShader); - fragmentShader = 0; - } - if(vertexShader) { - glDetachShader(shaderProgram,vertexShader); - glDeleteShader(vertexShader); - vertexShader = 0; - } - if(shaderProgram) { - glUseProgram(0); - glDeleteProgram(shaderProgram); - shaderProgram = 0; - } - - if(glslFileName==NULL || *glslFileName==TEXT('\0')) - return true; - - if(!LoadShaderFunctions()) { - MessageBox(NULL, TEXT("Unable to load OpenGL shader functions"), TEXT("Shader Loading Error"), - MB_OK|MB_ICONEXCLAMATION); + if (!glslFileName || !glslShader) return false; - } - hr = CoCreateInstance(CLSID_DOMDocument,NULL,CLSCTX_INPROC_SERVER,IID_PPV_ARGS(&pXMLDoc)); - - if(FAILED(hr)) { - MessageBox(NULL, TEXT("Error creating XML Parser"), TEXT("Shader Loading Error"), - MB_OK|MB_ICONEXCLAMATION); - return false; - } - - VARIANT fileName; - VARIANT_BOOL ret; - fileName.vt = VT_BSTR; -#ifdef UNICODE - fileName.bstrVal = SysAllocString(glslFileName); -#else - wchar_t tempfilename[MAX_PATH]; - MultiByteToWideChar(CP_UTF8,0,glslFileName,-1,tempfilename,MAX_PATH); - fileName.bstrVal = SysAllocString(tempfilename); -#endif - hr = pXMLDoc->load(fileName,&ret); - SysFreeString(fileName.bstrVal); - - if(FAILED(hr) || hr==S_FALSE) { - _stprintf(errorMsg,TEXT("Error loading GLSL shader file:\n%s"),glslFileName); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); - pXMLDoc->Release(); - return false; - } - - VARIANT attributeValue; - BSTR attributeName; - - hr = pXMLDoc->get_documentElement(&pXDE); - if(FAILED(hr) || hr==S_FALSE) { - _stprintf(errorMsg,TEXT("Error loading root element from file:\n%s"),glslFileName); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); - pXMLDoc->Release(); - return false; - } - - attributeName=SysAllocString(L"language"); - pXDE->getAttribute(attributeName,&attributeValue); - SysFreeString(attributeName); - pXDE->Release(); - - if(attributeValue.vt!=VT_BSTR || lstrcmpiW(attributeValue.bstrVal,L"glsl")) { - _stprintf(errorMsg,TEXT("Shader language is <%s>, expected in file:\n%s"),attributeValue.bstrVal,glslFileName); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); - if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal); - pXMLDoc->Release(); - return false; - } - if(attributeValue.vt==VT_BSTR) SysFreeString(attributeValue.bstrVal); - - queryString=SysAllocString(L"/shader/fragment"); - hr = pXMLDoc->selectSingleNode(queryString,&pXDN); - SysFreeString(queryString); - - if(hr == S_OK) { - hr = pXDN->get_text(&nodeContent); - if(hr == S_OK) { - int requiredChars = WideCharToMultiByte(CP_ACP,0,nodeContent,-1,fragment,0,NULL,NULL); - fragment = new char[requiredChars]; - WideCharToMultiByte(CP_UTF8,0,nodeContent,-1,fragment,requiredChars,NULL,NULL); - } - SysFreeString(nodeContent); - pXDN->Release(); - pXDN = NULL; - } - - queryString=SysAllocString(L"/shader/vertex"); - hr = pXMLDoc->selectSingleNode(queryString,&pXDN); - SysFreeString(queryString); - - if(hr == S_OK) { - hr = pXDN->get_text(&nodeContent); - if(hr == S_OK) { - int requiredChars = WideCharToMultiByte(CP_ACP,0,nodeContent,-1,vertex,0,NULL,NULL); - vertex = new char[requiredChars]; - WideCharToMultiByte(CP_UTF8,0,nodeContent,-1,vertex,requiredChars,NULL,NULL); - } - SysFreeString(nodeContent); - pXDN->Release(); - pXDN = NULL; - } - - pXMLDoc->Release(); - - if(!fragment && !vertex) { - _stprintf(errorMsg,TEXT("No vertex or fragment program in file:\n%s"),glslFileName); - MessageBox(NULL, errorMsg, TEXT("Shader Loading Error"), MB_OK|MB_ICONEXCLAMATION); - return false; - } - - shaderProgram = glCreateProgram (); - if(vertex) { - vertexShader = glCreateShader (GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, (const GLchar **)&vertex, NULL); - glCompileShader(vertexShader); - glAttachShader(shaderProgram, vertexShader); - delete[] vertex; - } - if(fragment) { - fragmentShader = glCreateShader (GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, (const GLchar **)&fragment, NULL); - glCompileShader(fragmentShader); - glAttachShader(shaderProgram, fragmentShader); - delete[] fragment; - } - - glLinkProgram(shaderProgram); - glUseProgram(shaderProgram); + glslShader->destroy(); + glslShader->load_shader(_tToChar(glslFileName)); shader_type = OGL_SHADER_GLSL; return true; } + +bool COpenGL::ShaderAailable() +{ + const char *extensions = (const char *)glGetString(GL_EXTENSIONS); + + if (!extensions) + return false; + + if (strstr(extensions, "fragment_program") || + strstr(extensions, "fragment_shader")) + { + return true; + } + + return false; +} + +bool COpenGL::NPOTAvailable() +{ + const char *extensions = (const char *)glGetString(GL_EXTENSIONS); + + if (!extensions) + return false; + + int glVersionMajor = 0; + glGetIntegerv(GL_MAJOR_VERSION, &glVersionMajor); + + if (glVersionMajor >= 2) + return true; + + if (strstr(extensions, "non_power_of_two") || + strstr(extensions, "npot")) + { + return true; + } + + return false; +} diff --git a/win32/COpenGL.h b/win32/COpenGL.h index 7955956b..71186cb5 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -198,6 +198,7 @@ #include "gl_core_3_1.h" #include "cgFunctions.h" #include "CGLCG.h" +#include "../shaders/glsl.h" #include "wglext.h" #include "IS9xDisplayOutput.h" @@ -234,6 +235,7 @@ private: bool cgAvailable; CGLCG *cgShader; + GLSLShader *glslShader; GLuint shaderProgram; GLuint vertexShader; @@ -251,6 +253,8 @@ private: void DestroyDrawSurface(void); bool ChangeDrawSurfaceSize(unsigned int scale); void SetupVertices(); + bool ShaderAailable(); + bool NPOTAvailable(); public: COpenGL(); diff --git a/win32/snes9xw.vcxproj b/win32/snes9xw.vcxproj index 2138b6c8..340e2d38 100644 --- a/win32/snes9xw.vcxproj +++ b/win32/snes9xw.vcxproj @@ -403,6 +403,9 @@ true + + + @@ -513,6 +516,8 @@ + + diff --git a/win32/snes9xw.vcxproj.filters b/win32/snes9xw.vcxproj.filters index bcf679a0..4922811e 100644 --- a/win32/snes9xw.vcxproj.filters +++ b/win32/snes9xw.vcxproj.filters @@ -40,6 +40,9 @@ {1e3e39fd-b2d2-4c3f-83b2-b5731ab8deee} + + {31758447-7e76-4af0-8561-a377194049e1} + @@ -255,6 +258,15 @@ Filter + + Shaders + + + Shaders + + + Shaders + GUI\VideoDriver @@ -560,6 +572,12 @@ GUI + + Shaders + + + Shaders + GUI\VideoDriver @@ -815,4 +833,4 @@ - + \ No newline at end of file diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp index 9805f223..21202689 100644 --- a/win32/wsnes9x.cpp +++ b/win32/wsnes9x.cpp @@ -7662,7 +7662,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;*.cg;*.cgp\0All Files\0*.*\0\0"); + ofn.lpstrFilter = TEXT("Shader Files\0*.shader;*.cg;*.cgp;*.glsl;*.glslp\0All Files\0*.*\0\0"); ofn.lpstrFile = openFileName; ofn.lpstrTitle = TEXT("Select Shader"); ofn.lpstrDefExt = TEXT("shader");