Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef toolx_sg_GL_manager 5 #define toolx_sg_GL_manager 6 7 #include "gl" 8 #include "../glbuf" 9 10 #include <tools/sg/render_manager> 11 #include <tools/mapmanip> 12 #include <tools/carray> 13 14 #include <cmath> //::sqrt 15 16 #ifdef TOOLS_MEM 17 #include <tools/mem> 18 #endif 19 20 namespace toolx { 21 namespace sg { 22 23 class GL_manager : public virtual tools::sg::render_manager { 24 typedef tools::sg::render_manager parent; 25 public: 26 TOOLS_SCLASS(toolx::sg::GL_manager) 27 virtual void* cast(const std::string& a_class) const { 28 if(void* p = tools::cmp_cast<GL_manager>(this,a_class)) {return p;} 29 else return 0; 30 } 31 public: 32 virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh, 33 float a_r,float a_g,float a_b,float a_a,bool a_clear = true) { 34 gl_clear_errors(); 35 36 #if TARGET_OS_IPHONE 37 #elif defined(ANDROID) 38 #elif _WIN32 39 #elif __APPLE__ // Cocoa 40 // to avoid a 0x506 error message : 41 #ifdef TOOLX_HAS_GL_VBO 42 #if GL_ARB_framebuffer_object 43 if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) { 44 //m_out << "toolx::sg::GL_manager::begin_render :" 45 // << " frame buffer not complete." 46 // << std::endl; 47 return false; 48 } 49 #endif //GL_ARB_framebuffer_object 50 #endif //TOOLX_HAS_GL_VBO 51 #else 52 #endif 53 54 // WARNING : the values set here must match the default values in sg::state. 55 56 // Antialiasing : 57 #if TARGET_OS_IPHONE 58 #elif defined(ANDROID) 59 ::glEnable(GL_MULTISAMPLE); 60 #elif _WIN32 61 #elif __APPLE__ 62 ::glEnable(GL_MULTISAMPLE); //Cocoa 63 #else 64 #endif 65 66 /* NOTE : not GL-ES : 67 // ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 68 // The upper is cruely lacking with povama solid+light. 69 // ::glEnable(GL_LINE_STIPPLE); 70 71 ::glDisable(GL_POLYGON_SMOOTH); 72 ::glAccum(GL_LOAD,1.0f); 73 ::glAccum(GL_RETURN,1.0f); 74 ::glReadBuffer(GL_FRONT); 75 76 NOTE : GL_POLYGON_SMOOTH is here on Cocoa/AGL, Windows/WGL but it 77 does nothing. 78 */ 79 80 #if TARGET_OS_IPHONE 81 // GL-ES 82 #elif defined(ANDROID) 83 // GL-ES 84 #else 85 ::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE. 86 #endif 87 88 /* 89 ::printf("debug : is enabled %d\n",::glIsEnabled(GL_COLOR_MATERIAL)); 90 {GLfloat v[4]; 91 ::glGetMaterialfv(GL_FRONT,GL_AMBIENT,v); 92 ::printf("debug : ambient : %g %g %g %g\n",v[0],v[1],v[2],v[3]);} 93 {GLfloat v[4]; 94 ::glGetMaterialfv(GL_FRONT,GL_DIFFUSE,v); 95 ::printf("debug : diffuse : %g %g %g %g\n",v[0],v[1],v[2],v[3]);} 96 {GLfloat v[4]; 97 ::glGetMaterialfv(GL_FRONT,GL_SPECULAR,v); 98 ::printf("debug : specular : %g %g %g %g\n",v[0],v[1],v[2],v[3]);} 99 {GLfloat v[4]; 100 ::glGetMaterialfv(GL_FRONT,GL_EMISSION,v); 101 ::printf("debug : emission : %g %g %g %g\n",v[0],v[1],v[2],v[3]);} 102 {GLfloat shine; 103 ::glGetMaterialfv(GL_FRONT,GL_SHININESS,&shine); 104 ::printf("debug : shine : %g\n",shine);} 105 debug : is enabled 0 106 debug : ambient : 0.2 0.2 0.2 1 107 debug : diffuse : 0.8 0.8 0.8 1 108 debug : specular : 0 0 0 1 109 debug : emission : 0 0 0 1 110 debug : shine : 0 111 */ 112 113 ::glEnable(GL_NORMALIZE); 114 ::glShadeModel(GL_FLAT); 115 //::glShadeModel(GL_SMOOTH); 116 // GL-ES : ::glMaterialfv does not work. We then use : 117 // ::glEnable(GL_COLOR_MATERIAL) and ::glColor. 118 //::glColorMaterial(GL_FRONT, GL_DIFFUSE); //? 119 ::glEnable(GL_COLOR_MATERIAL); 120 121 /* 122 debug : is enabled 1 123 debug : ambient : 1 1 1 1 124 debug : diffuse : 1 1 1 1 125 debug : specular : 0 0 0 1 126 debug : emission : 0 0 0 1 127 debug : shine : 0 128 */ 129 130 // to handle transparency (same as SoGLRenderAction::SCREEN_DOOR ?) : 131 //::glEnable(GL_BLEND); 132 // NOTE : with Cocoa+AppleGL on macOS-10.14 (Mojave), it appears that points are blended ! (Even if alpha color is 1). 133 // Seen with some simulated catalog of galaxies done for LSST/DC2. 134 // To master this, we disable GL_BLEND by default. Then people wanting some transparency have to 135 // use the tools::sg::blend node in their scene graph. 136 ::glDisable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default. 137 ::glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 138 139 //WARNING : the below glEnable/glDisable corresponds 140 // to defaults in tools::sg::state. 141 ::glEnable(GL_DEPTH_TEST); 142 ::glDisable(GL_LIGHTING); 143 ::glFrontFace(GL_CCW); 144 ::glEnable(GL_CULL_FACE); 145 ::glDisable(GL_POLYGON_OFFSET_FILL); 146 ::glDisable(GL_TEXTURE_2D); 147 148 ::glDisable(GL_POINT_SMOOTH); 149 ::glPointSize(1); 150 ::glDisable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms ! 151 ::glLineWidth(1); 152 153 ::glViewport(a_x,a_y,a_ww,a_wh); 154 155 // NOTE : iOS : glScissor logic does not work properly with Apple multisampling. 156 // But it appears that it is not needed for VR split views. 157 // Here a combination glViewport+[correct camera lrbt] does the clipping job (???). 158 // (But the clear color should be the same for both views). 159 //::glEnable(GL_SCISSOR_TEST); 160 //::glScissor(a_x,a_y,a_ww,a_wh); 161 162 //NOTE : a=0 coworks with the below logic to handle transparent background. 163 if(a_clear) { 164 ::glClearColor(a_r,a_g,a_b,0); 165 ::glClear(GL_COLOR_BUFFER_BIT); 166 ::glClear(GL_DEPTH_BUFFER_BIT); 167 } 168 169 //WARNING : Android, iPhone : only one glPushMatrix ok ! 170 ::glMatrixMode(GL_PROJECTION); 171 ::glLoadIdentity(); 172 173 //WARNING : we take the convention that the current mode is MODELVIEW 174 ::glMatrixMode(GL_MODELVIEW); 175 ::glLoadIdentity(); 176 177 //m_clear_color.set_a(0.2); 178 179 // to handle a transparent background : 180 //NOTE : not tested on Android and iOS. 181 // dst color : 182 // cr * alpha + cr * (1-alpha) = cr 183 // cg * alpha + cg * (1-alpha) = cg 184 // cb * alpha + cb * (1-alpha) = cb 185 // alpha*alpha + 0 * (1-alpha) = ca => alpha = sqrt(ca) 186 187 {::glColor4f(a_r,a_g,a_b,::sqrt(a_a)); 188 float xyzs[12]; 189 xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0; 190 xyzs[3] = 1;xyzs[ 4] = -1;xyzs[ 5] = 0; 191 xyzs[6] = 1;xyzs[ 7] = 1;xyzs[ 8] = 0; 192 xyzs[9] = -1;xyzs[10] = 1;xyzs[11] = 0; 193 ::glDisable(GL_DEPTH_TEST); 194 ::glEnableClientState(GL_VERTEX_ARRAY); 195 ::glVertexPointer(3,GL_FLOAT,0,xyzs); 196 ::glDrawArrays(GL_TRIANGLE_FAN,0,4); 197 ::glDisableClientState(GL_VERTEX_ARRAY); 198 ::glEnable(GL_DEPTH_TEST);} 199 200 return true; 201 } 202 203 virtual void end_render() { 204 ::glFinish(); 205 gl_dump_if_errors(m_out,"toolx::sg::GL_manager::end_render :"); 206 } 207 208 //////////////////////////////////////////////// 209 /// texture : ////////////////////////////////// 210 //////////////////////////////////////////////// 211 virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) { 212 213 unsigned int gl_id; 214 ::glGenTextures(1,&gl_id); 215 if(!gl_id) return 0; 216 217 #ifdef TOOLS_MEM 218 tools::mem::increment(tools::s_tex().c_str()); 219 #endif 220 unsigned int gsto_size = a_img.size(); 221 ::glBindTexture(GL_TEXTURE_2D,gl_id); 222 bool status = true; 223 {int sz; 224 ::glGetIntegerv(GL_MAX_TEXTURE_SIZE,&sz); 225 // MacBookPro : it returns 8192. 226 // Android : it returns 2048. 227 // iPad1 : it returns 2048. 228 // iPod : it returns ? 229 //::printf("debug : GL_MAX_TEXTURE_SIZE : %d\n",sz); 230 tools::img_byte res; 231 if(!sz) { 232 m_out << "toolx::sg::gl::tex_img : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl; 233 status = gl_tex_img(m_out,a_img); 234 } else { 235 if(a_img.check_gl_limit(sz,res)) { 236 if(res.is_empty()) { //a_img does not exceed. 237 status = gl_tex_img(m_out,a_img); 238 } else { 239 m_out << "toolx::sg::gl::tex_img : warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ")." << std::endl; 240 status = gl_tex_img(m_out,res); 241 gsto_size = res.size(); 242 } 243 } else { 244 m_out << "toolx::sg::gl::tex_img :" 245 << " warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce." 246 << std::endl; 247 status = false; 248 }}} 249 250 if(a_NEAREST) { 251 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels. 252 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem. 253 } else { 254 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 255 ::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 256 } 257 ::glBindTexture(GL_TEXTURE_2D,0); 258 259 if(!status) { 260 gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (1) :"); 261 ::glDeleteTextures(1,&gl_id); 262 #ifdef TOOLS_MEM 263 tools::mem::decrement(tools::s_tex().c_str()); 264 #endif 265 gl_id = 0; 266 gl_clear_errors(); 267 return 0; 268 } 269 270 if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_texture (2) :")) { 271 ::glDeleteTextures(1,&gl_id); 272 #ifdef TOOLS_MEM 273 tools::mem::decrement(tools::s_tex().c_str()); 274 #endif 275 gl_id = 0; 276 gl_clear_errors(); 277 return 0; 278 } 279 280 unsigned int _id = m_gen_id;m_gen_id++; 281 m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0); 282 return _id; 283 } 284 285 //////////////////////////////////////////////// 286 /// VBO //////////////////////////////////////// 287 //////////////////////////////////////////////// 288 virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) { 289 if(!a_floatn) return 0; 290 switch(m_gsto_mode) { 291 case tools::sg::gsto_gl_vbo:{ 292 #ifdef TOOLX_HAS_GL_VBO 293 unsigned int gl_id = 0; 294 ::glGenBuffers(1,&gl_id); 295 if(!gl_id) { 296 if(!m_warned) { 297 m_warned = true; 298 m_out << "toolx::sg::GL_manager::create_gsto_from_data : glGenBuffers failed ()." << std::endl; 299 } 300 return 0; 301 } 302 #ifdef TOOLS_MEM 303 tools::mem::increment(tools::s_gsto().c_str()); 304 #endif 305 306 ::glBindBuffer(GL_ARRAY_BUFFER,gl_id); 307 ::glBufferData(GL_ARRAY_BUFFER, 308 a_floatn*sizeof(float),a_data, 309 GL_STATIC_DRAW); 310 ::glBindBuffer(GL_ARRAY_BUFFER,0); 311 312 if(gl_dump_if_errors(m_out,"toolx::sg::GL_manager::create_gsto_from_data :")) { 313 ::glDeleteBuffers(1,&gl_id); 314 #ifdef TOOLS_MEM 315 tools::mem::decrement(tools::s_gsto().c_str()); 316 #endif 317 gl_id = 0; 318 gl_clear_errors(); 319 return 0; 320 } 321 322 unsigned int _id = m_gen_id;m_gen_id++; 323 m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0); 324 return _id; 325 #else //!TOOLX_HAS_GL_VBO 326 m_out << "toolx::sg::GL_manager::create_gsto_from_data :" 327 << " gsto mode is gl_vbo but class not compiled with TOOLX_HAS_GL_VBO." 328 << std::endl; 329 return 0; 330 #endif //TOOLX_HAS_GL_VBO 331 }break; 332 case tools::sg::gsto_gl_list:{ 333 unsigned int gl_id = 0; 334 unsigned int _id = m_gen_id;m_gen_id++; 335 m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data); 336 return _id; 337 }break; 338 case tools::sg::gsto_memory:{ 339 unsigned int gl_id = 0; 340 unsigned int _id = m_gen_id;m_gen_id++; 341 m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data); 342 return _id; 343 }break; 344 } 345 return 0; 346 } 347 348 virtual bool is_gsto_id_valid(unsigned int a_id) const { 349 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id); 350 if(it==m_gstos.end()) return false; 351 return (*it).second->is_valid(); 352 } 353 354 virtual void delete_gsto(unsigned int a_id){ 355 tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id); 356 } 357 358 //////////////////////////////////////////////////////// 359 //////////////////////////////////////////////////////// 360 //////////////////////////////////////////////////////// 361 362 float* gsto_data(unsigned int a_id) const { 363 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id); 364 if(it==m_gstos.end()) return 0; 365 return (*it).second->m_data; 366 } 367 368 unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) const { 369 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id); 370 if(it==m_gstos.end()) {a_created = false;return 0;} 371 if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;} 372 if((*it).second->m_gl_id) { 373 a_created = false; 374 return (*it).second->m_gl_id; 375 } else { 376 #ifdef TOOLX_HAS_GL_LIST 377 unsigned int _id = ::glGenLists(1); 378 if(!_id) {a_created = false;return 0;} 379 #ifdef TOOLS_MEM 380 tools::mem::increment(tools::s_gsto().c_str()); 381 #endif 382 a_created = true; 383 (*it).second->m_gl_id = _id; 384 return _id; 385 #else 386 a_created = false; 387 return 0; 388 #endif 389 } 390 } 391 392 //////////////////////////////////////////////////////// 393 //////////////////////////////////////////////////////// 394 //////////////////////////////////////////////////////// 395 virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;} 396 397 virtual void set_gsto_mode(tools::sg::gsto_mode a_v) { 398 if(a_v==m_gsto_mode) return; 399 tools::safe_clear<unsigned int,gsto_t>(m_gstos); 400 switch(a_v) { 401 case tools::sg::gsto_gl_vbo:{ 402 #ifdef TOOLX_HAS_GL_VBO 403 m_gsto_mode = a_v; 404 #else 405 m_gsto_mode = tools::sg::gsto_memory; 406 #endif 407 }break; 408 case tools::sg::gsto_gl_list:{ 409 #ifdef TOOLX_HAS_GL_LIST 410 m_gsto_mode = a_v; 411 #else 412 m_gsto_mode = tools::sg::gsto_memory; 413 #endif 414 }break; 415 case tools::sg::gsto_memory:{ 416 m_gsto_mode = tools::sg::gsto_memory; 417 }break; 418 } 419 } 420 421 virtual void available_gsto_modes(std::vector<std::string>& a_vs) { 422 a_vs.clear(); 423 #ifdef TOOLX_HAS_GL_VBO 424 a_vs.push_back(tools::sg::s_gsto_gl_vbo()); 425 #endif 426 #ifdef TOOLX_HAS_GL_LIST 427 a_vs.push_back(tools::sg::s_gsto_gl_list()); 428 #endif 429 a_vs.push_back(tools::sg::s_gsto_memory()); 430 } 431 432 virtual void available_not_memory_gsto_mode(std::string& a_v) const { 433 a_v.clear(); 434 #ifdef TOOLX_HAS_GL_VBO 435 a_v = tools::sg::s_gsto_gl_vbo(); 436 #endif 437 #ifdef TOOLX_HAS_GL_LIST 438 if(a_v.empty()) a_v = tools::sg::s_gsto_gl_list(); 439 #endif 440 } 441 442 virtual size_t used_texture_memory() const { 443 size_t sz = 0; 444 std::map<unsigned int,gsto_t*>::const_iterator it; 445 for(it=m_gstos.begin();it!=m_gstos.end();++it) { 446 if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size; 447 } 448 return sz; 449 } 450 451 virtual size_t gstos_size() const { 452 size_t sz = 0; 453 std::map<unsigned int,gsto_t*>::const_iterator it; 454 for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size; 455 return sz; 456 } 457 458 public: 459 GL_manager(std::ostream& a_out) 460 :m_out(a_out) 461 ,m_gen_id(1) 462 #ifdef TOOLX_HAS_GL_VBO 463 ,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs. 464 #elif TOOLX_HAS_GL_LIST 465 ,m_gsto_mode(tools::sg::gsto_gl_list) 466 #else 467 ,m_gsto_mode(tools::sg::gsto_memory) 468 #endif 469 ,m_warned(false) 470 {} 471 virtual ~GL_manager(){ 472 tools::safe_clear<unsigned int,gsto_t>(m_gstos); 473 } 474 public: 475 GL_manager(const GL_manager& a_from) 476 :parent(a_from) 477 ,m_out(a_from.m_out) 478 ,m_gen_id(a_from.m_gen_id) 479 ,m_gsto_mode(a_from.m_gsto_mode) 480 ,m_warned(false) 481 {} 482 GL_manager& operator=(const GL_manager& a_from){ 483 if(&a_from==this) return *this; 484 m_gen_id = a_from.m_gen_id; 485 m_gsto_mode = a_from.m_gsto_mode; 486 tools::safe_clear<unsigned int,gsto_t>(m_gstos); 487 m_warned = false; 488 return *this; 489 } 490 491 public: 492 void bind_gsto(unsigned int a_id) { 493 std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id); 494 if(it==m_gstos.end()) return; 495 (*it).second->bind(); 496 } 497 498 void delete_gstos() { 499 tools::safe_clear<unsigned int,gsto_t>(m_gstos); 500 } 501 502 public: 503 504 static unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) { 505 //WARNING : it does OpenGL. Under Android it should be executed 506 // in the OpenGL thread. 507 //NOTE : Android, iOS : RGB produces a black image. 508 unsigned char* rgbas = new unsigned char[4 * a_w * a_h]; 509 if(!rgbas) return 0; 510 ::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa. 511 ::glReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas); 512 /*{size_t number = 4 * a_w * a_h; 513 size_t count_not_255 = 0; 514 for(size_t item=3;item<number;item+=4) { 515 unsigned char a = rgbas[item]; 516 if(a!=255) { 517 ::printf("%lu : %d\n",item,a); 518 count_not_255++; 519 rgbas[item] = 255; 520 } 521 } 522 ::printf("not_255 : %lu\n",count_not_255);}*/ 523 return rgbas; 524 } 525 526 #if defined(TARGET_OS_IPHONE) || defined(ANDROID) 527 static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) { 528 unsigned char* rgbas = get_rgbas(a_w,a_h); 529 if(!rgbas) return 0; 530 unsigned char* rgbs = tools::_4s_to_3s<unsigned char,unsigned int>(rgbas,a_w,a_h); 531 delete [] rgbas; 532 return rgbs; 533 } 534 #else 535 static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) { 536 //WARNING : it does OpenGL. Under Android it should be executed 537 // in the OpenGL thread. 538 //NOTE : Android, iOS : RGB produces a black image. 539 unsigned char* rgbs = new unsigned char[3 * a_w * a_h]; 540 if(!rgbs) return 0; 541 ::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa. 542 ::glReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs); 543 return rgbs; 544 } 545 #endif 546 547 protected: 548 std::ostream& m_out; 549 550 class gsto_t { 551 TOOLS_SCLASS(GL_manager::gsto_t) 552 public: 553 enum kind { 554 kind_texture, 555 kind_buffer, 556 kind_list, 557 kind_memory 558 }; 559 public: 560 gsto_t(kind a_kind,int a_gl_id,size_t a_size,const float* a_data) 561 :m_gl_id(a_gl_id) 562 ,m_kind(a_kind) 563 ,m_size(a_size) 564 ,m_data(0) 565 { 566 #ifdef TOOLS_MEM 567 tools::mem::increment(s_class().c_str()); 568 #endif 569 if(a_data) { 570 size_t num = m_size/sizeof(float); 571 m_data = new float[num]; 572 #ifdef TOOLS_MEM 573 tools::mem::increment(tools::s_new().c_str()); 574 #endif 575 ::memcpy(m_data,a_data,m_size); 576 } 577 } 578 virtual ~gsto_t() { 579 if(m_kind==kind_texture) { 580 ::glDeleteTextures(1,&m_gl_id); 581 #ifdef TOOLS_MEM 582 tools::mem::decrement(tools::s_tex().c_str()); 583 #endif 584 } else if(m_kind==kind_buffer) { 585 #ifdef TOOLX_HAS_GL_VBO 586 ::glDeleteBuffers(1,&m_gl_id); 587 #ifdef TOOLS_MEM 588 tools::mem::decrement(tools::s_gsto().c_str()); 589 #endif 590 #endif 591 } else if(m_kind==kind_list) { 592 if(m_gl_id) { 593 #ifdef TOOLX_HAS_GL_LIST 594 ::glDeleteLists(m_gl_id,1); 595 #ifdef TOOLS_MEM 596 tools::mem::decrement(tools::s_gsto().c_str()); 597 #endif 598 #endif 599 } 600 } 601 602 if(m_data) { 603 delete [] m_data; 604 #ifdef TOOLS_MEM 605 tools::mem::decrement(tools::s_new().c_str()); 606 #endif 607 } 608 #ifdef TOOLS_MEM 609 tools::mem::decrement(s_class().c_str()); 610 #endif 611 } 612 private: 613 gsto_t(const gsto_t& a_from) 614 :m_gl_id(a_from.m_gl_id) 615 ,m_kind(a_from.m_kind) 616 ,m_size(a_from.m_size) 617 ,m_data(0) 618 { 619 #ifdef TOOLS_MEM 620 tools::mem::increment(s_class().c_str()); 621 #endif 622 if(a_from.m_data) { 623 size_t num = m_size/sizeof(float); 624 m_data = new float[num]; 625 #ifdef TOOLS_MEM 626 tools::mem::increment(tools::s_new().c_str()); 627 #endif 628 ::memcpy(m_data,a_from.m_data,m_size); 629 } 630 } 631 gsto_t& operator=(const gsto_t& a_from){ 632 if(&a_from==this) return *this; 633 m_gl_id = a_from.m_gl_id; 634 m_kind = a_from.m_kind; 635 m_size = a_from.m_size; 636 if(m_data) { 637 delete [] m_data; 638 #ifdef TOOLS_MEM 639 tools::mem::decrement(tools::s_new().c_str()); 640 #endif 641 m_data = 0; 642 } 643 if(a_from.m_data) { 644 size_t num = m_size/sizeof(float); 645 m_data = new float[num]; 646 #ifdef TOOLS_MEM 647 tools::mem::increment(tools::s_new().c_str()); 648 #endif 649 ::memcpy(m_data,a_from.m_data,m_size); 650 } 651 return *this; 652 } 653 public: 654 bool is_valid() const { 655 if(m_kind==kind_texture) { 656 return (::glIsTexture(m_gl_id)==GL_TRUE?true:false); 657 } else if(m_kind==kind_buffer) { 658 #ifdef TOOLX_HAS_GL_VBO 659 return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false); 660 #endif 661 } else if(m_kind==kind_list) { 662 #ifdef TOOLX_HAS_GL_LIST 663 return (::glIsList(m_gl_id)==GL_TRUE?true:false); 664 #endif 665 } else if(m_kind==kind_memory) { 666 return true; 667 } 668 return false; 669 } 670 void bind() const { 671 if(m_kind==kind_texture) { 672 ::glBindTexture(GL_TEXTURE_2D,m_gl_id); 673 } else if(m_kind==kind_buffer) { 674 #ifdef TOOLX_HAS_GL_VBO 675 ::glBindBuffer(GL_ARRAY_BUFFER,m_gl_id); 676 #endif 677 } 678 } 679 public: 680 unsigned int m_gl_id; 681 kind m_kind; 682 size_t m_size; 683 float* m_data; 684 }; 685 686 std::map<unsigned int,gsto_t*> m_gstos; 687 688 unsigned int m_gen_id; 689 tools::sg::gsto_mode m_gsto_mode; 690 bool m_warned; 691 }; 692 693 }} 694 695 #endif