summaryrefslogtreecommitdiff
path: root/src/graphics/ShaderRegistry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/ShaderRegistry.cpp')
-rw-r--r--src/graphics/ShaderRegistry.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/src/graphics/ShaderRegistry.cpp b/src/graphics/ShaderRegistry.cpp
new file mode 100644
index 0000000..529482f
--- /dev/null
+++ b/src/graphics/ShaderRegistry.cpp
@@ -0,0 +1,193 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "ShaderRegistry.h"
+
+#include "GLContext.h"
+#include "OGLShader.h"
+
+#include "../base/Logger.h"
+#include "../base/Exception.h"
+#include "../base/OSHelper.h"
+#include "../base/FileHelper.h"
+#include "../base/StringHelper.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace boost;
+
+namespace avg {
+
+std::string ShaderRegistry::s_sLibPath;
+
+ShaderRegistryPtr ShaderRegistry::get()
+{
+ return GLContext::getCurrent()->getShaderRegistry();
+}
+
+ShaderRegistry::ShaderRegistry()
+{
+ if (s_sLibPath == "") {
+ setShaderPath(getPath(getAvgLibPath())+"shaders");
+ }
+}
+
+ShaderRegistry::~ShaderRegistry()
+{
+}
+
+void ShaderRegistry::setShaderPath(const string& sLibPath)
+{
+ s_sLibPath = sLibPath;
+#ifdef __linux
+ // XXX: If we're running make distcheck, the shaders are in a different place than
+ // usual. Grrr.
+ char * pszSrcDir = getenv("srcdir");
+ if (pszSrcDir && string(pszSrcDir) != ".") {
+ s_sLibPath = string(pszSrcDir) + "/../graphics/shaders";
+ }
+#endif
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO,
+ "Loading shaders from "+s_sLibPath);
+}
+
+void ShaderRegistry::setPreprocessorDefine(const string& sName, const string& sValue)
+{
+ m_PreprocessorDefinesMap[sName] = sValue;
+}
+
+void ShaderRegistry::createShader(const std::string& sID)
+{
+ OGLShaderPtr pShader = getShader(sID);
+ if (!pShader) {
+ string sShaderCode;
+ string sVertPreprocessed;
+ loadShaderString(s_sLibPath+"/standard.vert", sVertPreprocessed);
+ string sFilename = s_sLibPath+"/"+sID+".frag";
+ string sFragPreprocessed;
+ loadShaderString(sFilename, sFragPreprocessed);
+ string sVertPrefix = createPrefixString(false);
+ string sFragPrefix = createPrefixString(true);
+ m_ShaderMap[sID] = OGLShaderPtr(
+ new OGLShader(sID, sVertPreprocessed, sFragPreprocessed, sVertPrefix,
+ sFragPrefix));
+ }
+}
+
+OGLShaderPtr ShaderRegistry::getShader(const std::string& sID) const
+{
+ ShaderMap::const_iterator it = m_ShaderMap.find(sID);
+ if (it == m_ShaderMap.end()) {
+ return OGLShaderPtr();
+ } else {
+ return it->second;
+ }
+}
+
+OGLShaderPtr ShaderRegistry::getCurShader() const
+{
+ return m_pCurShader;
+}
+
+void ShaderRegistry::setCurShader(const std::string& sID)
+{
+ if (sID == "") {
+ m_pCurShader = OGLShaderPtr();
+ } else {
+ m_pCurShader = getShader(sID);
+ }
+}
+
+void ShaderRegistry::loadShaderString(const string& sFilename, string& sPreprocessed)
+{
+ string sShaderCode;
+ readWholeFile(sFilename, sShaderCode);
+ preprocess(sShaderCode, sFilename, sPreprocessed);
+}
+
+void ShaderRegistry::preprocess(const string& sShaderCode, const string& sFileName,
+ string& sProcessed)
+{
+ sProcessed.append("#line 0\n");
+ istringstream stream(sShaderCode);
+ string sCurLine;
+ int curLine = 0;
+ while(getline(stream, sCurLine)) {
+ curLine++;
+ string sStripped = removeStartEndSpaces(sCurLine);
+ if (sStripped.substr(0, 8) == "#include") {
+ size_t startPos = sStripped.find('"');
+ size_t endPos = sStripped.find('"', startPos+1);
+ if (startPos == string::npos || endPos == string::npos) {
+ throwParseError(sFileName, curLine);
+ }
+ string sIncFileName = sStripped.substr(startPos+1, endPos-startPos-1);
+ sIncFileName = s_sLibPath+"/"+sIncFileName;
+ string sIncludedFile;
+ readWholeFile(sIncFileName, sIncludedFile);
+ string sProcessedIncludedFile;
+ preprocess(sIncludedFile, sIncFileName, sProcessedIncludedFile);
+ sProcessed.append(sProcessedIncludedFile);
+ sProcessed.append("#line "+toString(curLine)+"\n");
+ } else {
+ sProcessed.append(sCurLine+"\n");
+ }
+ }
+}
+
+string ShaderRegistry::createPrefixString(bool bFragment)
+{
+ stringstream ss;
+ std::map<std::string, std::string>::iterator it;
+ for (it = m_PreprocessorDefinesMap.begin(); it != m_PreprocessorDefinesMap.end();
+ ++it)
+ {
+ ss << "#define " << it->first << " " << it->second << endl;
+ }
+ if (GLContext::getCurrent()->isGLES()) {
+ ss << endl;
+ if (bFragment) {
+ ss << "#extension GL_OES_standard_derivatives : enable" << endl;
+ }
+ ss << "precision mediump float;" << endl;
+ }
+ return ss.str();
+}
+
+void ShaderRegistry::throwParseError(const string& sFileName, int curLine)
+{
+ throw Exception(AVG_ERR_VIDEO_GENERAL, "File '"+sFileName+"', Line "+
+ toString(curLine)+": Syntax error.");
+}
+
+void createShader(const std::string& sID)
+{
+ return ShaderRegistry::get()->createShader(sID);
+}
+
+OGLShaderPtr getShader(const std::string& sID)
+{
+ return ShaderRegistry::get()->getShader(sID);
+}
+
+}
+