1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef BACKENDS_GRAPHICS_OPENGL_SHADER_H
24 #define BACKENDS_GRAPHICS_OPENGL_SHADER_H
25 
26 #include "backends/graphics/opengl/opengl-sys.h"
27 
28 #if !USE_FORCED_GLES
29 
30 #include "common/singleton.h"
31 #include "common/hash-str.h"
32 #include "common/ptr.h"
33 
34 namespace OpenGL {
35 
36 /**
37  * A generic uniform value interface for a shader program.
38  */
39 class ShaderUniformValue {
40 public:
~ShaderUniformValue()41 	virtual ~ShaderUniformValue() {}
42 
43 	/**
44 	 * Setup the the value to the given location.
45 	 *
46 	 * @param location Location of the uniform.
47 	 */
48 	virtual void set(GLint location) const = 0;
49 };
50 
51 /**
52  * Integer value for a shader uniform.
53  */
54 class ShaderUniformInteger : public ShaderUniformValue {
55 public:
ShaderUniformInteger(GLint value)56 	ShaderUniformInteger(GLint value) : _value(value) {}
57 
58 	virtual void set(GLint location) const override;
59 
60 private:
61 	const GLint _value;
62 };
63 
64 /**
65  * Float value for a shader uniform.
66  */
67 class ShaderUniformFloat : public ShaderUniformValue {
68 public:
ShaderUniformFloat(GLfloat value)69 	ShaderUniformFloat(GLfloat value) : _value(value) {}
70 
71 	virtual void set(GLint location) const override;
72 
73 private:
74 	const GLfloat _value;
75 };
76 
77 /**
78  * 4x4 Matrix value for a shader uniform.
79  */
80 class ShaderUniformMatrix44 : public ShaderUniformValue {
81 public:
ShaderUniformMatrix44(const GLfloat * mat44)82 	ShaderUniformMatrix44(const GLfloat *mat44) {
83 		memcpy(_matrix, mat44, sizeof(_matrix));
84 	}
85 
86 	virtual void set(GLint location) const override;
87 
88 private:
89 	GLfloat _matrix[4*4];
90 };
91 
92 class Shader {
93 public:
94 	Shader(const Common::String &vertex, const Common::String &fragment);
95 	~Shader();
96 
97 	/**
98 	 * Destroy the shader program.
99 	 *
100 	 * This keeps the vertex and fragment shader sources around and thus
101 	 * allows for recreating the shader on context recreation. It also keeps
102 	 * the uniform state around.
103 	 */
104 	void destroy();
105 
106 	/**
107 	 * Recreate shader program.
108 	 *
109 	 * @return true on success, false on failure.
110 	 */
111 	bool recreate();
112 
113 	/**
114 	 * Make shader active.
115 	 */
116 	void activate();
117 
118 	/**
119 	 * Make shader inactive.
120 	 */
121 	void deactivate();
122 
123 	/**
124 	 * Return location for attribute with given name.
125 	 *
126 	 * @param name Name of the attribute to look up in the shader.
127 	 * @return The loctaion of -1 if attribute was not found.
128 	 */
129 	GLint getAttributeLocation(const char *name) const;
getAttributeLocation(const Common::String & name)130 	GLint getAttributeLocation(const Common::String &name) const {
131 		return getAttributeLocation(name.c_str());
132 	}
133 
134 	/**
135 	 * Return location for uniform with given name.
136 	 *
137 	 * @param name Name of the uniform to look up in the shader.
138 	 * @return The location or -1 if uniform was not found.
139 	 */
140 	GLint getUniformLocation(const char *name) const;
getUniformLocation(const Common::String & name)141 	GLint getUniformLocation(const Common::String &name) const {
142 		return getUniformLocation(name.c_str());
143 	}
144 
145 	/**
146 	 * Bind value to uniform.
147 	 *
148 	 * @param name  The name of the uniform to be set.
149 	 * @param value The value to be set.
150 	 * @return 'false' on error (i.e. uniform unknown or otherwise),
151 	 *         'true' otherwise.
152 	 */
153 	bool setUniform(const Common::String &name, ShaderUniformValue *value);
154 
155 	/**
156 	 * Bind integer value to uniform.
157 	 *
158 	 * @param name  The name of the uniform to be set.
159 	 * @param value The value to be set.
160 	 * @return 'false' on error (i.e. uniform unknown or otherwise),
161 	 *         'true' otherwise.
162 	 */
setUniform1I(const Common::String & name,GLint value)163 	bool setUniform1I(const Common::String &name, GLint value) {
164 		return setUniform(name, new ShaderUniformInteger(value));
165 	}
166 protected:
167 	/**
168 	 * Vertex shader sources.
169 	 */
170 	const Common::String _vertex;
171 
172 	/**
173 	 * Fragment shader sources.
174 	 */
175 	const Common::String _fragment;
176 
177 	/**
178 	 * Whether the shader is active or not.
179 	 */
180 	bool _isActive;
181 
182 	/**
183 	 * Shader program handle.
184 	 */
185 	GLprogram _program;
186 
187 	/**
188 	 * A uniform descriptor.
189 	 *
190 	 * This stores the state of a shader uniform. The state is made up of the
191 	 * uniform location, whether the state was altered since last set, and the
192 	 * value of the uniform.
193 	 */
194 	struct Uniform {
UniformUniform195 		Uniform() : location(-1), altered(false), value() {}
UniformUniform196 		Uniform(GLint loc, ShaderUniformValue *val)
197 		    : location(loc), altered(true), value(val) {}
198 
199 		/**
200 		 * Write uniform value into currently active shader.
201 		 */
setUniform202 		void set() {
203 			if (altered && value) {
204 				value->set(location);
205 				altered = false;
206 			}
207 		}
208 
209 		/**
210 		 * The location of the uniform or -1 in case it does not exist.
211 		 */
212 		GLint location;
213 
214 		/**
215 		 * Whether the uniform state was aletered since last 'set'.
216 		 */
217 		bool altered;
218 
219 		/**
220 		 * The value of the uniform.
221 		 */
222 		Common::SharedPtr<ShaderUniformValue> value;
223 	};
224 
225 	typedef Common::HashMap<Common::String, Uniform> UniformMap;
226 
227 	/**
228 	 * Map from uniform name to associated uniform description.
229 	 */
230 	UniformMap _uniforms;
231 
232 	/**
233 	 * Compile a vertex or fragment shader.
234 	 *
235 	 * @param source     Sources to the shader.
236 	 * @param shaderType Type of shader to compile (GL_FRAGMENT_SHADER_ARB or
237 	 *                   GL_VERTEX_SHADER_ARB)
238 	 * @return The shader object or 0 on failure.
239 	 */
240 	static GLshader compileShader(const char *source, GLenum shaderType);
241 };
242 
243 class ShaderManager : public Common::Singleton<ShaderManager> {
244 public:
245 	enum ShaderUsage {
246 		/** Default shader implementing the GL fixed-function pipeline. */
247 		kDefault = 0,
248 
249 		/** CLUT8 look up shader. */
250 		kCLUT8LookUp,
251 
252 		/** Number of built-in shaders. Should not be used for query. */
253 		kMaxUsages
254 	};
255 
256 	/**
257 	 * Notify shader manager about context destruction.
258 	 */
259 	void notifyDestroy();
260 
261 	/**
262 	 * Notify shader manager about context creation.
263 	 */
264 	void notifyCreate();
265 
266 	/**
267 	 * Query a built-in shader.
268 	 */
269 	Shader *query(ShaderUsage shader) const;
270 
271 private:
272 	friend class Common::Singleton<SingletonBaseType>;
273 	ShaderManager();
274 	~ShaderManager();
275 
276 	bool _initializeShaders;
277 
278 	Shader *_builtIn[kMaxUsages];
279 };
280 
281 } // End of namespace OpenGL
282 
283 /** Shortcut for accessing the font manager. */
284 #define ShaderMan (OpenGL::ShaderManager::instance())
285 
286 #endif // !USE_FORCED_GLES
287 
288 #endif
289