1 #ifndef GLW_SHADER_H
2 #define GLW_SHADER_H
3 
4 #include <string>
5 #include <iostream>
6 
7 #include "./object.h"
8 
9 namespace glw
10 {
11 
12 class ShaderArguments : public ObjectArguments
13 {
14 	public:
15 
16 		typedef ObjectArguments BaseType;
17 		typedef ShaderArguments ThisType;
18 
19 		std::string source;
20 
ShaderArguments(void)21 		ShaderArguments(void)
22 			: BaseType()
23 		{
24 			;
25 		}
26 
clear(void)27 		void clear(void)
28 		{
29 			BaseType::clear();
30 			this->source.clear();
31 		}
32 };
33 
34 class Shader : public Object
35 {
36 	friend class Context;
37 
38 	public:
39 
40 		typedef Object BaseType;
41 		typedef Shader ThisType;
42 
~Shader(void)43 		virtual ~Shader(void)
44 		{
45 			this->destroy();
46 		}
47 
source(void)48 		const std::string & source(void) const
49 		{
50 			return this->m_source;
51 		}
52 
log(void)53 		const std::string & log(void) const
54 		{
55 			return this->m_log;
56 		}
57 
isCompiled(void)58 		bool isCompiled(void) const
59 		{
60 			return this->m_compiled;
61 		}
62 
63 	protected:
64 
65 		std::string  m_source;
66 		std::string  m_log;
67 		bool         m_compiled;
68 
Shader(Context * ctx)69 		Shader(Context * ctx)
70 			: BaseType   (ctx)
71 			, m_compiled (false)
72 		{
73 			;
74 		}
75 
76 		virtual GLenum shaderType(void) const = 0;
77 
create(const ShaderArguments & args)78 		bool create(const ShaderArguments & args)
79 		{
80 			this->destroy();
81 			const GLenum shType = this->shaderType();
82 			this->m_name = glCreateShader(shType);
83 			this->compile(args.source);
84 			return this->m_compiled;
85 		}
86 
doDestroy(void)87 		virtual void doDestroy(void)
88 		{
89 			glDeleteShader(this->m_name);
90 			this->m_source.clear();
91 			this->m_log.clear();
92 			this->m_compiled = false;
93 		}
94 
doIsValid(void)95 		virtual bool doIsValid(void) const
96 		{
97 			return this->m_compiled;
98 		}
99 
compile(const std::string & source)100 		void compile(const std::string & source)
101 		{
102 			const char * src = source.c_str();
103 			glShaderSource(this->m_name, 1, &src, 0);
104 			glCompileShader(this->m_name);
105 
106 			GLint compileStatus = 0;
107 			glGetShaderiv(this->m_name, GL_COMPILE_STATUS, &compileStatus);
108 
109 			this->m_source   = source;
110 			this->m_log      = ThisType::getInfoLog(this->m_name);
111 			this->m_compiled = (compileStatus != GL_FALSE);
112 
113 #if GLW_PRINT_LOG_TO_STDERR
114 			std::cerr << "---------------------------" << std::endl;
115 			std::cerr << "[";
116 			switch (this->shaderType())
117 			{
118 				case GL_VERTEX_SHADER   : std::cerr << "Vertex ";   break;
119 				case GL_GEOMETRY_SHADER : std::cerr << "Geometry "; break;
120 				case GL_FRAGMENT_SHADER : std::cerr << "Fragment "; break;
121 				default: break;
122 			}
123 			std::cerr << "Shader Compile Log]: " << ((this->m_compiled) ? ("OK") : ("FAILED")) << std::endl;
124 			std::cerr << this->m_log << std::endl;
125 			std::cerr << "---------------------------" << std::endl;
126 #endif
127 		}
128 
129 	private:
130 
getInfoLog(GLuint Shader)131 		static std::string getInfoLog(GLuint Shader)
132 		{
133 			std::string log;
134 
135 			GLint logLen = 0;
136 			glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &logLen);
137 			if (logLen > 0)
138 			{
139 				char * sLog = new char[logLen + 1];
140 				glGetShaderInfoLog(Shader, logLen, &logLen, sLog);
141 				if (logLen > 0)
142 				{
143 					if (sLog[0] != '\0')
144 					{
145 						sLog[logLen - 1] = '\0';
146 						log = sLog;
147 					}
148 				}
149 				delete [] sLog;
150 			}
151 			return log;
152 		}
153 };
154 
155 namespace detail { template <> struct BaseOf <Shader> { typedef Object Type; }; };
156 typedef   detail::ObjectSharedPointerTraits  <Shader> ::Type ShaderPtr;
157 
158 class SafeShader : public SafeObject
159 {
160 	friend class Context;
161 	friend class BoundShader;
162 
163 	public:
164 
165 		typedef SafeObject BaseType;
166 		typedef SafeShader ThisType;
167 
168 		SafeShader(void)
169 			: BaseType()
170 		{
171 			;
172 		}
173 
174 		const std::string & source(void) const
175 		{
176 			return this->object()->source();
177 		}
178 
179 		const std::string & log(void) const
180 		{
181 			return this->object()->log();
182 		}
183 
184 		bool isCompiled(void) const
185 		{
186 			return this->object()->isCompiled();
187 		}
188 
189 	protected:
190 
191 		SafeShader(const ShaderPtr & shader)
192 			: BaseType(shader)
193 		{
194 			;
195 		}
196 
197 		const ShaderPtr & object(void) const
198 		{
199 			return static_cast<const ShaderPtr &>(BaseType::object());
200 		}
201 
202 		ShaderPtr & object(void)
203 		{
204 			return static_cast<ShaderPtr &>(BaseType::object());
205 		}
206 };
207 
208 namespace detail { template <> struct BaseOf     <SafeShader> { typedef SafeObject Type; }; };
209 namespace detail { template <> struct ObjectBase <SafeShader> { typedef Shader     Type; }; };
210 namespace detail { template <> struct ObjectSafe <Shader    > { typedef SafeShader Type; }; };
211 typedef   detail::ObjectSharedPointerTraits      <SafeShader> ::Type ShaderHandle;
212 
213 class ShaderBindingParams : public ObjectBindingParams
214 {
215 	public:
216 
217 		typedef ObjectBindingParams BaseType;
218 		typedef ShaderBindingParams ThisType;
219 
220 		ShaderBindingParams(void)
221 			: BaseType()
222 		{
223 			;
224 		}
225 
226 		ShaderBindingParams(GLenum aTarget, GLenum aUnit)
227 			: BaseType(aTarget, aUnit)
228 		{
229 			;
230 		}
231 };
232 
233 class BoundShader : public BoundObject
234 {
235 	friend class Context;
236 
237 	public:
238 
239 		typedef BoundObject BaseType;
240 		typedef BoundShader ThisType;
241 
242 		BoundShader(void)
243 			: BaseType()
244 		{
245 			;
246 		}
247 
248 		const ShaderHandle & handle(void) const
249 		{
250 			return static_cast<const ShaderHandle &>(BaseType::handle());
251 		}
252 
253 		ShaderHandle & handle(void)
254 		{
255 			return static_cast<ShaderHandle &>(BaseType::handle());
256 		}
257 
258 	protected:
259 
260 		BoundShader(const ShaderHandle & handle, const ShaderBindingParams & params)
261 			: BaseType(handle, params)
262 		{
263 			;
264 		}
265 
266 		const ShaderPtr & object(void) const
267 		{
268 			return this->handle()->object();
269 		}
270 
271 		ShaderPtr & object(void)
272 		{
273 			return this->handle()->object();
274 		}
275 
276 		virtual void bind(void)
277 		{
278 			;
279 		}
280 
281 		virtual void unbind(void)
282 		{
283 			;
284 		}
285 };
286 
287 namespace detail { template <> struct ParamsOf    <BoundShader> { typedef ShaderBindingParams Type; }; };
288 namespace detail { template <> struct BaseOf      <BoundShader> { typedef BoundObject Type; }; };
289 namespace detail { template <> struct ObjectBase  <BoundShader> { typedef Shader      Type; }; };
290 namespace detail { template <> struct ObjectBound <Shader     > { typedef BoundShader Type; }; };
291 typedef   detail::ObjectSharedPointerTraits       <BoundShader> ::Type  BoundShaderHandle;
292 
293 };
294 
295 #endif // GLW_SHADER_H
296