1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 #include "Rendering/GL/myGL.h"
4
5 #include "Rendering/Shaders/ShaderHandler.h"
6 #include "Rendering/GlobalRendering.h"
7 #include "System/Log/ILog.h"
8 #include "System/Util.h"
9
10 #include <cassert>
11
12
GetInstance()13 CShaderHandler* CShaderHandler::GetInstance() {
14 static CShaderHandler shaHandler;
15 return &shaHandler;
16 }
17
18
ReloadAll()19 void CShaderHandler::ReloadAll() {
20 for (std::map<std::string, ProgramObjMap>::iterator it = programObjects.begin(); it != programObjects.end(); ++it) {
21 for (ProgramObjMapIt jt = it->second.begin(); jt != it->second.end(); ++jt) {
22 (jt->second)->Reload(true);
23 }
24 }
25 }
26
27
ReleaseProgramObjects(const std::string & poClass)28 void CShaderHandler::ReleaseProgramObjects(const std::string& poClass) {
29 if (programObjects.find(poClass) == programObjects.end()) {
30 return;
31 }
32
33 for (ProgramObjMapIt it = programObjects[poClass].begin(); it != programObjects[poClass].end(); ++it) {
34 // free the program object and its attachments
35 if (it->second != Shader::nullProgramObject) {
36 (it->second)->Release(); delete (it->second);
37 }
38 }
39
40 programObjects[poClass].clear();
41 programObjects.erase(poClass);
42 }
43
44
GetProgramObject(const std::string & poClass,const std::string & poName)45 Shader::IProgramObject* CShaderHandler::GetProgramObject(const std::string& poClass, const std::string& poName) {
46 if (programObjects.find(poClass) != programObjects.end()) {
47 if (programObjects[poClass].find(poName) != programObjects[poClass].end()) {
48 return (programObjects[poClass][poName]);
49 }
50 }
51 return NULL;
52 }
53
54
CreateProgramObject(const std::string & poClass,const std::string & poName,bool arbProgram)55 Shader::IProgramObject* CShaderHandler::CreateProgramObject(const std::string& poClass, const std::string& poName, bool arbProgram) {
56 Shader::IProgramObject* po = Shader::nullProgramObject;
57
58 if (programObjects.find(poClass) != programObjects.end()) {
59 if (programObjects[poClass].find(poName) != programObjects[poClass].end()) {
60 LOG_L(L_WARNING, "[%s] There is already a shader program named \"%s\"!",
61 __FUNCTION__, poName.c_str());
62 return (programObjects[poClass][poName]);
63 }
64 } else {
65 programObjects[poClass] = ProgramObjMap();
66 }
67
68 if (arbProgram) {
69 if (globalRendering->haveARB) {
70 po = new Shader::ARBProgramObject(poName);
71 }
72 } else {
73 if (globalRendering->haveGLSL) {
74 po = new Shader::GLSLProgramObject(poName);
75 }
76 }
77
78 if (po == Shader::nullProgramObject) {
79 LOG_L(L_ERROR, "[%s] Tried to create \"%s\" a %s shader program on hardware w/o support for it!",
80 __FUNCTION__, poName.c_str(), arbProgram ? "ARB" : "GLSL");
81 }
82
83 programObjects[poClass][poName] = po;
84 return po;
85 }
86
87
88
CreateShaderObject(const std::string & soName,const std::string & soDefs,int soType)89 Shader::IShaderObject* CShaderHandler::CreateShaderObject(const std::string& soName, const std::string& soDefs, int soType) {
90 assert(!soName.empty());
91
92 const std::string lowerSoName = StringToLower(soName);
93
94 const bool arbShader = (lowerSoName.find("arb") != std::string::npos);
95 /*
96 const bool arbShader =
97 lowerSoName.find(".glsl") == std::string::npos &&
98 lowerSoName.find(".vert") == std::string::npos &&
99 lowerSoName.find(".frag") == std::string::npos;
100 */
101 Shader::IShaderObject* so = Shader::nullShaderObject;
102
103 switch (soType) {
104 case GL_VERTEX_PROGRAM_ARB:
105 case GL_FRAGMENT_PROGRAM_ARB: {
106 assert(arbShader);
107
108 if (globalRendering->haveARB) {
109 so = new Shader::ARBShaderObject(soType, soName);
110 }
111 } break;
112
113 default: {
114 // assume GLSL shaders by default
115 assert(!arbShader);
116
117 if (globalRendering->haveGLSL) {
118 so = new Shader::GLSLShaderObject(soType, soName, soDefs);
119 }
120 } break;
121 }
122
123 if (so == Shader::nullShaderObject) {
124 LOG_L(L_ERROR, "[%s] Tried to create a %s shader (\"%s\") on hardware that does not support them!",
125 __FUNCTION__, arbShader? "ARB": "GLSL", soName.c_str());
126 return so;
127 }
128
129 so->Compile(true);
130 return so;
131 }
132