697 lines
20 KiB
Plaintext
697 lines
20 KiB
Plaintext
// Copyright (C) 2010, Guy Barrand. All rights reserved.
|
|
// See the file tools.license for terms.
|
|
|
|
#ifndef tools_sg_GL_manager
|
|
#define tools_sg_GL_manager
|
|
|
|
#include "gl"
|
|
#include "../glbuf"
|
|
|
|
#include <tools/sg/render_manager>
|
|
#include <tools/mapmanip>
|
|
#include <tools/carray>
|
|
|
|
#include <cmath> //::sqrt
|
|
|
|
#ifdef TOOLS_MEM
|
|
#include <tools/mem>
|
|
#endif
|
|
|
|
namespace tools {
|
|
namespace sg {
|
|
|
|
class GL_manager : public virtual tools::sg::render_manager {
|
|
typedef tools::sg::render_manager parent;
|
|
public:
|
|
TOOLS_SCLASS(tools::sg::GL_manager)
|
|
virtual void* cast(const std::string& a_class) const {
|
|
if(void* p = tools::cmp_cast<GL_manager>(this,a_class)) {return p;}
|
|
else return 0;
|
|
}
|
|
public:
|
|
virtual bool begin_render(int a_x,int a_y,unsigned int a_ww,unsigned int a_wh,
|
|
float a_r,float a_g,float a_b,float a_a,bool a_clear = true) {
|
|
gl_clear_errors();
|
|
|
|
#if TARGET_OS_IPHONE
|
|
#elif defined(ANDROID)
|
|
#elif _WIN32
|
|
#elif __APPLE__ // Cocoa
|
|
// to avoid a 0x506 error message :
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
#if GL_ARB_framebuffer_object
|
|
if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
|
|
//m_out << "tools::sg::GL_manager::begin_render :"
|
|
// << " frame buffer not complete."
|
|
// << std::endl;
|
|
return false;
|
|
}
|
|
#endif //GL_ARB_framebuffer_object
|
|
#endif //TOOLS_HAS_GL_VBO
|
|
#else
|
|
#endif
|
|
|
|
// WARNING : the values set here must match the default values in sg::state.
|
|
|
|
// Antialiasing :
|
|
#if TARGET_OS_IPHONE
|
|
#elif defined(ANDROID)
|
|
::glEnable(GL_MULTISAMPLE);
|
|
#elif _WIN32
|
|
#elif __APPLE__
|
|
::glEnable(GL_MULTISAMPLE); //Cocoa
|
|
#else
|
|
#endif
|
|
|
|
/* NOTE : not GL-ES :
|
|
// ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
// The upper is cruely lacking with povama solid+light.
|
|
// ::glEnable(GL_LINE_STIPPLE);
|
|
|
|
::glDisable(GL_POLYGON_SMOOTH);
|
|
::glAccum(GL_LOAD,1.0f);
|
|
::glAccum(GL_RETURN,1.0f);
|
|
::glReadBuffer(GL_FRONT);
|
|
|
|
NOTE : GL_POLYGON_SMOOTH is here on Cocoa/AGL, Windows/WGL but it
|
|
does nothing.
|
|
*/
|
|
|
|
#if TARGET_OS_IPHONE
|
|
// GL-ES
|
|
#elif defined(ANDROID)
|
|
// GL-ES
|
|
#else
|
|
::glDisable(GL_POLYGON_STIPPLE); //CoinGL : reading a .wrl having Material::transparency may enable GL_POLYGON_STIPPLE.
|
|
#endif
|
|
|
|
/*
|
|
::printf("debug : is enabled %d\n",::glIsEnabled(GL_COLOR_MATERIAL));
|
|
{GLfloat v[4];
|
|
::glGetMaterialfv(GL_FRONT,GL_AMBIENT,v);
|
|
::printf("debug : ambient : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
|
{GLfloat v[4];
|
|
::glGetMaterialfv(GL_FRONT,GL_DIFFUSE,v);
|
|
::printf("debug : diffuse : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
|
{GLfloat v[4];
|
|
::glGetMaterialfv(GL_FRONT,GL_SPECULAR,v);
|
|
::printf("debug : specular : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
|
{GLfloat v[4];
|
|
::glGetMaterialfv(GL_FRONT,GL_EMISSION,v);
|
|
::printf("debug : emission : %g %g %g %g\n",v[0],v[1],v[2],v[3]);}
|
|
{GLfloat shine;
|
|
::glGetMaterialfv(GL_FRONT,GL_SHININESS,&shine);
|
|
::printf("debug : shine : %g\n",shine);}
|
|
debug : is enabled 0
|
|
debug : ambient : 0.2 0.2 0.2 1
|
|
debug : diffuse : 0.8 0.8 0.8 1
|
|
debug : specular : 0 0 0 1
|
|
debug : emission : 0 0 0 1
|
|
debug : shine : 0
|
|
*/
|
|
|
|
::glEnable(GL_NORMALIZE);
|
|
::glShadeModel(GL_FLAT);
|
|
//::glShadeModel(GL_SMOOTH);
|
|
// GL-ES : ::glMaterialfv does not work. We then use :
|
|
// ::glEnable(GL_COLOR_MATERIAL) and ::glColor.
|
|
//::glColorMaterial(GL_FRONT, GL_DIFFUSE); //?
|
|
::glEnable(GL_COLOR_MATERIAL);
|
|
|
|
/*
|
|
debug : is enabled 1
|
|
debug : ambient : 1 1 1 1
|
|
debug : diffuse : 1 1 1 1
|
|
debug : specular : 0 0 0 1
|
|
debug : emission : 0 0 0 1
|
|
debug : shine : 0
|
|
*/
|
|
|
|
// to handle transparency (same as SoGLRenderAction::SCREEN_DOOR ?) :
|
|
//::glEnable(GL_BLEND);
|
|
// NOTE : with Cocoa+AppleGL on macOS-10.14 (Mojave), it appears that points are blended ! (Even if alpha color is 1).
|
|
// Seen with some simulated catalog of galaxies done for LSST/DC2.
|
|
// To master this, we disable GL_BLEND by default. Then people wanting some transparency have to
|
|
// use the tools::sg::blend node in their scene graph.
|
|
::glDisable(GL_BLEND); //must be in sync with tools::sg::state.m_GL_BLEND and sg::blend node default.
|
|
::glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
//WARNING : the below glEnable/glDisable corresponds
|
|
// to defaults in tools::sg::state.
|
|
::glEnable(GL_DEPTH_TEST);
|
|
::glDisable(GL_LIGHTING);
|
|
::glFrontFace(GL_CCW);
|
|
::glEnable(GL_CULL_FACE);
|
|
::glDisable(GL_POLYGON_OFFSET_FILL);
|
|
::glDisable(GL_TEXTURE_2D);
|
|
|
|
::glDisable(GL_POINT_SMOOTH);
|
|
::glPointSize(1);
|
|
::glDisable(GL_LINE_SMOOTH); //NOTE : it does not work on all platforms !
|
|
::glLineWidth(1);
|
|
|
|
::glViewport(a_x,a_y,a_ww,a_wh);
|
|
|
|
// NOTE : iOS : glScissor logic does not work properly with Apple multisampling.
|
|
// But it appears that it is not needed for VR split views.
|
|
// Here a combination glViewport+[correct camera lrbt] does the clipping job (???).
|
|
// (But the clear color should be the same for both views).
|
|
//::glEnable(GL_SCISSOR_TEST);
|
|
//::glScissor(a_x,a_y,a_ww,a_wh);
|
|
|
|
//NOTE : a=0 coworks with the below logic to handle transparent background.
|
|
if(a_clear) {
|
|
::glClearColor(a_r,a_g,a_b,0);
|
|
::glClear(GL_COLOR_BUFFER_BIT);
|
|
::glClear(GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
//WARNING : Android, iPhone : only one glPushMatrix ok !
|
|
::glMatrixMode(GL_PROJECTION);
|
|
::glLoadIdentity();
|
|
|
|
//WARNING : we take the convention that the current mode is MODELVIEW
|
|
::glMatrixMode(GL_MODELVIEW);
|
|
::glLoadIdentity();
|
|
|
|
//m_clear_color.set_a(0.2);
|
|
|
|
// to handle a transparent background :
|
|
//NOTE : not tested on Android and iOS.
|
|
// dst color :
|
|
// cr * alpha + cr * (1-alpha) = cr
|
|
// cg * alpha + cg * (1-alpha) = cg
|
|
// cb * alpha + cb * (1-alpha) = cb
|
|
// alpha*alpha + 0 * (1-alpha) = ca => alpha = sqrt(ca)
|
|
|
|
{::glColor4f(a_r,a_g,a_b,::sqrt(a_a));
|
|
float xyzs[12];
|
|
xyzs[0] = -1;xyzs[ 1] = -1;xyzs[ 2] = 0;
|
|
xyzs[3] = 1;xyzs[ 4] = -1;xyzs[ 5] = 0;
|
|
xyzs[6] = 1;xyzs[ 7] = 1;xyzs[ 8] = 0;
|
|
xyzs[9] = -1;xyzs[10] = 1;xyzs[11] = 0;
|
|
::glDisable(GL_DEPTH_TEST);
|
|
::glEnableClientState(GL_VERTEX_ARRAY);
|
|
::glVertexPointer(3,GL_FLOAT,0,xyzs);
|
|
::glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
|
::glDisableClientState(GL_VERTEX_ARRAY);
|
|
::glEnable(GL_DEPTH_TEST);}
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual void end_render() {
|
|
::glFinish();
|
|
gl_dump_if_errors(m_out,"tools::sg::GL_manager::end_render :");
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
/// texture : //////////////////////////////////
|
|
////////////////////////////////////////////////
|
|
virtual unsigned int create_texture(const tools::img_byte& a_img,bool a_NEAREST) {
|
|
|
|
unsigned int gl_id;
|
|
::glGenTextures(1,&gl_id);
|
|
if(!gl_id) return 0;
|
|
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_tex().c_str());
|
|
#endif
|
|
unsigned int gsto_size = a_img.size();
|
|
::glBindTexture(GL_TEXTURE_2D,gl_id);
|
|
bool status = true;
|
|
{int sz;
|
|
::glGetIntegerv(GL_MAX_TEXTURE_SIZE,&sz);
|
|
// MacBookPro : it returns 8192.
|
|
// Android : it returns 2048.
|
|
// iPad1 : it returns 2048.
|
|
// iPod : it returns ?
|
|
//::printf("debug : GL_MAX_TEXTURE_SIZE : %d\n",sz);
|
|
tools::img_byte res;
|
|
if(!sz) {
|
|
m_out << "tools::sg::gl::tex_img : warning : GL_MAX_TEXTURE_SIZE is zero." << std::endl;
|
|
status = gl_tex_img(m_out,a_img);
|
|
} else {
|
|
if(a_img.check_gl_limit(sz,res)) {
|
|
if(res.is_empty()) { //a_img does not exceed.
|
|
status = gl_tex_img(m_out,a_img);
|
|
} else {
|
|
m_out << "tools::sg::gl::tex_img : warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ")." << std::endl;
|
|
status = gl_tex_img(m_out,res);
|
|
gsto_size = res.size();
|
|
}
|
|
} else {
|
|
m_out << "tools::sg::gl::tex_img :"
|
|
<< " warning : img size > GL_MAX_TEXTURE_SIZE (" << sz << ") but can't reduce."
|
|
<< std::endl;
|
|
status = false;
|
|
}}}
|
|
|
|
if(a_NEAREST) {
|
|
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); //good to see astro images pixels.
|
|
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); //idem.
|
|
} else {
|
|
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
|
|
::glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
}
|
|
::glBindTexture(GL_TEXTURE_2D,0);
|
|
|
|
if(!status) {
|
|
gl_dump_if_errors(m_out,"tools::sg::GL_manager::create_texture (1) :");
|
|
::glDeleteTextures(1,&gl_id);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_tex().c_str());
|
|
#endif
|
|
gl_id = 0;
|
|
gl_clear_errors();
|
|
return 0;
|
|
}
|
|
|
|
if(gl_dump_if_errors(m_out,"tools::sg::GL_manager::create_texture (2) :")) {
|
|
::glDeleteTextures(1,&gl_id);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_tex().c_str());
|
|
#endif
|
|
gl_id = 0;
|
|
gl_clear_errors();
|
|
return 0;
|
|
}
|
|
|
|
unsigned int _id = m_gen_id;m_gen_id++;
|
|
m_gstos[_id] = new gsto_t(gsto_t::kind_texture,gl_id,gsto_size,0);
|
|
return _id;
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
/// VBO ////////////////////////////////////////
|
|
////////////////////////////////////////////////
|
|
virtual unsigned int create_gsto_from_data(size_t a_floatn,const float* a_data) {
|
|
if(!a_floatn) return 0;
|
|
switch(m_gsto_mode) {
|
|
case tools::sg::gsto_gl_vbo:{
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
unsigned int gl_id = 0;
|
|
::glGenBuffers(1,&gl_id);
|
|
if(!gl_id) {
|
|
if(!m_warned) {
|
|
m_warned = true;
|
|
m_out << "tools::sg::GL_manager::create_gsto_from_data : glGenBuffers failed ()." << std::endl;
|
|
}
|
|
return 0;
|
|
}
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_gsto().c_str());
|
|
#endif
|
|
|
|
::glBindBuffer(GL_ARRAY_BUFFER,gl_id);
|
|
::glBufferData(GL_ARRAY_BUFFER,
|
|
a_floatn*sizeof(float),a_data,
|
|
GL_STATIC_DRAW);
|
|
::glBindBuffer(GL_ARRAY_BUFFER,0);
|
|
|
|
if(gl_dump_if_errors(m_out,"tools::sg::GL_manager::create_gsto_from_data :")) {
|
|
::glDeleteBuffers(1,&gl_id);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_gsto().c_str());
|
|
#endif
|
|
gl_id = 0;
|
|
gl_clear_errors();
|
|
return 0;
|
|
}
|
|
|
|
unsigned int _id = m_gen_id;m_gen_id++;
|
|
m_gstos[_id] = new gsto_t(gsto_t::kind_buffer,gl_id,a_floatn*sizeof(float),0);
|
|
return _id;
|
|
#else //!TOOLS_HAS_GL_VBO
|
|
m_out << "tools::sg::GL_manager::create_gsto_from_data :"
|
|
<< " gsto mode is gl_vbo but class not compiled with TOOLS_HAS_GL_VBO."
|
|
<< std::endl;
|
|
return 0;
|
|
#endif //TOOLS_HAS_GL_VBO
|
|
}break;
|
|
case tools::sg::gsto_gl_list:{
|
|
unsigned int gl_id = 0;
|
|
unsigned int _id = m_gen_id;m_gen_id++;
|
|
m_gstos[_id] = new gsto_t(gsto_t::kind_list,gl_id,a_floatn*sizeof(float),a_data);
|
|
return _id;
|
|
}break;
|
|
case tools::sg::gsto_memory:{
|
|
unsigned int gl_id = 0;
|
|
unsigned int _id = m_gen_id;m_gen_id++;
|
|
m_gstos[_id] = new gsto_t(gsto_t::kind_memory,gl_id,a_floatn*sizeof(float),a_data);
|
|
return _id;
|
|
}break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
virtual bool is_gsto_id_valid(unsigned int a_id) const {
|
|
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
|
if(it==m_gstos.end()) return false;
|
|
return (*it).second->is_valid();
|
|
}
|
|
|
|
virtual void delete_gsto(unsigned int a_id){
|
|
tools::delete_key<unsigned int,gsto_t>(m_gstos,a_id);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////
|
|
|
|
float* gsto_data(unsigned int a_id) const {
|
|
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
|
if(it==m_gstos.end()) return 0;
|
|
return (*it).second->m_data;
|
|
}
|
|
|
|
unsigned int gsto_gl_list_id(unsigned int a_id,bool& a_created) const {
|
|
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
|
if(it==m_gstos.end()) {a_created = false;return 0;}
|
|
if((*it).second->m_kind!=gsto_t::kind_list) {a_created = false;return 0;}
|
|
if((*it).second->m_gl_id) {
|
|
a_created = false;
|
|
return (*it).second->m_gl_id;
|
|
} else {
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
unsigned int _id = ::glGenLists(1);
|
|
if(!_id) {a_created = false;return 0;}
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_gsto().c_str());
|
|
#endif
|
|
a_created = true;
|
|
(*it).second->m_gl_id = _id;
|
|
return _id;
|
|
#else
|
|
a_created = false;
|
|
return 0;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////
|
|
virtual tools::sg::gsto_mode get_gsto_mode() const {return m_gsto_mode;}
|
|
|
|
virtual void set_gsto_mode(tools::sg::gsto_mode a_v) {
|
|
if(a_v==m_gsto_mode) return;
|
|
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
|
switch(a_v) {
|
|
case tools::sg::gsto_gl_vbo:{
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
m_gsto_mode = a_v;
|
|
#else
|
|
m_gsto_mode = tools::sg::gsto_memory;
|
|
#endif
|
|
}break;
|
|
case tools::sg::gsto_gl_list:{
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
m_gsto_mode = a_v;
|
|
#else
|
|
m_gsto_mode = tools::sg::gsto_memory;
|
|
#endif
|
|
}break;
|
|
case tools::sg::gsto_memory:{
|
|
m_gsto_mode = tools::sg::gsto_memory;
|
|
}break;
|
|
}
|
|
}
|
|
|
|
virtual void available_gsto_modes(std::vector<std::string>& a_vs) {
|
|
a_vs.clear();
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
a_vs.push_back(tools::sg::s_gsto_gl_vbo());
|
|
#endif
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
a_vs.push_back(tools::sg::s_gsto_gl_list());
|
|
#endif
|
|
a_vs.push_back(tools::sg::s_gsto_memory());
|
|
}
|
|
|
|
virtual void available_not_memory_gsto_mode(std::string& a_v) const {
|
|
a_v.clear();
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
a_v = tools::sg::s_gsto_gl_vbo();
|
|
#endif
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
if(a_v.empty()) a_v = tools::sg::s_gsto_gl_list();
|
|
#endif
|
|
}
|
|
|
|
virtual size_t used_texture_memory() const {
|
|
size_t sz = 0;
|
|
std::map<unsigned int,gsto_t*>::const_iterator it;
|
|
for(it=m_gstos.begin();it!=m_gstos.end();++it) {
|
|
if((*it).second->m_kind==gsto_t::kind_texture) sz += (*it).second->m_size;
|
|
}
|
|
return sz;
|
|
}
|
|
|
|
virtual size_t gstos_size() const {
|
|
size_t sz = 0;
|
|
std::map<unsigned int,gsto_t*>::const_iterator it;
|
|
for(it=m_gstos.begin();it!=m_gstos.end();++it) sz += (*it).second->m_size;
|
|
return sz;
|
|
}
|
|
|
|
public:
|
|
GL_manager(std::ostream& a_out)
|
|
:m_out(a_out)
|
|
,m_gen_id(1)
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs.
|
|
#elif TOOLS_HAS_GL_LIST
|
|
,m_gsto_mode(tools::sg::gsto_gl_list)
|
|
#else
|
|
,m_gsto_mode(tools::sg::gsto_memory)
|
|
#endif
|
|
,m_warned(false)
|
|
{}
|
|
virtual ~GL_manager(){
|
|
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
|
}
|
|
public:
|
|
GL_manager(const GL_manager& a_from)
|
|
:parent(a_from)
|
|
,m_out(a_from.m_out)
|
|
,m_gen_id(a_from.m_gen_id)
|
|
,m_gsto_mode(a_from.m_gsto_mode)
|
|
,m_warned(false)
|
|
{}
|
|
GL_manager& operator=(const GL_manager& a_from){
|
|
if(&a_from==this) return *this;
|
|
m_gen_id = a_from.m_gen_id;
|
|
m_gsto_mode = a_from.m_gsto_mode;
|
|
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
|
m_warned = false;
|
|
return *this;
|
|
}
|
|
|
|
public:
|
|
void bind_gsto(unsigned int a_id) {
|
|
std::map<unsigned int,gsto_t*>::const_iterator it = m_gstos.find(a_id);
|
|
if(it==m_gstos.end()) return;
|
|
(*it).second->bind();
|
|
}
|
|
|
|
void delete_gstos() {
|
|
tools::safe_clear<unsigned int,gsto_t>(m_gstos);
|
|
}
|
|
|
|
public:
|
|
|
|
static unsigned char* get_rgbas(unsigned int a_w,unsigned int a_h) {
|
|
//WARNING : it does OpenGL. Under Android it should be executed
|
|
// in the OpenGL thread.
|
|
//NOTE : Android, iOS : RGB produces a black image.
|
|
unsigned char* rgbas = new unsigned char[4 * a_w * a_h];
|
|
if(!rgbas) return 0;
|
|
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
|
|
::glReadPixels(0,0,a_w,a_h,GL_RGBA,GL_UNSIGNED_BYTE,rgbas);
|
|
/*{size_t number = 4 * a_w * a_h;
|
|
size_t count_not_255 = 0;
|
|
for(size_t item=3;item<number;item+=4) {
|
|
unsigned char a = rgbas[item];
|
|
if(a!=255) {
|
|
::printf("%lu : %d\n",item,a);
|
|
count_not_255++;
|
|
rgbas[item] = 255;
|
|
}
|
|
}
|
|
::printf("not_255 : %lu\n",count_not_255);}*/
|
|
return rgbas;
|
|
}
|
|
|
|
#if defined(TARGET_OS_IPHONE) || defined(ANDROID)
|
|
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
|
|
unsigned char* rgbas = get_rgbas(a_w,a_h);
|
|
if(!rgbas) return 0;
|
|
unsigned char* rgbs = inlib::_4s_to_3s<unsigned char,unsigned int>(rgbas,a_w,a_h);
|
|
delete [] rgbas;
|
|
return rgbs;
|
|
}
|
|
#else
|
|
static unsigned char* get_rgbs(unsigned int a_w,unsigned int a_h) {
|
|
//WARNING : it does OpenGL. Under Android it should be executed
|
|
// in the OpenGL thread.
|
|
//NOTE : Android, iOS : RGB produces a black image.
|
|
unsigned char* rgbs = new unsigned char[3 * a_w * a_h];
|
|
if(!rgbs) return 0;
|
|
::glPixelStorei(GL_PACK_ALIGNMENT,1); //needed with Cocoa.
|
|
::glReadPixels(0,0,a_w,a_h,GL_RGB,GL_UNSIGNED_BYTE,rgbs);
|
|
return rgbs;
|
|
}
|
|
#endif
|
|
|
|
protected:
|
|
std::ostream& m_out;
|
|
|
|
class gsto_t {
|
|
TOOLS_SCLASS(GL_manager::gsto_t)
|
|
public:
|
|
enum kind {
|
|
kind_texture,
|
|
kind_buffer,
|
|
kind_list,
|
|
kind_memory
|
|
};
|
|
public:
|
|
gsto_t(kind a_kind,int a_gl_id,size_t a_size,const float* a_data)
|
|
:m_gl_id(a_gl_id)
|
|
,m_kind(a_kind)
|
|
,m_size(a_size)
|
|
,m_data(0)
|
|
{
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(s_class().c_str());
|
|
#endif
|
|
if(a_data) {
|
|
size_t num = m_size/sizeof(float);
|
|
m_data = new float[num];
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_new().c_str());
|
|
#endif
|
|
::memcpy(m_data,a_data,m_size);
|
|
}
|
|
}
|
|
virtual ~gsto_t() {
|
|
if(m_kind==kind_texture) {
|
|
::glDeleteTextures(1,&m_gl_id);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_tex().c_str());
|
|
#endif
|
|
} else if(m_kind==kind_buffer) {
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
::glDeleteBuffers(1,&m_gl_id);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_gsto().c_str());
|
|
#endif
|
|
#endif
|
|
} else if(m_kind==kind_list) {
|
|
if(m_gl_id) {
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
::glDeleteLists(m_gl_id,1);
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_gsto().c_str());
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if(m_data) {
|
|
delete [] m_data;
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_new().c_str());
|
|
#endif
|
|
}
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(s_class().c_str());
|
|
#endif
|
|
}
|
|
private:
|
|
gsto_t(const gsto_t& a_from)
|
|
:m_gl_id(a_from.m_gl_id)
|
|
,m_kind(a_from.m_kind)
|
|
,m_size(a_from.m_size)
|
|
,m_data(0)
|
|
{
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(s_class().c_str());
|
|
#endif
|
|
if(a_from.m_data) {
|
|
size_t num = m_size/sizeof(float);
|
|
m_data = new float[num];
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_new().c_str());
|
|
#endif
|
|
::memcpy(m_data,a_from.m_data,m_size);
|
|
}
|
|
}
|
|
gsto_t& operator=(const gsto_t& a_from){
|
|
if(&a_from==this) return *this;
|
|
m_gl_id = a_from.m_gl_id;
|
|
m_kind = a_from.m_kind;
|
|
m_size = a_from.m_size;
|
|
if(m_data) {
|
|
delete [] m_data;
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::decrement(tools::s_new().c_str());
|
|
#endif
|
|
m_data = 0;
|
|
}
|
|
if(a_from.m_data) {
|
|
size_t num = m_size/sizeof(float);
|
|
m_data = new float[num];
|
|
#ifdef TOOLS_MEM
|
|
tools::mem::increment(tools::s_new().c_str());
|
|
#endif
|
|
::memcpy(m_data,a_from.m_data,m_size);
|
|
}
|
|
return *this;
|
|
}
|
|
public:
|
|
bool is_valid() const {
|
|
if(m_kind==kind_texture) {
|
|
return (::glIsTexture(m_gl_id)==GL_TRUE?true:false);
|
|
} else if(m_kind==kind_buffer) {
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false);
|
|
#endif
|
|
} else if(m_kind==kind_list) {
|
|
#ifdef TOOLS_HAS_GL_LIST
|
|
return (::glIsList(m_gl_id)==GL_TRUE?true:false);
|
|
#endif
|
|
} else if(m_kind==kind_memory) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
void bind() const {
|
|
if(m_kind==kind_texture) {
|
|
::glBindTexture(GL_TEXTURE_2D,m_gl_id);
|
|
} else if(m_kind==kind_buffer) {
|
|
#ifdef TOOLS_HAS_GL_VBO
|
|
::glBindBuffer(GL_ARRAY_BUFFER,m_gl_id);
|
|
#endif
|
|
}
|
|
}
|
|
public:
|
|
unsigned int m_gl_id;
|
|
kind m_kind;
|
|
size_t m_size;
|
|
float* m_data;
|
|
};
|
|
|
|
std::map<unsigned int,gsto_t*> m_gstos;
|
|
|
|
bool m_gsto_on_card;
|
|
unsigned int m_gen_id;
|
|
tools::sg::gsto_mode m_gsto_mode;
|
|
bool m_warned;
|
|
};
|
|
|
|
}}
|
|
|
|
#endif
|