00001 #ifndef GLW_UTILITY_H 00002 #define GLW_UTILITY_H 00003 00004 #include <stdio.h> 00005 #include <stddef.h> 00006 00007 #include <string> 00008 #include <sstream> 00009 #include <map> 00010 #include <vector> 00011 00012 #include "./context.h" 00013 00014 #define GLW_STRINGIFY(S) #S 00015 #define GLW_OFFSET_OF(TYPE, MEMBER) ((const void *)(offsetof(TYPE, MEMBER))) 00016 00017 namespace glw 00018 { 00019 00020 class ShaderHeaderBuilder 00021 { 00022 public: 00023 00024 typedef void BaseType; 00025 typedef ShaderHeaderBuilder ThisType; 00026 00027 void clear(void) 00028 { 00029 this->m_version .clear(); 00030 this->m_extensions .clear(); 00031 this->m_defines .clear(); 00032 this->m_texts .clear(); 00033 } 00034 00035 ThisType & version(const std::string & v) 00036 { 00037 this->m_version = v; 00038 return (*this); 00039 } 00040 00041 ThisType & enableExtension(const std::string & ext) 00042 { 00043 this->m_extensions[ext] = ThisType::Enable; 00044 return (*this); 00045 } 00046 00047 ThisType & disableExtension(const std::string & ext) 00048 { 00049 this->m_extensions[ext] = ThisType::Disable; 00050 return (*this); 00051 } 00052 00053 ThisType & requireExtension(const std::string & ext) 00054 { 00055 this->m_extensions[ext] = ThisType::Require; 00056 return (*this); 00057 } 00058 00059 ThisType & define(const std::string & name, const std::string & value) 00060 { 00061 this->m_defines[name] = value; 00062 return (*this); 00063 } 00064 00065 ThisType & text(const std::string & txt) 00066 { 00067 this->m_texts.push_back(txt); 00068 return (*this); 00069 } 00070 00071 std::string toString(void) const 00072 { 00073 const char * extModeMap[] = 00074 { 00075 "", 00076 "enable", 00077 "disable", 00078 "require" 00079 }; 00080 00081 std::ostringstream res; 00082 00083 if (!this->m_version.empty()) 00084 { 00085 res << "#version " << this->m_version << std::endl; 00086 res << std::endl; 00087 } 00088 00089 if (!this->m_extensions.empty()) 00090 { 00091 for (ExtensionMapConstIterator it=this->m_extensions.begin(); it!=this->m_extensions.end(); ++it) 00092 { 00093 if (it->second == ThisType::DontCare) continue; 00094 res << "#extension " << it->first << " : " << extModeMap[it->second] << std::endl; 00095 } 00096 res << std::endl; 00097 } 00098 00099 if (!this->m_defines.empty()) 00100 { 00101 for (DefineMapConstIterator it=this->m_defines.begin(); it!=this->m_defines.end(); ++it) 00102 { 00103 res << "#define " << it->first << " " << it->second << std::endl; 00104 } 00105 res << std::endl; 00106 } 00107 00108 if (!this->m_texts.empty()) 00109 { 00110 for (size_t i=0; i<this->m_texts.size(); ++i) 00111 { 00112 res << this->m_texts[i] << std::endl; 00113 } 00114 res << std::endl; 00115 } 00116 00117 return res.str(); 00118 } 00119 00120 protected: 00121 00122 enum ExtensionMode 00123 { 00124 DontCare = 0, 00125 Enable, 00126 Disable, 00127 Require 00128 }; 00129 00130 typedef std::map<std::string, ExtensionMode> ExtensionMap; 00131 typedef ExtensionMap::const_iterator ExtensionMapConstIterator; 00132 typedef ExtensionMap::iterator ExtensionMapIterator; 00133 typedef ExtensionMap::value_type ExtensionMapValue; 00134 00135 typedef std::map<std::string, std::string> DefineMap; 00136 typedef DefineMap::const_iterator DefineMapConstIterator; 00137 typedef DefineMap::iterator DefineMapIterator; 00138 typedef DefineMap::value_type DefineMapValue; 00139 00140 typedef std::vector<std::string> TextVector; 00141 00142 std::string m_version; 00143 ExtensionMap m_extensions; 00144 DefineMap m_defines; 00145 TextVector m_texts; 00146 }; 00147 00148 inline std::string readTextFile(const char * fileName) 00149 { 00150 std::string r; 00151 if (fileName == 0) return r; 00152 00153 FILE * f = fopen(fileName, "rb"); 00154 if (f == 0) return r; 00155 00156 fseek(f, 0, SEEK_END); 00157 const size_t sz = size_t(ftell(f)); 00158 rewind(f); 00159 00160 char * str = new char [sz + 1]; 00161 fread(str, sizeof(char), sz / sizeof(char), f); 00162 fclose(f); 00163 00164 str[sz] = '\0'; 00165 r = str; 00166 delete [] str; 00167 00168 return r; 00169 } 00170 00171 inline std::string readTextFile(const std::string & fileName) 00172 { 00173 return readTextFile(fileName.c_str()); 00174 } 00175 00176 inline BufferHandle createBuffer(Context & ctx, GLsizeiptr size, const void * data = 0, GLenum usage = GL_STATIC_DRAW) 00177 { 00178 BufferArguments args; 00179 args.size = size; 00180 args.usage = usage; 00181 args.data = data; 00182 return ctx.createBuffer(args); 00183 } 00184 00185 template <typename TValue, typename TAllocator> 00186 inline BufferHandle createBuffer(Context & ctx, const std::vector<TValue, TAllocator> & data, GLenum usage = GL_STATIC_DRAW) 00187 { 00188 return createBuffer(ctx, GLsizeiptr(sizeof(TValue) * data.size()), ((!data.empty()) ? (&(data[0])) : (0)), usage); 00189 } 00190 00191 inline RenderbufferHandle createRenderbuffer(Context & ctx, GLenum format, GLsizei width, GLsizei height) 00192 { 00193 RenderbufferArguments args; 00194 args.format = format; 00195 args.width = width; 00196 args.height = height; 00197 return ctx.createRenderbuffer(args); 00198 } 00199 00200 inline Texture2DHandle createTexture2D(Context & ctx, GLenum format, GLsizei width, GLsizei height, GLenum dataFormat, GLenum dataType, const void * data = 0, const TextureSampleMode & sampler = TextureSampleMode()) 00201 { 00202 Texture2DArguments args; 00203 args.format = format; 00204 args.width = width; 00205 args.height = height; 00206 args.dataFormat = dataFormat; 00207 args.dataType = dataType; 00208 args.data = data; 00209 args.sampler = sampler; 00210 return ctx.createTexture2D(args); 00211 } 00212 00213 inline TextureCubeHandle createTextureCube(Context & ctx, GLenum format, GLsizei size, GLenum dataFormat, GLenum dataType, const void * data = 0, const TextureSampleMode & sampler = TextureSampleMode()) 00214 { 00215 TextureCubeArguments args; 00216 args.format = format; 00217 args.size = size; 00218 args.dataFormat = dataFormat; 00219 args.dataType = dataType; 00220 args.data = data; 00221 args.sampler = sampler; 00222 return ctx.createTextureCube(args); 00223 } 00224 00225 inline FramebufferHandle createFramebufferWithDepthStencil 00226 ( 00227 Context & ctx, 00228 const RenderTarget & depthTarget, 00229 const RenderTarget & stencilTarget, 00230 const RenderTarget & colorTarget0 = RenderTarget(), 00231 const RenderTarget & colorTarget1 = RenderTarget(), 00232 const RenderTarget & colorTarget2 = RenderTarget(), 00233 const RenderTarget & colorTarget3 = RenderTarget(), 00234 const RenderTarget & colorTarget4 = RenderTarget(), 00235 const RenderTarget & colorTarget5 = RenderTarget(), 00236 const RenderTarget & colorTarget6 = RenderTarget(), 00237 const RenderTarget & colorTarget7 = RenderTarget() 00238 ) 00239 { 00240 FramebufferArguments args; 00241 00242 args.depthTarget = depthTarget; 00243 args.stencilTarget = stencilTarget; 00244 00245 if (colorTarget0.target) { args.colorTargets[0] = colorTarget0; args.targetInputs[0] = 0; } 00246 if (colorTarget1.target) { args.colorTargets[1] = colorTarget1; args.targetInputs[1] = 1; } 00247 if (colorTarget2.target) { args.colorTargets[2] = colorTarget2; args.targetInputs[2] = 2; } 00248 if (colorTarget3.target) { args.colorTargets[3] = colorTarget3; args.targetInputs[3] = 3; } 00249 if (colorTarget4.target) { args.colorTargets[4] = colorTarget4; args.targetInputs[4] = 4; } 00250 if (colorTarget5.target) { args.colorTargets[5] = colorTarget5; args.targetInputs[5] = 5; } 00251 if (colorTarget6.target) { args.colorTargets[6] = colorTarget6; args.targetInputs[6] = 6; } 00252 if (colorTarget7.target) { args.colorTargets[7] = colorTarget7; args.targetInputs[7] = 7; } 00253 00254 return ctx.createFramebuffer(args); 00255 } 00256 00257 inline FramebufferHandle createFramebuffer 00258 ( 00259 Context & ctx, 00260 const RenderTarget & depthTarget, 00261 const RenderTarget & colorTarget0 = RenderTarget(), 00262 const RenderTarget & colorTarget1 = RenderTarget(), 00263 const RenderTarget & colorTarget2 = RenderTarget(), 00264 const RenderTarget & colorTarget3 = RenderTarget(), 00265 const RenderTarget & colorTarget4 = RenderTarget(), 00266 const RenderTarget & colorTarget5 = RenderTarget(), 00267 const RenderTarget & colorTarget6 = RenderTarget(), 00268 const RenderTarget & colorTarget7 = RenderTarget() 00269 ) 00270 { 00271 RenderTarget nullTarget; 00272 return createFramebufferWithDepthStencil(ctx, depthTarget, nullTarget, colorTarget0, colorTarget1, colorTarget2, colorTarget3, colorTarget4, colorTarget5, colorTarget6, colorTarget7); 00273 } 00274 00275 inline ProgramHandle createProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexSrc, const std::string & geometrySrc, const std::string & fragmentSrc, const ProgramArguments & args = ProgramArguments()) 00276 { 00277 ProgramArguments pArgs = args; 00278 00279 if (!vertexSrc.empty()) 00280 { 00281 VertexShaderArguments args; 00282 args.source = srcPrefix + vertexSrc; 00283 pArgs.shaders.push_back(ctx.createVertexShader(args)); 00284 } 00285 00286 if (!geometrySrc.empty()) 00287 { 00288 GeometryShaderArguments args; 00289 args.source = srcPrefix + geometrySrc; 00290 pArgs.shaders.push_back(ctx.createGeometryShader(args)); 00291 } 00292 00293 if (!fragmentSrc.empty()) 00294 { 00295 FragmentShaderArguments args; 00296 args.source = srcPrefix + fragmentSrc; 00297 pArgs.shaders.push_back(ctx.createFragmentShader(args)); 00298 } 00299 00300 return ctx.createProgram(pArgs); 00301 } 00302 00303 inline ProgramHandle createProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexSrc, const std::string & fragmentSrc, const ProgramArguments & args = ProgramArguments()) 00304 { 00305 return createProgram(ctx, srcPrefix, vertexSrc, "", fragmentSrc, args); 00306 } 00307 00308 inline ProgramHandle loadProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexFile, const std::string & geometryFile, const std::string & fragmentFile, const ProgramArguments & args = ProgramArguments()) 00309 { 00310 return createProgram(ctx, srcPrefix, readTextFile(vertexFile), readTextFile(geometryFile), readTextFile(fragmentFile), args); 00311 } 00312 00313 inline ProgramHandle loadProgram(Context & ctx, const std::string & srcPrefix, const std::string & vertexFile, const std::string & fragmentFile, const ProgramArguments & args = ProgramArguments()) 00314 { 00315 return loadProgram(ctx, srcPrefix, vertexFile, "", fragmentFile.c_str(), args); 00316 } 00317 00318 }; 00319 00320 #endif // GLW_UTILITY_H