Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/toolx/sg/GL_manager is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef toolx_sg_GL_manager
0005 #define toolx_sg_GL_manager
0006 
0007 #ifndef GL_VERSION_1_1
0008   #error You have to include OpenGL header(s) before including this file.
0009 #endif
0010 
0011 #include <tools/sg/render_manager>
0012 #include <tools/mapmanip>
0013 #include <tools/carray>
0014 #include <tools/num2s>
0015 #ifdef TOOLS_USE_GL_VERSION_3_2
0016 #include <tools/lina/mat4f>
0017 #endif
0018 
0019 #include <sstream>
0020 
0021 #include <cmath> //::sqrt
0022 
0023 
0024 namespace toolx {
0025 namespace sg {
0026 
0027 template <class GL_FUNCTIONS>
0028 class gsto_elem: protected GL_FUNCTIONS {
0029   TOOLS_T_SCLASS(GL_FUNCTIONS,toolx::sg::gsto_elem)
0030   using parent_gl_functions = GL_FUNCTIONS;
0031 public:
0032   enum kind {
0033     kind_texture,
0034     kind_buffer,
0035     kind_list,
0036     kind_memory
0037   };
0038 public:
0039 #ifdef TOOLS_USE_GL_VERSION_3_2
0040   gsto_elem(kind a_kind,unsigned int a_gl_id,size_t a_size,const float* a_data,unsigned int a_vao_id = 0)
0041   :m_gl_id(a_gl_id)
0042   ,m_vao_id(a_vao_id)
0043 #else
0044   gsto_elem(kind a_kind,unsigned int a_gl_id,size_t a_size,const float* a_data)
0045   :m_gl_id(a_gl_id)
0046 #endif
0047   ,m_kind(a_kind)
0048   ,m_size(a_size)
0049   ,m_data(0)
0050   {
0051     if(a_data) {
0052       size_t num = m_size/sizeof(float);
0053       m_data = new float[num];
0054       ::memcpy(m_data,a_data,m_size);
0055     }
0056   }
0057   virtual ~gsto_elem() {
0058     if(m_kind==kind_texture) {
0059       parent_gl_functions::gl__DeleteTextures(1,&m_gl_id);
0060     } else if(m_kind==kind_buffer) {
0061 #ifdef TOOLS_USE_GL_VERSION_3_2
0062       parent_gl_functions::gl__DeleteBuffers(1,&m_gl_id);
0063       parent_gl_functions::gl__DeleteVertexArrays(1,&m_vao_id);
0064 #endif
0065     } else if(m_kind==kind_list) {
0066       if(m_gl_id) {
0067 #ifndef TOOLS_USE_GL_VERSION_3_2
0068         parent_gl_functions::gl__DeleteLists(m_gl_id,1);
0069 #endif
0070       }
0071     }
0072 
0073     if(m_data) {
0074       delete [] m_data;
0075     }
0076   }
0077 private:
0078   gsto_elem(const gsto_elem& a_from)
0079   :parent_gl_functions(a_from)
0080   ,m_gl_id(a_from.m_gl_id)
0081 #ifdef TOOLS_USE_GL_VERSION_3_2
0082   ,m_vao_id(a_from.m_vao_id)
0083 #endif
0084   ,m_kind(a_from.m_kind)
0085   ,m_size(a_from.m_size)
0086   ,m_data(0)
0087   {
0088     if(a_from.m_data) {
0089       size_t num = m_size/sizeof(float);
0090       m_data = new float[num];
0091       ::memcpy(m_data,a_from.m_data,m_size);
0092     }
0093   }
0094   gsto_elem& operator=(const gsto_elem& a_from){
0095     if(&a_from==this) return *this;
0096     m_gl_id = a_from.m_gl_id;
0097 #ifdef TOOLS_USE_GL_VERSION_3_2
0098     m_vao_id = a_from.m_vao_id;
0099 #endif
0100     m_kind = a_from.m_kind;
0101     m_size = a_from.m_size;
0102     if(m_data) {
0103       delete [] m_data;
0104       m_data = 0;
0105     }
0106     if(a_from.m_data) {
0107       size_t num = m_size/sizeof(float);
0108       m_data = new float[num];
0109       ::memcpy(m_data,a_from.m_data,m_size);
0110     }
0111     return *this;
0112   }
0113 public:
0114   bool is_valid() /*const*/ {
0115     if(!parent_gl_functions::initialize()) return false;
0116     if(m_kind==kind_texture) {
0117       return (parent_gl_functions::gl__IsTexture(m_gl_id)==GL_TRUE?true:false);
0118     } else if(m_kind==kind_buffer) {
0119 #ifdef TOOLS_USE_GL_VERSION_3_2
0120       return (parent_gl_functions::gl__IsBuffer(m_gl_id)==GL_TRUE?true:false); //If ok, then VAO is ok too.
0121 #endif
0122     } else if(m_kind==kind_list) {
0123 #ifndef TOOLS_USE_GL_VERSION_3_2
0124       return (parent_gl_functions::gl__IsList(m_gl_id)==GL_TRUE?true:false);
0125 #endif
0126     } else if(m_kind==kind_memory) {
0127       return true;
0128     }
0129     return false;
0130   }
0131   void bind() /*const*/ {
0132     parent_gl_functions::initialize();
0133     if(m_kind==kind_texture) {
0134       parent_gl_functions::gl__BindTexture(GL_TEXTURE_2D,m_gl_id);
0135     } else if(m_kind==kind_buffer) {
0136 #ifdef TOOLS_USE_GL_VERSION_3_2
0137       parent_gl_functions::gl__BindVertexArray(m_vao_id);
0138       parent_gl_functions::gl__BindBuffer(GL_ARRAY_BUFFER,m_gl_id);
0139 #endif
0140     }
0141   }
0142 public:
0143   unsigned int m_gl_id;
0144 #ifdef TOOLS_USE_GL_VERSION_3_2
0145   unsigned int m_vao_id;
0146 #endif
0147   kind m_kind;
0148   size_t m_size;
0149   float* m_data;
0150 };
0151 
0152 template <class GL_FUNCTIONS>
0153 class GL_manager_T : public virtual tools::sg::render_manager, protected GL_FUNCTIONS {
0154   typedef tools::sg::render_manager parent;
0155   using parent_gl_functions = GL_FUNCTIONS;
0156   typedef gsto_elem<GL_FUNCTIONS> gsto_t;
0157   typedef typename  std::map<unsigned int, gsto_t*>::const_iterator gstos_it_t;
0158 public:
0159   TOOLS_T_SCLASS(GL_FUNCTIONS,toolx::sg::GL_manager_T)
0160   virtual void* cast(const std::string& a_class) const {
0161     if(void* p = tools::cmp_cast<GL_manager_T>(this,a_class)) {return p;}
0162     else return 0;
0163   }
0164 public:
0165   virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh,
0166                             float a_r,float a_g,float a_b,float a_a,bool a_clear = true) {
0167 
0168     if (!parent_gl_functions::initialize()) {
0169       m_out << "toolx::sg::GL_manager_T::begin_render: parent_gl_functions::initialize() failed." << std::endl;
0170       return false;
0171     }
0172 
0173     if(m_gl_version.empty()) {
0174      {m_gl_version.clear();
0175       const char* _sv = (const char*)parent_gl_functions::gl__GetString(GL_VERSION);
0176       if(_sv) m_gl_version = _sv;}
0177 #ifdef TOOLS_USE_GL_VERSION_3_2
0178      {m_gl_shading_language_version.clear();
0179       const char* _sv = (const char*)parent_gl_functions::gl__GetString(GL_SHADING_LANGUAGE_VERSION);
0180       if(_sv) m_gl_shading_language_version = _sv;}
0181 #endif
0182      {m_gl_vendor.clear();
0183       const char* _sv = (const char*)parent_gl_functions::gl__GetString(GL_VENDOR);
0184       if(_sv) m_gl_vendor = _sv;}
0185      {m_gl_renderer.clear();
0186       const char* _sv = (const char*)parent_gl_functions::gl__GetString(GL_RENDERER);
0187       if(_sv) m_gl_renderer = _sv;}
0188      {m_gl_extensions.clear();
0189       const char* _sv = (const char*)parent_gl_functions::gl__GetString(GL_EXTENSIONS);
0190       if(_sv) m_gl_extensions = _sv;}
0191       m_gl_max_texture_size = 0;
0192       parent_gl_functions::gl__GetIntegerv(GL_MAX_TEXTURE_SIZE, &m_gl_max_texture_size);
0193     }
0194 
0195     clear_gl_errors();
0196 
0197 #ifdef TOOLS_USE_GL_VERSION_3_2
0198 
0199     // to avoid a 0x506 error message :
0200     if(parent_gl_functions::gl__CheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
0201       return false;
0202     }
0203 
0204     if(!create_shader_program()) {
0205       dump_if_gl_errors(m_out,"toolx::sg::GL_manager_T::create_shader_program :");
0206       m_out << "toolx::sg::GL_manager_T::begin_render : create_shader_program() failed." << std::endl;
0207       return false;
0208     }
0209     use_shader_program();
0210 
0211     // WARNING : the values set here must match the default values in sg::state.
0212 
0213     //WARNING : the below glEnable/glDisable corresponds
0214     //          to defaults in tools::sg::state.
0215     parent_gl_functions::gl__Enable(GL_DEPTH_TEST);
0216     parent_gl_functions::gl__FrontFace(GL_CCW);
0217     parent_gl_functions::gl__Enable(GL_CULL_FACE);
0218     parent_gl_functions::gl__Disable(GL_POLYGON_OFFSET_FILL);
0219 
0220     parent_gl_functions::gl__DepthFunc(GL_LESS);
0221     parent_gl_functions::gl__DepthMask(GL_TRUE);
0222 
0223     parent_gl_functions::gl__Disable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
0224     parent_gl_functions::gl__BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
0225 
0226     parent_gl_functions::gl__LineWidth(1.0f);
0227     parent_gl_functions::gl__Uniform1f(g_point_size_location(),1.0f);
0228 
0229     parent_gl_functions::gl__Viewport(a_x,a_y,a_ww,a_wh);
0230 
0231     if(a_clear) {
0232       parent_gl_functions::gl__ClearColor(a_r,a_g,a_b,a_a);
0233       parent_gl_functions::gl__Clear(GL_COLOR_BUFFER_BIT);
0234       parent_gl_functions::gl__Clear(GL_DEPTH_BUFFER_BIT);
0235     }
0236 
0237     tools::mat4f ID4;ID4.set_identity();
0238     parent_gl_functions::gl__UniformMatrix4fv(g_model_proj_matrix_location(),1,GL_FALSE,ID4.data());
0239     parent_gl_functions::gl__UniformMatrix4fv(g_normal_matrix_location(),1,GL_FALSE,ID4.data());
0240 
0241 #else //not TOOLS_USE_GL_VERSION_3_2
0242 
0243 #ifdef __APPLE__
0244 #ifdef __COREFOUNDATION__  //Cocoa.h included: we build a Cocoa application.
0245     // to avoid a 0x506 error message :
0246     if(parent_gl_functions::gl__CheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) { //It is a GL_VERSION_3_0 function.
0247       return false;
0248     }
0249 #endif
0250 #endif
0251 
0252     // WARNING : the values set here must match the default values in sg::state.
0253 
0254 
0255     parent_gl_functions::gl__Disable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
0256 
0257     parent_gl_functions::gl__Enable(GL_NORMALIZE);
0258     parent_gl_functions::gl__ShadeModel(GL_FLAT);
0259     parent_gl_functions::gl__Enable(GL_COLOR_MATERIAL);
0260 
0261 
0262     parent_gl_functions::gl__Disable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
0263     parent_gl_functions::gl__BlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
0264 
0265     //WARNING : the below glEnable/glDisable corresponds
0266     //          to defaults in tools::sg::state.
0267     parent_gl_functions::gl__Enable(GL_DEPTH_TEST);
0268     parent_gl_functions::gl__Disable(GL_LIGHTING);
0269     parent_gl_functions::gl__FrontFace(GL_CCW);
0270     parent_gl_functions::gl__Enable(GL_CULL_FACE);
0271     parent_gl_functions::gl__Disable(GL_POLYGON_OFFSET_FILL);
0272     parent_gl_functions::gl__Disable(GL_TEXTURE_2D);
0273 
0274     parent_gl_functions::gl__DepthFunc(GL_LESS);
0275     parent_gl_functions::gl__DepthMask(GL_TRUE);
0276 
0277     parent_gl_functions::gl__Disable(GL_POINT_SMOOTH);
0278     parent_gl_functions::gl__PointSize(1);
0279 
0280     parent_gl_functions::gl__Disable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms !
0281     parent_gl_functions::gl__LineWidth(1);
0282 
0283     parent_gl_functions::gl__Viewport(a_x,a_y,a_ww,a_wh);
0284 
0285     if(a_clear) {
0286       parent_gl_functions::gl__ClearColor(a_r,a_g,a_b,0);
0287       parent_gl_functions::gl__Clear(GL_COLOR_BUFFER_BIT);
0288       parent_gl_functions::gl__Clear(GL_DEPTH_BUFFER_BIT);
0289     }
0290 
0291     parent_gl_functions::gl__MatrixMode(GL_PROJECTION);
0292     parent_gl_functions::gl__LoadIdentity();
0293 
0294     parent_gl_functions::gl__MatrixMode(GL_MODELVIEW);
0295     parent_gl_functions::gl__LoadIdentity();
0296 
0297 
0298    {parent_gl_functions::gl__Color4f(a_r,a_g,a_b,::sqrt(a_a));
0299     float xyzs[12];
0300     xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0;
0301     xyzs[3] =  1;xyzs[ 4] = -1;xyzs[ 5] = 0;
0302     xyzs[6] =  1;xyzs[ 7] =  1;xyzs[ 8] = 0;
0303     xyzs[9] = -1;xyzs[10] =  1;xyzs[11] = 0;
0304     parent_gl_functions::gl__Disable(GL_DEPTH_TEST);
0305     parent_gl_functions::gl__EnableClientState(GL_VERTEX_ARRAY);
0306     parent_gl_functions::gl__VertexPointer(3,GL_FLOAT,0,xyzs);
0307     parent_gl_functions::gl__DrawArrays(GL_TRIANGLE_FAN,0,4);
0308     parent_gl_functions::gl__DisableClientState(GL_VERTEX_ARRAY);
0309     parent_gl_functions::gl__Enable(GL_DEPTH_TEST);}
0310 
0311 #endif //not TOOLS_USE_GL_VERSION_3_2
0312     return true;
0313   }
0314 
0315   virtual void end_render() {
0316 #ifdef TOOLS_USE_GL_VERSION_3_2
0317     reset_shader_locations();
0318 #endif
0319     dump_if_gl_errors(m_out,"toolx::sg::GL_manager_T::end_render :");
0320   }
0321 
0322   ////////////////////////////////////////////////
0323   /// texture : //////////////////////////////////
0324   ////////////////////////////////////////////////
0325   virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) {
0326 
0327     tools::img_byte* _img = 0;
0328     bool _img_delete = false;
0329 
0330     if(a_img.bytes_per_pixel()==1) { //exa eiffel-tower.png
0331       _img = new tools::img_byte;
0332       _img_delete = true;
0333       if(!a_img.bw2x(3,*_img)) {
0334         m_out << "toolx::sg::GL_manager_T::create_texture :"
0335               << " a_imgr.bw2x() failed."
0336               << std::endl;
0337         delete _img;
0338         return 0;
0339       }
0340     } else if(a_img.bytes_per_pixel()==3) {
0341       _img = const_cast<tools::img_byte*>(&a_img);
0342     } else if(a_img.bytes_per_pixel()==4) { //exa windusrf.png, text_freetype/font_pixmap.
0343       _img = const_cast<tools::img_byte*>(&a_img);
0344     } else {
0345       //should not happen.
0346       m_out << "toolx::sg::GL_manager_T::create_texture :"
0347             << " image with bytes_per_pixel " << a_img.bytes_per_pixel() << " not (yet) supported."
0348             << std::endl;
0349       return 0;
0350     }
0351     if(_img->is_empty()) {
0352       m_out << "toolx::sg::GL_manager_T::create_texture : img_byte is empty." << std::endl;
0353       if(_img_delete) delete _img;
0354       return 0;
0355     }
0356 
0357    {int sz;
0358     parent_gl_functions::gl__GetIntegerv(GL_MAX_TEXTURE_SIZE,&sz);
0359     if(!sz) {
0360       m_out << "toolx::sg::GL_manager_T::create_texture : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl;
0361     } else {
0362       tools::img_byte* res = new tools::img_byte;
0363       if(_img->check_gl_limit(sz,*res)) {
0364         if(res->is_empty()) { //_img does not exceed.
0365           delete res;
0366         } else {
0367           m_out << "toolx::sg::GL_manager_T::create_texture:"
0368                 << " warning : img size (" << _img->size() << ") > GL_MAX_TEXTURE_SIZE (" << sz << "), we use a reduced one." << std::endl;
0369           if(_img_delete) delete _img;
0370           _img = res;
0371           _img_delete = true;
0372         }
0373       } else {
0374         m_out << "toolx::sg::GL_manager_T::create_texture :"
0375               << " warning : img size (" << _img->size() << ") > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce it."
0376               << std::endl;
0377         delete res;
0378         if(_img_delete) delete _img;
0379         return false;
0380       }
0381     }}
0382     if(_img->is_empty()) {
0383       m_out << "toolx::sg::GL_manager_T::create_texture : img_byte is empty." << std::endl;
0384       if(_img_delete) delete _img;
0385       return 0;
0386     }
0387 
0388     unsigned int gl_id;
0389     parent_gl_functions::gl__GenTextures(1,&gl_id);
0390     if(!gl_id) {
0391       m_out << "toolx::sg::GL_manager_T::create_texture : glGenTextures failed ()." << std::endl;
0392       if(_img_delete) delete _img;
0393       return 0;
0394     }
0395 
0396     unsigned int gsto_size = _img->size();
0397     if(_img->bytes_per_pixel()==3) {
0398       parent_gl_functions::gl__BindTexture(GL_TEXTURE_2D,gl_id);
0399       parent_gl_functions::gl__TexImage2D(GL_TEXTURE_2D,0,GL_RGB,_img->width(),_img->height(),0,GL_RGB,GL_UNSIGNED_BYTE,_img->buffer());
0400       if(_img_delete) delete _img;
0401     } else if(_img->bytes_per_pixel()==4) {
0402       parent_gl_functions::gl__BindTexture(GL_TEXTURE_2D,gl_id);
0403       parent_gl_functions::gl__TexImage2D(GL_TEXTURE_2D,0,GL_RGBA,_img->width(),_img->height(),0,GL_RGBA,GL_UNSIGNED_BYTE,_img->buffer());
0404       if(_img_delete) delete _img;
0405     } else {
0406       m_out << "toolx::sg::GL_manager_T::create_texture : img.bytes_per_pixel() " << _img->bytes_per_pixel() << " not handled." << std::endl;
0407       if(_img_delete) delete _img;
0408       parent_gl_functions::gl__DeleteTextures(1,&gl_id);
0409       gl_id = 0;
0410       return false;
0411     }
0412     if(a_NEAREST) {
0413       parent_gl_functions::gl__TexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels.
0414       parent_gl_functions::gl__TexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem.
0415     } else {
0416       parent_gl_functions::gl__TexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
0417       parent_gl_functions::gl__TexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
0418     }
0419     parent_gl_functions::gl__BindTexture(GL_TEXTURE_2D,0);
0420 
0421     if(dump_if_gl_errors(m_out,"toolx::sg::GL_manager_T::create_texture :")) {
0422       parent_gl_functions::gl__DeleteTextures(1,&gl_id);
0423       gl_id = 0;
0424       clear_gl_errors();
0425       return 0;
0426     }
0427 
0428     unsigned int _id = m_gen_id;m_gen_id++;
0429     m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0);
0430     return _id;
0431   }
0432 
0433   ////////////////////////////////////////////////
0434   /// gsto ///////////////////////////////////////
0435   ////////////////////////////////////////////////
0436   virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) {
0437     if(!a_floatn) return 0;
0438     switch(m_gsto_mode) {
0439     case tools::sg::gsto_gl_vbo:{
0440 #ifdef TOOLS_USE_GL_VERSION_3_2
0441       GLuint vao_id = 0;
0442       parent_gl_functions::gl__GenVertexArrays(1,&vao_id);
0443       if(!vao_id) {
0444         m_out << "toolx::sg::GL_manager_T::create_gsto_from_data : glGenVertexArray failed ()." << std::endl;
0445         return 0;
0446       }
0447 
0448       parent_gl_functions::gl__BindVertexArray(vao_id);
0449       ////////////////////////////////////////////////////////////////////
0450       ////////////////////////////////////////////////////////////////////
0451       GLuint gl_id = 0;
0452       parent_gl_functions::gl__GenBuffers(1,&gl_id);
0453       if(!gl_id) {
0454         parent_gl_functions::gl__DeleteVertexArrays(1,&vao_id);
0455         m_out << "toolx::sg::GL_manager_T::create_gsto_from_data : glGenBuffers failed ()." << std::endl;
0456         return 0;
0457       }
0458       parent_gl_functions::gl__BindBuffer(GL_ARRAY_BUFFER,gl_id);
0459       parent_gl_functions::gl__BufferData(GL_ARRAY_BUFFER,a_floatn*sizeof(float),a_data,GL_STATIC_DRAW);
0460       parent_gl_functions::gl__BindBuffer(GL_ARRAY_BUFFER,0);
0461       ////////////////////////////////////////////////////////////////////
0462       ////////////////////////////////////////////////////////////////////
0463       parent_gl_functions::gl__BindVertexArray(0);
0464 
0465       if(dump_if_gl_errors(m_out,"toolx::sg::GL_manager_T::create_gsto_from_data :")) {
0466         m_out << "toolx::sg::GL_manager_T::create_gsto_from_data :"
0467               << " a_floatn = " << a_floatn << ", a_data = " << a_data
0468               << ", vao_id " << vao_id << ", gl_id " << gl_id
0469               << std::endl;
0470         parent_gl_functions::gl__DeleteBuffers(1,&gl_id);
0471         parent_gl_functions::gl__DeleteVertexArrays(1,&vao_id);
0472         clear_gl_errors();
0473         return 0;
0474       }
0475 
0476       unsigned int _id = m_gen_id;m_gen_id++;
0477       m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0,vao_id);
0478       return _id;
0479 
0480 #else
0481       m_out << "toolx::sg::GL_manager_T::create_gsto_from_data :"
0482             << " gsto mode is gl_vbo but class not compiled with TOOLS_USE_GL_VERSION_3_2."
0483             << std::endl;
0484       return 0;
0485 #endif
0486       }break;
0487     case tools::sg::gsto_gl_list:{
0488       unsigned int gl_id = 0;
0489       unsigned int _id = m_gen_id;m_gen_id++;
0490       m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data);
0491       return _id;
0492       }break;
0493     case tools::sg::gsto_memory:{
0494       unsigned int gl_id = 0;
0495       unsigned int _id = m_gen_id;m_gen_id++;
0496       m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data);
0497       return _id;
0498       }break;
0499     }
0500     return 0;
0501   }
0502 
0503   virtual bool is_gsto_id_valid(unsigned int a_id) const {
0504     gstos_it_t it = m_gstos.find(a_id);
0505     if(it==m_gstos.end()) return false;
0506     return (*it).second->is_valid();
0507   }
0508 
0509   virtual void delete_gsto(unsigned int a_id){
0510     tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id);
0511   }
0512 
0513   ////////////////////////////////////////////////////////
0514   ////////////////////////////////////////////////////////
0515   ////////////////////////////////////////////////////////
0516 
0517   float* gsto_data(unsigned int a_id) const {
0518     gstos_it_t it = m_gstos.find(a_id);
0519     if(it==m_gstos.end()) return 0;
0520     return (*it).second->m_data;
0521   }
0522 
0523   unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) {
0524     gstos_it_t it = m_gstos.find(a_id);
0525     if(it==m_gstos.end()) {a_created = false;return 0;}
0526     if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;}
0527     if((*it).second->m_gl_id) {
0528       a_created = false;
0529       return (*it).second->m_gl_id;
0530     } else {
0531 #ifndef TOOLS_USE_GL_VERSION_3_2
0532       unsigned int _id = parent_gl_functions::gl__GenLists(1);
0533       if(!_id) {a_created = false;return 0;}
0534       a_created = true;
0535       (*it).second->m_gl_id = _id;
0536       return _id;
0537 #else
0538       a_created = false;
0539       return 0;
0540 #endif
0541     }
0542   }
0543 
0544   ////////////////////////////////////////////////////////
0545   ////////////////////////////////////////////////////////
0546   ////////////////////////////////////////////////////////
0547   virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;}
0548 
0549   virtual void set_gsto_mode(tools::sg::gsto_mode a_v) {
0550     if(a_v==m_gsto_mode) return;
0551     tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0552     switch(a_v) {
0553     case tools::sg::gsto_gl_vbo:{
0554 #ifdef TOOLS_USE_GL_VERSION_3_2
0555       m_gsto_mode = a_v;
0556 #else
0557       m_gsto_mode = tools::sg::gsto_memory;
0558 #endif
0559       }break;
0560     case tools::sg::gsto_gl_list:{
0561 #ifndef TOOLS_USE_GL_VERSION_3_2
0562       m_gsto_mode = a_v;
0563 #else
0564       m_gsto_mode = tools::sg::gsto_memory;
0565 #endif
0566       }break;
0567     case tools::sg::gsto_memory:{
0568       m_gsto_mode = tools::sg::gsto_memory;
0569       }break;
0570     }
0571   }
0572 
0573   virtual void available_gsto_modes(std::vector<std::string>& a_vs) {
0574     a_vs.clear();
0575 #ifdef TOOLS_USE_GL_VERSION_3_2
0576     a_vs.push_back(tools::sg::s_gsto_gl_vbo());
0577 #endif
0578 #ifndef TOOLS_USE_GL_VERSION_3_2
0579     a_vs.push_back(tools::sg::s_gsto_gl_list());
0580 #endif
0581     a_vs.push_back(tools::sg::s_gsto_memory());
0582   }
0583 
0584   virtual void available_not_memory_gsto_mode(std::string& a_v) const {
0585     a_v.clear();
0586 #ifdef TOOLS_USE_GL_VERSION_3_2
0587     a_v = tools::sg::s_gsto_gl_vbo();
0588 #else
0589     a_v = tools::sg::s_gsto_gl_list();
0590 #endif
0591   }
0592 
0593   virtual size_t used_texture_memory() const {
0594     size_t sz = 0;
0595     gstos_it_t it;
0596     for(it=m_gstos.begin();it!=m_gstos.end();++it) {
0597       if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size;
0598     }
0599     return sz;
0600   }
0601 
0602   virtual size_t gstos_size() const {
0603     size_t sz = 0;
0604     gstos_it_t it;
0605     for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size;
0606     return sz;
0607   }
0608 
0609 public:
0610   GL_manager_T(std::ostream& a_out)
0611   :m_out(a_out)
0612   ,m_gen_id(1)
0613   ,m_gsto_mode(tools::sg::gsto_memory)
0614 #ifdef TOOLS_USE_GL_VERSION_3_2
0615   ,m_fragment_shader(0)
0616   ,m_vertex_shader(0)
0617   ,m_shader_program(0)
0618 #endif
0619   ,m_gl_max_texture_size(0)
0620   {}
0621   virtual ~GL_manager_T(){
0622 #ifdef TOOLS_USE_GL_VERSION_3_2
0623     delete_shader_program();
0624 #endif
0625     tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0626   }
0627 public:
0628   GL_manager_T(const GL_manager_T& a_from)
0629   :parent(a_from)
0630   ,parent_gl_functions(a_from)
0631   ,m_out(a_from.m_out)
0632   ,m_gen_id(a_from.m_gen_id)
0633   ,m_gsto_mode(a_from.m_gsto_mode)
0634   ,m_gl_max_texture_size(0)
0635   {}
0636   GL_manager_T& operator=(const GL_manager_T& a_from){
0637     if(&a_from==this) return *this;
0638     m_gen_id = a_from.m_gen_id;
0639     m_gsto_mode = a_from.m_gsto_mode;
0640     tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0641     return *this;
0642   }
0643 
0644 public:
0645   void bind_gsto(unsigned int a_id) {
0646     gstos_it_t it = m_gstos.find(a_id);
0647     if(it==m_gstos.end()) return;
0648     (*it).second->bind();
0649   }
0650   void unbind_gsto() {
0651 #ifdef TOOLS_USE_GL_VERSION_3_2
0652     parent_gl_functions::gl__BindBuffer(GL_ARRAY_BUFFER,0);
0653     parent_gl_functions::gl__BindVertexArray(0);
0654 #endif
0655   }
0656 
0657   void delete_gstos() {
0658     tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0659   }
0660 
0661 public:
0662 
0663   unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) {
0664     unsigned char* rgbas = new unsigned char[4 * a_w * a_h];
0665     if(!rgbas) return 0;
0666     parent_gl_functions::gl__PixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
0667     parent_gl_functions::gl__ReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas);
0668     return rgbas;
0669   }
0670 
0671   unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
0672     unsigned char* rgbs = new unsigned char[3 * a_w * a_h];
0673     if(!rgbs) return 0;
0674     parent_gl_functions::gl__PixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
0675     parent_gl_functions::gl__ReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs);
0676     return rgbs;
0677   }
0678 #ifdef TOOLS_USE_GL_VERSION_3_2
0679   bool create_shader_program() {
0680     if(m_shader_program) return true; //done
0681 
0682     unsigned int gl_glsl_major_version = 0;
0683     unsigned int gl_glsl_minor_version = 0;
0684     if(!get_version_numbers(m_out,m_gl_shading_language_version,gl_glsl_major_version,gl_glsl_minor_version)) {
0685       m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0686             << " can't get version numnbers for GL_SHADING_LANGUAGE_VERSION."
0687             << std::endl;
0688       return false;
0689     }
0690     unsigned int glsl_shader_processor_version = gl_glsl_major_version*100+gl_glsl_minor_version;
0691     if(glsl_shader_processor_version<150) {
0692       m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0693             << " glsl_shader_processor_version is " << glsl_shader_processor_version
0694             << ", but only the ones greater or equal to 150 are supported."
0695             << std::endl;
0696       return false;
0697     }
0698 
0699    {unsigned int gl_major_version = 0;
0700     unsigned int gl_minor_version = 0;
0701     if(!get_version_numbers(m_out,m_gl_version,gl_major_version,gl_minor_version)) {
0702       m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0703             << " can't get version numbers for GL_VERSION."
0704             << std::endl;
0705       gl_major_version = 0;
0706       gl_minor_version = 0;
0707     }
0708     m_out << "toolx::sg::GL_manager_T::create_shader_program: infos:" << std::endl
0709           << " GL_VERSION " << gl_major_version << "." << gl_minor_version << std::endl
0710           << " GL_SHADING_LANGUAGE_VERSION " << gl_glsl_major_version << "." << gl_glsl_minor_version << std::endl
0711           << " shader processor version " << glsl_shader_processor_version
0712           << std::endl;}
0713 
0714     ////////////////////////////////////////////////////
0715     ////////////////////////////////////////////////////
0716     static const GLchar* str_fs_150 = "\
0717 #version 150\n\
0718   uniform sampler2D sampler;\n\
0719   in vec4 frag_color;\n\
0720   in float frag_tex_on;\n\
0721 \n\
0722   in vec2 frag_tex_coords;\n\
0723   out vec4 _gl_FragColor;\n\
0724   void main(void) {\n\
0725     if(frag_tex_on==1.0) {\n\
0726       _gl_FragColor = frag_color*texture(sampler,vec2(frag_tex_coords.s,frag_tex_coords.t));\n\
0727     } else {\n\
0728       _gl_FragColor = frag_color;\n\
0729     }\n\
0730   }\n\
0731 ";
0732 
0733     m_fragment_shader = parent_gl_functions::gl__CreateShader(GL_FRAGMENT_SHADER);
0734     if(!m_fragment_shader) {
0735        m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0736              << " glCreateShader(GL_FRAGMENT_SHADER) failed."
0737              << std::endl;
0738        return false;
0739     }
0740     char* str_fs = (char*)str_fs_150;
0741     parent_gl_functions::gl__ShaderSource(m_fragment_shader,1,&str_fs,NULL);
0742     parent_gl_functions::gl__CompileShader(m_fragment_shader);
0743    {GLint status;
0744     parent_gl_functions::gl__GetShaderiv(m_fragment_shader,GL_COMPILE_STATUS,&status);
0745     if(status==GL_FALSE) {
0746        m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0747              << " compilation of the fragment shader failed."
0748              << std::endl;
0749 
0750       {GLsizei log_size;
0751        char shader_log[4096];
0752        parent_gl_functions::gl__GetShaderInfoLog(m_fragment_shader,1024,&log_size,shader_log);
0753        m_out << "toolx::sg::GL_manager_T::create_shader_program: fragment shader_log size " << log_size << std::endl;
0754        m_out << std::string(shader_log) << std::endl;}
0755 
0756        parent_gl_functions::gl__DeleteShader(m_fragment_shader);
0757        m_fragment_shader = 0;
0758        return false;
0759     }}
0760 
0761     ////////////////////////////////////////////////////
0762     ////////////////////////////////////////////////////
0763     static const GLchar* str_vs_150 = "\
0764 #version 150\n\
0765   in vec3 one_pos;\n\
0766   in vec3 one_normal;\n\
0767   in vec4 one_color;\n\
0768   in vec2 one_tex;\n\
0769   uniform mat4 model_proj_matrix;\n\
0770   uniform mat4 normal_matrix;\n\
0771   uniform vec4 color;\n\
0772   uniform bool pos_color;\n\
0773   uniform vec3 normal;\n\
0774   uniform bool pos_normal;\n\
0775   uniform bool tex_on;\n\
0776   uniform bool light_on;\n\
0777   uniform vec3 light_direction;\n\
0778   uniform vec4 light_color;\n\
0779   uniform vec4 light_ambient;\n\
0780   uniform float point_size;\n\
0781 \n\
0782   out float frag_tex_on;\n\
0783   out vec4 frag_color;\n\
0784   out vec2 frag_tex_coords;\n\
0785 \n\
0786   void main(void) {\n\
0787     frag_tex_on = 0.0;\n\
0788     if(tex_on) frag_tex_on = 1.0;\n\
0789     frag_tex_coords = one_tex;\n\
0790     if(tex_on) {\n\
0791       frag_color = color;\n\
0792     } else {\n\
0793       frag_color = color;\n\
0794       if(pos_color) frag_color = one_color;\n\
0795     }\n\
0796   /*frag_color = clamp(frag_color,0,1);*/\n\
0797 \n\
0798     if(light_on) {\n\
0799       vec3 _normal = normal;\n\
0800       if(pos_normal) _normal = one_normal;\n\
0801       vec3 frag_normal = vec3(normalize(normal_matrix*vec4(_normal,0)));\n\
0802       /* at this point, light_direction should be normalized.*/\n\
0803       vec4 ambient_color = light_ambient;\n\
0804     /*ambient_color = clamp(ambient_color,0,1);*/\n\
0805       float cooking = 1.4; /*to have same intensity as GL-1.1.*/\n\
0806       float _dot = dot(frag_normal,light_direction);\n\
0807       if(_dot<0.0) {\n\
0808         _dot *= -1.0;\n\
0809         vec4 diffuse_color = light_color*_dot*cooking;\n\
0810       /*diffuse_color = clamp(diffuse_color,0,1);*/\n\
0811         vec4 _color = (ambient_color+diffuse_color)*frag_color;\n\
0812         frag_color = vec4(_color.rgb,frag_color.a);\n\
0813       } else {\n\
0814         frag_color = ambient_color*frag_color*cooking;\n\
0815       }\n\
0816     }\n\
0817     gl_PointSize = point_size;\n\
0818     gl_Position = model_proj_matrix * vec4(one_pos,1);\n\
0819   }\n\
0820 ";
0821 
0822     m_vertex_shader = parent_gl_functions::gl__CreateShader(GL_VERTEX_SHADER);
0823     if(!m_vertex_shader) {
0824        m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0825              << " glCreateShader(GL_VERTEX_SHADER) failed."
0826              << std::endl;
0827        parent_gl_functions::gl__DeleteShader(m_fragment_shader);
0828        m_fragment_shader = 0;
0829        return false;
0830     }
0831     char* str_vs = (char*)str_vs_150;
0832     parent_gl_functions::gl__ShaderSource(m_vertex_shader,1,&str_vs,NULL);
0833     parent_gl_functions::gl__CompileShader(m_vertex_shader);
0834    {GLint status;
0835     parent_gl_functions::gl__GetShaderiv(m_vertex_shader,GL_COMPILE_STATUS,&status);
0836     if(status==GL_FALSE) {
0837        m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0838              << " compilation of the vertex shader failed."
0839              << std::endl;
0840 
0841       {GLsizei log_size;
0842        char shader_log[4096];
0843        parent_gl_functions::gl__GetShaderInfoLog(m_fragment_shader,1024,&log_size,shader_log);
0844        m_out << "toolx::sg::GL_manager_T::create_shader_program: vertex shader_log size " << log_size << std::endl;
0845        m_out << std::string(shader_log) << std::endl;}
0846 
0847        parent_gl_functions::gl__DeleteShader(m_vertex_shader);
0848        parent_gl_functions::gl__DeleteShader(m_fragment_shader);
0849        m_vertex_shader = 0;
0850        m_fragment_shader = 0;
0851        return false;
0852     }}
0853 
0854     m_shader_program = parent_gl_functions::gl__CreateProgram();
0855     parent_gl_functions::gl__AttachShader(m_shader_program,m_fragment_shader);
0856     parent_gl_functions::gl__AttachShader(m_shader_program,m_vertex_shader);
0857     parent_gl_functions::gl__LinkProgram(m_shader_program);
0858    {GLint status;
0859     parent_gl_functions::gl__GetProgramiv(m_shader_program,GL_LINK_STATUS,&status);
0860     if(status==GL_FALSE) {
0861        m_out << "toolx::sg::GL_manager_T::create_shader_program :"
0862              << " link program failed."
0863              << std::endl;
0864        parent_gl_functions::gl__DetachShader(m_shader_program,m_fragment_shader);
0865        parent_gl_functions::gl__DetachShader(m_shader_program,m_vertex_shader);
0866        parent_gl_functions::gl__DeleteProgram(m_shader_program);
0867        parent_gl_functions::gl__DeleteShader(m_vertex_shader);
0868        parent_gl_functions::gl__DeleteShader(m_fragment_shader);
0869        m_vertex_shader = 0;
0870        m_fragment_shader = 0;
0871        m_shader_program = 0;
0872        return false;
0873     }}
0874     return true;
0875   }
0876   void delete_shader_program() {
0877     if(!m_shader_program) return;
0878     parent_gl_functions::gl__DetachShader(m_shader_program,m_fragment_shader);
0879     parent_gl_functions::gl__DetachShader(m_shader_program,m_vertex_shader);
0880     parent_gl_functions::gl__DeleteProgram(m_shader_program);
0881     parent_gl_functions::gl__DeleteShader(m_vertex_shader);
0882     parent_gl_functions::gl__DeleteShader(m_fragment_shader);
0883      m_vertex_shader = 0;
0884      m_fragment_shader = 0;
0885      m_shader_program = 0;
0886   }
0887 
0888 #define GET_UNIFORM_LOCATION(a__var,a__name)\
0889   m_##a__var = parent_gl_functions::gl__GetUniformLocation(m_shader_program,a__name);\
0890   if(m_##a__var==(-1)) {\
0891     m_out << "toolx::sg::GL_manager_T::use_shader_program : glGetUniformLocation(" << a__name << ") failed." << std::endl;\
0892   }
0893 
0894 #define GET_ATTRIB_LOCATION(a__var,a__name)\
0895   m_##a__var = parent_gl_functions::gl__GetAttribLocation(m_shader_program,a__name);\
0896   if(m_##a__var==(-1)) {\
0897     m_out << "toolx::sg::GL_manager_T::use_shader_program : glGetAttribLocation(" << a__name << ") failed." << std::endl;\
0898   }
0899 
0900   GLint g_sampler_location() {return m_g_sampler;}
0901   GLint g_tex_on_location() {return m_g_tex_on;}
0902   GLint g_point_size_location() {return m_g_point_size;}
0903 
0904   GLint g_one_pos_location() {return m_g_one_pos;}
0905   GLint g_one_normal_location() {return m_g_one_normal;}
0906   GLint g_one_color_location() {return m_g_one_color;}
0907   GLint g_one_tex_location() {return m_g_one_tex;}
0908 
0909   GLint g_model_proj_matrix_location() {return m_g_model_proj_matrix;}
0910   GLint g_normal_matrix_location() {return m_g_normal_matrix;}
0911   GLint g_color_location() {return m_g_color;}
0912   GLint g_pos_color_location() {return m_g_pos_color;}
0913   GLint g_normal_location() {return m_g_normal;}
0914   GLint g_pos_normal_location() {return m_g_pos_normal;}
0915 
0916   GLint g_light_on_location() {return m_g_light_on;}
0917   GLint g_light_direction_location() {return m_g_light_direction;}
0918   GLint g_light_color_location() {return m_g_light_color;}
0919   GLint g_light_ambient_location() {return m_g_light_ambient;}
0920 
0921   void use_shader_program() {
0922     if(!m_shader_program) return;
0923 
0924     parent_gl_functions::gl__UseProgram(m_shader_program);
0925 
0926     // used by renderer :
0927     GET_UNIFORM_LOCATION(g_sampler,"sampler")
0928     GET_UNIFORM_LOCATION(g_tex_on,"tex_on")
0929     GET_UNIFORM_LOCATION(g_point_size,"point_size")
0930 
0931     GET_ATTRIB_LOCATION(g_one_pos,"one_pos")
0932     GET_ATTRIB_LOCATION(g_one_normal,"one_normal")
0933     GET_ATTRIB_LOCATION(g_one_color,"one_color")
0934     GET_ATTRIB_LOCATION(g_one_tex,"one_tex")
0935 
0936     GET_UNIFORM_LOCATION(g_model_proj_matrix,"model_proj_matrix")
0937     GET_UNIFORM_LOCATION(g_normal_matrix,"normal_matrix")
0938     GET_UNIFORM_LOCATION(g_color,"color")
0939     GET_UNIFORM_LOCATION(g_pos_color,"pos_color")
0940     GET_UNIFORM_LOCATION(g_normal,"normal")
0941     GET_UNIFORM_LOCATION(g_pos_normal,"pos_normal")
0942 
0943     GET_UNIFORM_LOCATION(g_light_on,"light_on")
0944     GET_UNIFORM_LOCATION(g_light_direction,"light_direction")
0945     GET_UNIFORM_LOCATION(g_light_color,"light_color")
0946     GET_UNIFORM_LOCATION(g_light_ambient,"light_ambient")
0947 
0948     parent_gl_functions::gl__Uniform1i(m_g_tex_on,0);
0949     parent_gl_functions::gl__Uniform1f(m_g_point_size,1);
0950 
0951     parent_gl_functions::gl__Uniform4f(m_g_color,1,1,1,1);
0952     parent_gl_functions::gl__Uniform1i(m_g_pos_color,false);
0953 
0954     parent_gl_functions::gl__Uniform3f(m_g_normal,0,0,1);
0955     parent_gl_functions::gl__Uniform1i(m_g_pos_normal,false);
0956 
0957     parent_gl_functions::gl__Uniform1i(m_g_light_on,0);
0958     parent_gl_functions::gl__Uniform4f(m_g_light_color,1,1,1,0);
0959     parent_gl_functions::gl__Uniform3f(m_g_light_direction,0,0,-1);
0960 
0961   }
0962   void reset_shader_locations() {
0963     m_g_sampler = -1;
0964     m_g_tex_on = -1;
0965     m_g_point_size = -1;
0966 
0967     m_g_one_pos = -1;
0968     m_g_one_normal = -1;
0969     m_g_one_color = -1;
0970     m_g_one_tex = -1;
0971 
0972     m_g_model_proj_matrix = -1;
0973     m_g_normal_matrix = -1;
0974     m_g_color = -1;
0975     m_g_pos_color = -1;
0976     m_g_normal = -1;
0977     m_g_pos_normal = -1;
0978 
0979     m_g_light_on = -1;
0980     m_g_light_direction = -1;
0981     m_g_light_color = -1;
0982     m_g_light_ambient = -1;
0983   }
0984 #undef GET_ATTRIB_LOCATION
0985 #undef GET_UNIFORM_LOCATION
0986 
0987 #endif //TOOLS_USE_GL_VERSION_3_2
0988 
0989 protected:
0990   /*static*/ void clear_gl_errors() {
0991     GLenum glerror = parent_gl_functions::gl__GetError();
0992     while(glerror!=GL_NO_ERROR) {
0993       glerror = parent_gl_functions::gl__GetError();
0994     }
0995   }
0996 
0997   /*static*/ bool dump_if_gl_errors(std::ostream& a_out,const std::string& a_head) {
0998     bool retval = false;
0999     GLenum glerror = parent_gl_functions::gl__GetError();
1000     if(glerror!=GL_NO_ERROR) {
1001       a_out << a_head
1002             << " we have gl errors :"
1003             << std::endl;
1004       retval = true;
1005     }
1006     while(glerror!=GL_NO_ERROR) {
1007       //#define GL_NO_ERROR                       0
1008       //#define GL_INVALID_ENUM                   0x0500
1009       //#define GL_INVALID_VALUE                  0x0501
1010       //#define GL_INVALID_OPERATION              0x0502
1011       //#define GL_STACK_OVERFLOW                 0x0503
1012       //#define GL_STACK_UNDERFLOW                0x0504
1013       //#define GL_OUT_OF_MEMORY                  0x0505
1014 
1015       //#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
1016 
1017       std::ostringstream oss;
1018       oss << "0x" << std::hex << glerror;
1019       a_out << oss.str() << std::endl;
1020 
1021       glerror = parent_gl_functions::gl__GetError();
1022     }
1023     return retval;
1024   }
1025 
1026   static bool s2vers(const std::string& a_string,std::vector<unsigned int>& a_versions) {
1027     // a_string is of the form "<number>[.<number>.<number>] <comment>, extract <numbers>.
1028     // Examples : "1.0.2" "2.1 ATI-4.8.101"
1029     a_versions.clear();
1030     if(a_string.empty()) return false;
1031     char* pos = (char*)a_string.c_str();
1032     while((*pos!='\0')&&(*pos!=' ')) {
1033       char* s;
1034       long v = ::strtol(pos,&s,10);
1035       if(s==pos) {
1036         a_versions.clear();
1037         return false;
1038       }
1039       if(v<0) {
1040         a_versions.clear();
1041         return false;
1042       }
1043       a_versions.push_back((unsigned int)v);
1044       pos = s; //Could be at end.
1045       if(*pos=='\0') break;
1046       if(*pos==' ') break;
1047       if(*pos!='.') {
1048         a_versions.clear();
1049         return false;
1050       }
1051       // Next char is '.', skip it:
1052       pos++;
1053     }
1054     return true;
1055   }
1056 
1057   /*static*/ bool get_version_numbers(std::ostream& a_out,const std::string& a_version,unsigned int& a_major,unsigned int& a_minor) {
1058     a_major = 0;
1059     a_minor = 0;
1060     std::vector<unsigned int> verss;
1061     if(!s2vers(a_version,verss)) {
1062       a_out << "toolx::sg::GL_manager_T::get_version_numbers :"
1063             << " toolx::sg::GL_manager_T::s2vers() failed on \"" << a_version << "\"."
1064             << std::endl;
1065       return false;
1066     }
1067     if(verss.size()==1) {
1068       a_major = verss[0];
1069       a_minor = 0;
1070     } else if(verss.size()>=2) {
1071       a_major = verss[0];
1072       a_minor = verss[1];
1073     } else {
1074       a_out << "toolx::sg::GL_manager_T::get_version_numbers :"
1075             << " can't extract major/minor version number from \"" << a_version << "\"."
1076             << std::endl;
1077       return false;
1078     }
1079     return true;
1080   }
1081 
1082 protected:
1083   std::ostream& m_out;
1084 
1085   std::map<unsigned int,gsto_t*> m_gstos;
1086 
1087   unsigned int m_gen_id;
1088   tools::sg::gsto_mode m_gsto_mode;
1089 
1090 #ifdef TOOLS_USE_GL_VERSION_3_2
1091   GLuint m_fragment_shader;
1092   GLuint m_vertex_shader;
1093   GLuint m_shader_program;
1094   //locations:
1095   GLint m_g_sampler;
1096   GLint m_g_tex_on;
1097   GLint m_g_point_size;
1098 
1099   GLint m_g_one_pos;
1100   GLint m_g_one_normal;
1101   GLint m_g_one_color;
1102   GLint m_g_one_tex;
1103 
1104   GLint m_g_model_proj_matrix;
1105   GLint m_g_normal_matrix;
1106   GLint m_g_color;
1107   GLint m_g_pos_color;
1108   GLint m_g_normal;
1109   GLint m_g_pos_normal;
1110 
1111   GLint m_g_light_on;
1112   GLint m_g_light_direction;
1113   GLint m_g_light_color;
1114   GLint m_g_light_ambient;
1115 #endif //TOOLS_USE_GL_VERSION_3_2
1116 
1117   std::string m_gl_version;
1118 #ifdef TOOLS_USE_GL_VERSION_3_2
1119   std::string m_gl_shading_language_version;
1120 #endif
1121   std::string m_gl_vendor;
1122   std::string m_gl_renderer;
1123   std::string m_gl_extensions;
1124   GLint m_gl_max_texture_size;
1125 };
1126 
1127 }}
1128 
1129 #endif