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