From a911503d4ad7967fdc8f6bc7f9d0ca102cbe8c83 Mon Sep 17 00:00:00 2001 From: OV2 Date: Tue, 22 May 2018 21:43:51 +0200 Subject: [PATCH] win32: restore old style OGL .shader support --- win32/COpenGL.cpp | 190 ++++++++++++++++++++++++++++++++++++++++++++-- win32/COpenGL.h | 3 +- 2 files changed, 186 insertions(+), 7 deletions(-) diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index d4f7a62a..5d254b50 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -503,10 +503,11 @@ void COpenGL::Render(SSurface Src) //Get maximum rect respecting AR setting displayRect = CalculateDisplayRect(windowSize.right, windowSize.bottom, windowSize.right, windowSize.bottom); + // GLSL class does all the rendering, no output needed if (shader_type == OGL_SHADER_GLSL) { glslShader->render(drawTexture, afterRenderWidth, afterRenderHeight, displayRect.left, displayRect.top, displayRect.right - displayRect.left, displayRect.bottom - displayRect.top, wOGLViewportCallback); } - else { + else { // for CG shaders and old style .shader files the last pass is done here, same as no shader if(shader_type == OGL_SHADER_CG) { xySize inputSize = { (float)afterRenderWidth, (float)afterRenderHeight }; xySize xywindowSize = { (double)windowSize.right, (double)windowSize.bottom }; @@ -515,6 +516,23 @@ void COpenGL::Render(SSurface Src) xySize textureSize = { (double)outTextureWidth, (double)outTextureHeight }; cgShader->Render(drawTexture, textureSize, inputSize, viewportSize, xywindowSize); } + else if (shader_type == OGL_SHADER_GLSL_OLD) { + GLint location; + + float inputSize[2] = { (float)afterRenderWidth, (float)afterRenderHeight }; + float outputSize[2] = { (float)(GUI.Stretch ? windowSize.right : afterRenderWidth), + (float)(GUI.Stretch ? windowSize.bottom : afterRenderHeight) }; + float textureSize[2] = { (float)outTextureWidth, (float)outTextureHeight }; + 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); + } if (Settings.BilinearFilter) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -691,11 +709,14 @@ bool COpenGL::SetShaders(const TCHAR *file) { SetShadersCG(NULL); SetShadersGLSL(NULL); + SetShadersGLSL_OLD(NULL); shader_type = OGL_SHADER_NONE; - if(file!=NULL && ( - (lstrlen(file)>3 && _tcsncicmp(&file[lstrlen(file)-3],TEXT(".cg"),3)==0) || - (lstrlen(file)>4 && _tcsncicmp(&file[lstrlen(file)-4],TEXT(".cgp"),4)==0))) { + if (file != NULL && ( + (lstrlen(file) > 3 && _tcsncicmp(&file[lstrlen(file) - 3], TEXT(".cg"), 3) == 0) || + (lstrlen(file) > 4 && _tcsncicmp(&file[lstrlen(file) - 4], TEXT(".cgp"), 4) == 0))) { return SetShadersCG(file); + } else if((lstrlen(file) > 7 && _tcsncicmp(&file[lstrlen(file) - 7], TEXT(".shader"), 7) == 0)) { + return SetShadersGLSL_OLD(file); } else { return SetShadersGLSL(file); } @@ -740,10 +761,14 @@ bool COpenGL::SetShadersCG(const TCHAR *file) bool COpenGL::SetShadersGLSL(const TCHAR *glslFileName) { - if (!glslFileName || !glslShader) + if (!glslShader) + return false; + + glslShader->destroy(); + + if (!glslFileName) return false; - glslShader->destroy(); glslShader->load_shader(_tToChar(glslFileName)); shader_type = OGL_SHADER_GLSL; @@ -751,6 +776,159 @@ bool COpenGL::SetShadersGLSL(const TCHAR *glslFileName) return true; } +bool COpenGL::SetShadersGLSL_OLD(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); + 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); + + shader_type = OGL_SHADER_GLSL_OLD; + + return true; +} + bool COpenGL::ShaderAailable() { const char *extensions = (const char *)glGetString(GL_EXTENSIONS); diff --git a/win32/COpenGL.h b/win32/COpenGL.h index 2b6257f5..df608163 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -203,7 +203,7 @@ #include "wglext.h" #include "IS9xDisplayOutput.h" -enum current_ogl_shader_type { OGL_SHADER_NONE, OGL_SHADER_GLSL, OGL_SHADER_CG }; +enum current_ogl_shader_type { OGL_SHADER_NONE, OGL_SHADER_GLSL, OGL_SHADER_CG, OGL_SHADER_GLSL_OLD}; class COpenGL : public IS9xDisplayOutput { @@ -247,6 +247,7 @@ private: void checkForCgError(const char *situation); bool SetShadersCG(const TCHAR *file); bool SetShadersGLSL(const TCHAR *glslFileName); + bool SetShadersGLSL_OLD(const TCHAR *glslFileName); bool LoadShaderFunctions(); bool LoadPBOFunctions(); void CreateDrawSurface(unsigned int width, unsigned int height);