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 #include "gl"
0008 #include "../glbuf"
0009
0010 #include <tools/sg/render_manager>
0011 #include <tools/mapmanip>
0012 #include <tools/carray>
0013
0014 #include <cmath> //::sqrt
0015
0016 #ifdef TOOLS_MEM
0017 #include <tools/mem>
0018 #endif
0019
0020 namespace toolx {
0021 namespace sg {
0022
0023 class GL_manager : public virtual tools::sg::render_manager {
0024 typedef tools::sg::render_manager parent;
0025 public:
0026 TOOLS_SCLASS(toolx::sg::GL_manager)
0027 virtual void* cast(const std::string& a_class) const {
0028 if(void* p = tools::cmp_cast<GL_manager>(this,a_class)) {return p;}
0029 else return 0;
0030 }
0031 public:
0032 virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh,
0033 float a_r,float a_g,float a_b,float a_a,bool a_clear = true) {
0034 gl_clear_errors();
0035
0036 #if TARGET_OS_IPHONE
0037 #elif defined(ANDROID)
0038 #elif _WIN32
0039 #elif __APPLE__ // Cocoa
0040 // to avoid a 0x506 error message :
0041 #ifdef TOOLX_HAS_GL_VBO
0042 #if GL_ARB_framebuffer_object
0043 if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
0044 //m_out << "toolx::sg::GL_manager::begin_render :"
0045 // << " frame buffer not complete."
0046 // << std::endl;
0047 return false;
0048 }
0049 #endif //GL_ARB_framebuffer_object
0050 #endif //TOOLX_HAS_GL_VBO
0051 #else
0052 #endif
0053
0054 // WARNING : the values set here must match the default values in sg::state.
0055
0056 // Antialiasing :
0057 #if TARGET_OS_IPHONE
0058 #elif defined(ANDROID)
0059 ::glEnable(GL_MULTISAMPLE);
0060 #elif _WIN32
0061 #elif __APPLE__
0062 ::glEnable(GL_MULTISAMPLE); //Cocoa
0063 #else
0064 #endif
0065
0066 /* NOTE : not GL-ES :
0067 // ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
0068 // The upper is cruely lacking with povama solid+light.
0069 // ::glEnable(GL_LINE_STIPPLE);
0070
0071 ::glDisable(GL_POLYGON_SMOOTH);
0072 ::glAccum(GL_LOAD,1.0f);
0073 ::glAccum(GL_RETURN,1.0f);
0074 ::glReadBuffer(GL_FRONT);
0075
0076 NOTE : GL_POLYGON_SMOOTH is here on Cocoa/AGL, Windows/WGL but it
0077 does nothing.
0078 */
0079
0080 #if TARGET_OS_IPHONE
0081 // GL-ES
0082 #elif defined(ANDROID)
0083 // GL-ES
0084 #else
0085 ::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
0086 #endif
0087
0088 /*
0089 ::printf("debug : is enabled %d\n",::glIsEnabled(GL_COLOR_MATERIAL));
0090 {GLfloat v[4];
0091 ::glGetMaterialfv(GL_FRONT,GL_AMBIENT,v);
0092 ::printf("debug : ambient : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
0093 {GLfloat v[4];
0094 ::glGetMaterialfv(GL_FRONT,GL_DIFFUSE,v);
0095 ::printf("debug : diffuse : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
0096 {GLfloat v[4];
0097 ::glGetMaterialfv(GL_FRONT,GL_SPECULAR,v);
0098 ::printf("debug : specular : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
0099 {GLfloat v[4];
0100 ::glGetMaterialfv(GL_FRONT,GL_EMISSION,v);
0101 ::printf("debug : emission : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
0102 {GLfloat shine;
0103 ::glGetMaterialfv(GL_FRONT,GL_SHININESS,&shine);
0104 ::printf("debug : shine : %g\n",shine);}
0105 debug : is enabled 0
0106 debug : ambient : 0.2 0.2 0.2 1
0107 debug : diffuse : 0.8 0.8 0.8 1
0108 debug : specular : 0 0 0 1
0109 debug : emission : 0 0 0 1
0110 debug : shine : 0
0111 */
0112
0113 ::glEnable(GL_NORMALIZE);
0114 ::glShadeModel(GL_FLAT);
0115 //::glShadeModel(GL_SMOOTH);
0116 // GL-ES : ::glMaterialfv does not work. We then use :
0117 // ::glEnable(GL_COLOR_MATERIAL) and ::glColor.
0118 //::glColorMaterial(GL_FRONT, GL_DIFFUSE); //?
0119 ::glEnable(GL_COLOR_MATERIAL);
0120
0121 /*
0122 debug : is enabled 1
0123 debug : ambient : 1 1 1 1
0124 debug : diffuse : 1 1 1 1
0125 debug : specular : 0 0 0 1
0126 debug : emission : 0 0 0 1
0127 debug : shine : 0
0128 */
0129
0130 // to handle transparency (same as SoGLRenderAction::SCREEN_DOOR ?) :
0131 //::glEnable(GL_BLEND);
0132 // NOTE : with Cocoa+AppleGL on macOS-10.14 (Mojave), it appears that points are blended ! (Even if alpha color is 1).
0133 // Seen with some simulated catalog of galaxies done for LSST/DC2.
0134 // To master this, we disable GL_BLEND by default. Then people wanting some transparency have to
0135 // use the tools::sg::blend node in their scene graph.
0136 ::glDisable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
0137 ::glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
0138
0139 //WARNING : the below glEnable/glDisable corresponds
0140 // to defaults in tools::sg::state.
0141 ::glEnable(GL_DEPTH_TEST);
0142 ::glDisable(GL_LIGHTING);
0143 ::glFrontFace(GL_CCW);
0144 ::glEnable(GL_CULL_FACE);
0145 ::glDisable(GL_POLYGON_OFFSET_FILL);
0146 ::glDisable(GL_TEXTURE_2D);
0147
0148 ::glDisable(GL_POINT_SMOOTH);
0149 ::glPointSize(1);
0150 ::glDisable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms !
0151 ::glLineWidth(1);
0152
0153 ::glViewport(a_x,a_y,a_ww,a_wh);
0154
0155 // NOTE : iOS : glScissor logic does not work properly with Apple multisampling.
0156 // But it appears that it is not needed for VR split views.
0157 // Here a combination glViewport+[correct camera lrbt] does the clipping job (???).
0158 // (But the clear color should be the same for both views).
0159 //::glEnable(GL_SCISSOR_TEST);
0160 //::glScissor(a_x,a_y,a_ww,a_wh);
0161
0162 //NOTE : a=0 coworks with the below logic to handle transparent background.
0163 if(a_clear) {
0164 ::glClearColor(a_r,a_g,a_b,0);
0165 ::glClear(GL_COLOR_BUFFER_BIT);
0166 ::glClear(GL_DEPTH_BUFFER_BIT);
0167 }
0168
0169 //WARNING : Android, iPhone : only one glPushMatrix ok !
0170 ::glMatrixMode(GL_PROJECTION);
0171 ::glLoadIdentity();
0172
0173 //WARNING : we take the convention that the current mode is MODELVIEW
0174 ::glMatrixMode(GL_MODELVIEW);
0175 ::glLoadIdentity();
0176
0177 //m_clear_color.set_a(0.2);
0178
0179 // to handle a transparent background :
0180 //NOTE : not tested on Android and iOS.
0181 // dst color :
0182 // cr * alpha + cr * (1-alpha) = cr
0183 // cg * alpha + cg * (1-alpha) = cg
0184 // cb * alpha + cb * (1-alpha) = cb
0185 // alpha*alpha + 0 * (1-alpha) = ca => alpha = sqrt(ca)
0186
0187 {::glColor4f(a_r,a_g,a_b,::sqrt(a_a));
0188 float xyzs[12];
0189 xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0;
0190 xyzs[3] = 1;xyzs[ 4] = -1;xyzs[ 5] = 0;
0191 xyzs[6] = 1;xyzs[ 7] = 1;xyzs[ 8] = 0;
0192 xyzs[9] = -1;xyzs[10] = 1;xyzs[11] = 0;
0193 ::glDisable(GL_DEPTH_TEST);
0194 ::glEnableClientState(GL_VERTEX_ARRAY);
0195 ::glVertexPointer(3,GL_FLOAT,0,xyzs);
0196 ::glDrawArrays(GL_TRIANGLE_FAN,0,4);
0197 ::glDisableClientState(GL_VERTEX_ARRAY);
0198 ::glEnable(GL_DEPTH_TEST);}
0199
0200 return true;
0201 }
0202
0203 virtual void end_render() {
0204 ::glFinish();
0205 gl_dump_if_errors(m_out,"toolx::sg::GL_manager::end_render :");
0206 }
0207
0208 ////////////////////////////////////////////////
0209 /// texture : //////////////////////////////////
0210 ////////////////////////////////////////////////
0211 virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) {
0212
0213 unsigned int gl_id;
0214 ::glGenTextures(1,&gl_id);
0215 if(!gl_id) return 0;
0216
0217 #ifdef TOOLS_MEM
0218 tools::mem::increment(tools::s_tex().c_str());
0219 #endif
0220 unsigned int gsto_size = a_img.size();
0221 ::glBindTexture(GL_TEXTURE_2D,gl_id);
0222 bool status = true;
0223 {int sz;
0224 ::glGetIntegerv(GL_MAX_TEXTURE_SIZE,&sz);
0225 // MacBookPro : it returns 8192.
0226 // Android : it returns 2048.
0227 // iPad1 : it returns 2048.
0228 // iPod : it returns ?
0229 //::printf("debug : GL_MAX_TEXTURE_SIZE : %d\n",sz);
0230 tools::img_byte res;
0231 if(!sz) {
0232 m_out << "toolx::sg::gl::tex_img : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl;
0233 status = gl_tex_img(m_out,a_img);
0234 } else {
0235 if(a_img.check_gl_limit(sz,res)) {
0236 if(res.is_empty()) { //a_img does not exceed.
0237 status = gl_tex_img(m_out,a_img);
0238 } else {
0239 m_out << "toolx::sg::gl::tex_img : warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ")." << std::endl;
0240 status = gl_tex_img(m_out,res);
0241 gsto_size = res.size();
0242 }
0243 } else {
0244 m_out << "toolx::sg::gl::tex_img :"
0245 << " warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce."
0246 << std::endl;
0247 status = false;
0248 }}}
0249
0250 if(a_NEAREST) {
0251 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels.
0252 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem.
0253 } else {
0254 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
0255 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
0256 }
0257 ::glBindTexture(GL_TEXTURE_2D,0);
0258
0259 if(!status) {
0260 gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (1) :");
0261 ::glDeleteTextures(1,&gl_id);
0262 #ifdef TOOLS_MEM
0263 tools::mem::decrement(tools::s_tex().c_str());
0264 #endif
0265 gl_id = 0;
0266 gl_clear_errors();
0267 return 0;
0268 }
0269
0270 if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (2) :")) {
0271 ::glDeleteTextures(1,&gl_id);
0272 #ifdef TOOLS_MEM
0273 tools::mem::decrement(tools::s_tex().c_str());
0274 #endif
0275 gl_id = 0;
0276 gl_clear_errors();
0277 return 0;
0278 }
0279
0280 unsigned int _id = m_gen_id;m_gen_id++;
0281 m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0);
0282 return _id;
0283 }
0284
0285 ////////////////////////////////////////////////
0286 /// VBO ////////////////////////////////////////
0287 ////////////////////////////////////////////////
0288 virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) {
0289 if(!a_floatn) return 0;
0290 switch(m_gsto_mode) {
0291 case tools::sg::gsto_gl_vbo:{
0292 #ifdef TOOLX_HAS_GL_VBO
0293 unsigned int gl_id = 0;
0294 ::glGenBuffers(1,&gl_id);
0295 if(!gl_id) {
0296 if(!m_warned) {
0297 m_warned = true;
0298 m_out << "toolx::sg::GL_manager::create_gsto_from_data : glGenBuffers failed ()." << std::endl;
0299 }
0300 return 0;
0301 }
0302 #ifdef TOOLS_MEM
0303 tools::mem::increment(tools::s_gsto().c_str());
0304 #endif
0305
0306 ::glBindBuffer(GL_ARRAY_BUFFER,gl_id);
0307 ::glBufferData(GL_ARRAY_BUFFER,
0308 a_floatn*sizeof(float),a_data,
0309 GL_STATIC_DRAW);
0310 ::glBindBuffer(GL_ARRAY_BUFFER,0);
0311
0312 if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_gsto_from_data :")) {
0313 ::glDeleteBuffers(1,&gl_id);
0314 #ifdef TOOLS_MEM
0315 tools::mem::decrement(tools::s_gsto().c_str());
0316 #endif
0317 gl_id = 0;
0318 gl_clear_errors();
0319 return 0;
0320 }
0321
0322 unsigned int _id = m_gen_id;m_gen_id++;
0323 m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0);
0324 return _id;
0325 #else //!TOOLX_HAS_GL_VBO
0326 m_out << "toolx::sg::GL_manager::create_gsto_from_data :"
0327 << " gsto mode is gl_vbo but class not compiled with TOOLX_HAS_GL_VBO."
0328 << std::endl;
0329 return 0;
0330 #endif //TOOLX_HAS_GL_VBO
0331 }break;
0332 case tools::sg::gsto_gl_list:{
0333 unsigned int gl_id = 0;
0334 unsigned int _id = m_gen_id;m_gen_id++;
0335 m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data);
0336 return _id;
0337 }break;
0338 case tools::sg::gsto_memory:{
0339 unsigned int gl_id = 0;
0340 unsigned int _id = m_gen_id;m_gen_id++;
0341 m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data);
0342 return _id;
0343 }break;
0344 }
0345 return 0;
0346 }
0347
0348 virtual bool is_gsto_id_valid(unsigned int a_id) const {
0349 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
0350 if(it==m_gstos.end()) return false;
0351 return (*it).second->is_valid();
0352 }
0353
0354 virtual void delete_gsto(unsigned int a_id){
0355 tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id);
0356 }
0357
0358 ////////////////////////////////////////////////////////
0359 ////////////////////////////////////////////////////////
0360 ////////////////////////////////////////////////////////
0361
0362 float* gsto_data(unsigned int a_id) const {
0363 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
0364 if(it==m_gstos.end()) return 0;
0365 return (*it).second->m_data;
0366 }
0367
0368 unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) const {
0369 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
0370 if(it==m_gstos.end()) {a_created = false;return 0;}
0371 if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;}
0372 if((*it).second->m_gl_id) {
0373 a_created = false;
0374 return (*it).second->m_gl_id;
0375 } else {
0376 #ifdef TOOLX_HAS_GL_LIST
0377 unsigned int _id = ::glGenLists(1);
0378 if(!_id) {a_created = false;return 0;}
0379 #ifdef TOOLS_MEM
0380 tools::mem::increment(tools::s_gsto().c_str());
0381 #endif
0382 a_created = true;
0383 (*it).second->m_gl_id = _id;
0384 return _id;
0385 #else
0386 a_created = false;
0387 return 0;
0388 #endif
0389 }
0390 }
0391
0392 ////////////////////////////////////////////////////////
0393 ////////////////////////////////////////////////////////
0394 ////////////////////////////////////////////////////////
0395 virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;}
0396
0397 virtual void set_gsto_mode(tools::sg::gsto_mode a_v) {
0398 if(a_v==m_gsto_mode) return;
0399 tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0400 switch(a_v) {
0401 case tools::sg::gsto_gl_vbo:{
0402 #ifdef TOOLX_HAS_GL_VBO
0403 m_gsto_mode = a_v;
0404 #else
0405 m_gsto_mode = tools::sg::gsto_memory;
0406 #endif
0407 }break;
0408 case tools::sg::gsto_gl_list:{
0409 #ifdef TOOLX_HAS_GL_LIST
0410 m_gsto_mode = a_v;
0411 #else
0412 m_gsto_mode = tools::sg::gsto_memory;
0413 #endif
0414 }break;
0415 case tools::sg::gsto_memory:{
0416 m_gsto_mode = tools::sg::gsto_memory;
0417 }break;
0418 }
0419 }
0420
0421 virtual void available_gsto_modes(std::vector<std::string>& a_vs) {
0422 a_vs.clear();
0423 #ifdef TOOLX_HAS_GL_VBO
0424 a_vs.push_back(tools::sg::s_gsto_gl_vbo());
0425 #endif
0426 #ifdef TOOLX_HAS_GL_LIST
0427 a_vs.push_back(tools::sg::s_gsto_gl_list());
0428 #endif
0429 a_vs.push_back(tools::sg::s_gsto_memory());
0430 }
0431
0432 virtual void available_not_memory_gsto_mode(std::string& a_v) const {
0433 a_v.clear();
0434 #ifdef TOOLX_HAS_GL_VBO
0435 a_v = tools::sg::s_gsto_gl_vbo();
0436 #endif
0437 #ifdef TOOLX_HAS_GL_LIST
0438 if(a_v.empty()) a_v = tools::sg::s_gsto_gl_list();
0439 #endif
0440 }
0441
0442 virtual size_t used_texture_memory() const {
0443 size_t sz = 0;
0444 std::map<unsigned int,gsto_t*>::const_iterator it;
0445 for(it=m_gstos.begin();it!=m_gstos.end();++it) {
0446 if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size;
0447 }
0448 return sz;
0449 }
0450
0451 virtual size_t gstos_size() const {
0452 size_t sz = 0;
0453 std::map<unsigned int,gsto_t*>::const_iterator it;
0454 for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size;
0455 return sz;
0456 }
0457
0458 public:
0459 GL_manager(std::ostream& a_out)
0460 :m_out(a_out)
0461 ,m_gen_id(1)
0462 #ifdef TOOLX_HAS_GL_VBO
0463 ,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs.
0464 #elif TOOLX_HAS_GL_LIST
0465 ,m_gsto_mode(tools::sg::gsto_gl_list)
0466 #else
0467 ,m_gsto_mode(tools::sg::gsto_memory)
0468 #endif
0469 ,m_warned(false)
0470 {}
0471 virtual ~GL_manager(){
0472 tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0473 }
0474 public:
0475 GL_manager(const GL_manager& a_from)
0476 :parent(a_from)
0477 ,m_out(a_from.m_out)
0478 ,m_gen_id(a_from.m_gen_id)
0479 ,m_gsto_mode(a_from.m_gsto_mode)
0480 ,m_warned(false)
0481 {}
0482 GL_manager& operator=(const GL_manager& a_from){
0483 if(&a_from==this) return *this;
0484 m_gen_id = a_from.m_gen_id;
0485 m_gsto_mode = a_from.m_gsto_mode;
0486 tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0487 m_warned = false;
0488 return *this;
0489 }
0490
0491 public:
0492 void bind_gsto(unsigned int a_id) {
0493 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
0494 if(it==m_gstos.end()) return;
0495 (*it).second->bind();
0496 }
0497
0498 void delete_gstos() {
0499 tools::safe_clear<unsigned int,gsto_t>(m_gstos);
0500 }
0501
0502 public:
0503
0504 static unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) {
0505 //WARNING : it does OpenGL. Under Android it should be executed
0506 // in the OpenGL thread.
0507 //NOTE : Android, iOS : RGB produces a black image.
0508 unsigned char* rgbas = new unsigned char[4 * a_w * a_h];
0509 if(!rgbas) return 0;
0510 ::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
0511 ::glReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas);
0512 /*{size_t number = 4 * a_w * a_h;
0513 size_t count_not_255 = 0;
0514 for(size_t item=3;item<number;item+=4) {
0515 unsigned char a = rgbas[item];
0516 if(a!=255) {
0517 ::printf("%lu : %d\n",item,a);
0518 count_not_255++;
0519 rgbas[item] = 255;
0520 }
0521 }
0522 ::printf("not_255 : %lu\n",count_not_255);}*/
0523 return rgbas;
0524 }
0525
0526 #if defined(TARGET_OS_IPHONE) || defined(ANDROID)
0527 static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
0528 unsigned char* rgbas = get_rgbas(a_w,a_h);
0529 if(!rgbas) return 0;
0530 unsigned char* rgbs = tools::_4s_to_3s<unsigned char,unsigned int>(rgbas,a_w,a_h);
0531 delete [] rgbas;
0532 return rgbs;
0533 }
0534 #else
0535 static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
0536 //WARNING : it does OpenGL. Under Android it should be executed
0537 // in the OpenGL thread.
0538 //NOTE : Android, iOS : RGB produces a black image.
0539 unsigned char* rgbs = new unsigned char[3 * a_w * a_h];
0540 if(!rgbs) return 0;
0541 ::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
0542 ::glReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs);
0543 return rgbs;
0544 }
0545 #endif
0546
0547 protected:
0548 std::ostream& m_out;
0549
0550 class gsto_t {
0551 TOOLS_SCLASS(GL_manager::gsto_t)
0552 public:
0553 enum kind {
0554 kind_texture,
0555 kind_buffer,
0556 kind_list,
0557 kind_memory
0558 };
0559 public:
0560 gsto_t(kind a_kind,int a_gl_id,size_t a_size,const float* a_data)
0561 :m_gl_id(a_gl_id)
0562 ,m_kind(a_kind)
0563 ,m_size(a_size)
0564 ,m_data(0)
0565 {
0566 #ifdef TOOLS_MEM
0567 tools::mem::increment(s_class().c_str());
0568 #endif
0569 if(a_data) {
0570 size_t num = m_size/sizeof(float);
0571 m_data = new float[num];
0572 #ifdef TOOLS_MEM
0573 tools::mem::increment(tools::s_new().c_str());
0574 #endif
0575 ::memcpy(m_data,a_data,m_size);
0576 }
0577 }
0578 virtual ~gsto_t() {
0579 if(m_kind==kind_texture) {
0580 ::glDeleteTextures(1,&m_gl_id);
0581 #ifdef TOOLS_MEM
0582 tools::mem::decrement(tools::s_tex().c_str());
0583 #endif
0584 } else if(m_kind==kind_buffer) {
0585 #ifdef TOOLX_HAS_GL_VBO
0586 ::glDeleteBuffers(1,&m_gl_id);
0587 #ifdef TOOLS_MEM
0588 tools::mem::decrement(tools::s_gsto().c_str());
0589 #endif
0590 #endif
0591 } else if(m_kind==kind_list) {
0592 if(m_gl_id) {
0593 #ifdef TOOLX_HAS_GL_LIST
0594 ::glDeleteLists(m_gl_id,1);
0595 #ifdef TOOLS_MEM
0596 tools::mem::decrement(tools::s_gsto().c_str());
0597 #endif
0598 #endif
0599 }
0600 }
0601
0602 if(m_data) {
0603 delete [] m_data;
0604 #ifdef TOOLS_MEM
0605 tools::mem::decrement(tools::s_new().c_str());
0606 #endif
0607 }
0608 #ifdef TOOLS_MEM
0609 tools::mem::decrement(s_class().c_str());
0610 #endif
0611 }
0612 private:
0613 gsto_t(const gsto_t& a_from)
0614 :m_gl_id(a_from.m_gl_id)
0615 ,m_kind(a_from.m_kind)
0616 ,m_size(a_from.m_size)
0617 ,m_data(0)
0618 {
0619 #ifdef TOOLS_MEM
0620 tools::mem::increment(s_class().c_str());
0621 #endif
0622 if(a_from.m_data) {
0623 size_t num = m_size/sizeof(float);
0624 m_data = new float[num];
0625 #ifdef TOOLS_MEM
0626 tools::mem::increment(tools::s_new().c_str());
0627 #endif
0628 ::memcpy(m_data,a_from.m_data,m_size);
0629 }
0630 }
0631 gsto_t& operator=(const gsto_t& a_from){
0632 if(&a_from==this) return *this;
0633 m_gl_id = a_from.m_gl_id;
0634 m_kind = a_from.m_kind;
0635 m_size = a_from.m_size;
0636 if(m_data) {
0637 delete [] m_data;
0638 #ifdef TOOLS_MEM
0639 tools::mem::decrement(tools::s_new().c_str());
0640 #endif
0641 m_data = 0;
0642 }
0643 if(a_from.m_data) {
0644 size_t num = m_size/sizeof(float);
0645 m_data = new float[num];
0646 #ifdef TOOLS_MEM
0647 tools::mem::increment(tools::s_new().c_str());
0648 #endif
0649 ::memcpy(m_data,a_from.m_data,m_size);
0650 }
0651 return *this;
0652 }
0653 public:
0654 bool is_valid() const {
0655 if(m_kind==kind_texture) {
0656 return (::glIsTexture(m_gl_id)==GL_TRUE?true:false);
0657 } else if(m_kind==kind_buffer) {
0658 #ifdef TOOLX_HAS_GL_VBO
0659 return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false);
0660 #endif
0661 } else if(m_kind==kind_list) {
0662 #ifdef TOOLX_HAS_GL_LIST
0663 return (::glIsList(m_gl_id)==GL_TRUE?true:false);
0664 #endif
0665 } else if(m_kind==kind_memory) {
0666 return true;
0667 }
0668 return false;
0669 }
0670 void bind() const {
0671 if(m_kind==kind_texture) {
0672 ::glBindTexture(GL_TEXTURE_2D,m_gl_id);
0673 } else if(m_kind==kind_buffer) {
0674 #ifdef TOOLX_HAS_GL_VBO
0675 ::glBindBuffer(GL_ARRAY_BUFFER,m_gl_id);
0676 #endif
0677 }
0678 }
0679 public:
0680 unsigned int m_gl_id;
0681 kind m_kind;
0682 size_t m_size;
0683 float* m_data;
0684 };
0685
0686 std::map<unsigned int,gsto_t*> m_gstos;
0687
0688 unsigned int m_gen_id;
0689 tools::sg::gsto_mode m_gsto_mode;
0690 bool m_warned;
0691 };
0692
0693 }}
0694
0695 #endif