Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
+28
View File
@@ -0,0 +1,28 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_OpenGL
#define toolx_OpenGL
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if TARGET_OS_IPHONE
#include <OpenGLES/ES1/gl.h>
#elif defined(ANDROID)
#include <GLES/gl.h>
#elif _WIN32
#include <windows.h>
#include <GL/gl.h>
#elif __APPLE__
#if defined(TOOLX_USE_GL_GL_H) || defined(TOOLS_USE_GL_GL_H)
#include <GL/gl.h> //Macports X11 GL.
#else
#include <OpenGL/gl.h> //Apple/OpenGL.
#endif
#else
#include <GL/gl.h>
#endif
#endif
+97
View File
@@ -0,0 +1,97 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Qt_glarea
#define toolx_Qt_glarea
#include "../sg/GL_viewer"
#include <QtOpenGL/qgl.h>
#include <QtGui/qevent.h>
#include <tools/sg/device_interactor>
namespace toolx {
namespace Qt {
class glarea : public QGLWidget {
typedef QGLWidget parent;
public:
virtual void initialieGL() {}
virtual void resizeGL(int a_w,int a_h){
//::printf("debug : resize : %d %d\n",a_w,a_h);
#if QT_VERSION < 0x050000
#else
m_width = a_w;
m_height = a_h;
#endif
}
//virtual void paintGL();
virtual void paintGL() {
#if QT_VERSION < 0x050000
//::printf("debug : toolx::Qt::glarea::paintGL %d %d\n",width(),height());
m_viewer.set_size(width(),height());
#else
//::printf("debug : toolx::Qt::glarea::paintGL %d %d\n",m_width,m_height);
m_viewer.set_size(m_width,m_height);
#endif
m_viewer.render();
}
virtual void keyPressEvent(QKeyEvent* a_event) {
if(!m_interactor) return;
tools::sg::key_down_event event(convert(a_event->key()));
m_interactor->key_press(event);
}
virtual void keyReleaseEvent(QKeyEvent* a_event) {
if(!m_interactor) return;
tools::sg::key_up_event event(convert(a_event->key()));
m_interactor->key_release(event);
}
virtual void mousePressEvent(QMouseEvent* a_event) {
if(!m_interactor) return;
tools::sg::mouse_down_event event(a_event->x(),a_event->y());
m_interactor->mouse_press(event);
}
virtual void mouseReleaseEvent(QMouseEvent* a_event) {
if(!m_interactor) return;
tools::sg::mouse_up_event event(a_event->x(),a_event->y());
m_interactor->mouse_release(event);
}
virtual void mouseMoveEvent(QMouseEvent* a_event) {
if(!m_interactor) return;
tools::sg::mouse_move_event event(a_event->x(),a_event->y(),0,0,false);
m_interactor->mouse_move(event);
}
//virtual void mouseDoubleClickEvent(QMouseEvent* a_event) {
// if(!m_interactor) return;
// tools::sg::mouse_double_click_event event(a_event->x(),a_event->y());
// m_interactor->mouse_double_click(event);
//}
virtual void wheelEvent(QWheelEvent* a_event) {
if(!m_interactor) return;
tools::sg::wheel_rotate_event event(a_event->angleDelta().y());
m_interactor->wheel_rotate(event);
}
public:
glarea(QWidget* a_parent,toolx::sg::GL_viewer& a_viewer):parent(a_parent),m_viewer(a_viewer),m_interactor(0){}
virtual ~glarea(){}
public:
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
protected:
tools::key_code convert(/*Qt::Key*/int a_key) {return a_key;}
protected:
toolx::sg::GL_viewer& m_viewer;
#if QT_VERSION < 0x050000
#else
protected:
int m_width;
int m_height;
#endif
tools::sg::device_interactor* m_interactor;
};
}}
#endif
+109
View File
@@ -0,0 +1,109 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Qt_session
#define toolx_Qt_session
// pure Qt code, no GL.
#include <ostream>
#include <vector>
#include <QtCore/qglobal.h> //For QT_VERSION.
#include <QtCore/qnamespace.h>
#if QT_VERSION < 0x050000
#include <QtGui/qapplication.h>
#include <QtGui/qwidget.h>
#else
#include <QtWidgets/qapplication.h>
#include <QtWidgets/qwidget.h>
#endif
namespace toolx {
namespace Qt {
class session {
public:
session(std::ostream& a_out,int& a_argc,char** a_argv)
:m_out(a_out)
,m_qapp(0)
,m_own_qapp(false)
{
if(qApp) {
m_qapp = qApp;
m_own_qapp = false;
} else {
m_qapp = new QApplication(a_argc,a_argv);
m_own_qapp = true;
}
}
virtual ~session() {
if(m_own_qapp && m_qapp) delete m_qapp;
m_qapp = 0;
m_own_qapp = false;
}
protected:
session(const session& a_from)
:m_out(a_from.m_out)
,m_qapp(0)
,m_own_qapp(false)
{}
session& operator=(const session& a_from){
if(&a_from==this) return *this;
return *this;
}
public:
std::ostream& out() const {return m_out;}
bool is_valid() const {return m_qapp?true:false;}
bool steer() {
if(!m_qapp) return false;
m_qapp->exec();
return true;
}
bool sync() {
if(!m_qapp) return false;
//m_qapp->exec();
return true;
}
public:
QApplication* qapp() const {return m_qapp;}
QWidget* create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
if(!m_qapp) return 0;
#ifdef _MSC_VER
if(a_y<=0) a_y = 60;
#endif
QWidget* top = new QWidget();
top->setWindowFlags(::Qt::CustomizeWindowHint
| ::Qt::WindowTitleHint
| ::Qt::WindowMinMaxButtonsHint
// | ::Qt::WindowSystemMenuHint
// | ::Qt::WindowFullscreenButtonHint
);
top->setGeometry(a_x,a_y,a_width,a_height);
top->setWindowTitle(s2q(a_title));
//top->setAttribute(Qt::WA_DeleteOnClose,false);
return top;
}
void delete_window(QWidget* a_window) const {
if(!m_qapp) return;
delete a_window;
}
protected:
QString s2q(const std::string& a_s) {
#if QT_VERSION < 0x050000
return QString::fromAscii(a_s.c_str());
#else
return QString::fromLatin1(a_s.c_str());
#endif
}
protected:
std::ostream& m_out;
QApplication* m_qapp;
bool m_own_qapp;
};
}}
#endif
+101
View File
@@ -0,0 +1,101 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Qt_sg_viewer
#define toolx_Qt_sg_viewer
#include "glarea"
#include "session"
#include <QtCore/qglobal.h> //For QT_VERSION.
#if QT_VERSION < 0x050000
#include <QtGui/qboxlayout.h>
#else
#include <QtWidgets/qboxlayout.h>
#endif
namespace toolx {
namespace Qt {
class sg_viewer : public sg::GL_viewer {
typedef sg::GL_viewer parent;
public:
sg_viewer(session& a_session,
int a_x = 0,int a_y = 0,
unsigned int a_width = 500,unsigned int a_height = 500,
const std::string& a_win_title = "")
:parent(a_session.out(),a_width,a_height)
,m_session(a_session)
,m_shell(0)
,m_own_shell(false)
,m_glarea(0)
{
if(!m_session.is_valid()) return; //throw
m_shell = m_session.create_window(a_win_title.c_str(),a_x,a_y,a_width,a_height);
if(!m_shell) return; //throw
m_own_shell = true;
m_glarea = new Qt::glarea(0,*this);
QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0,0,0,0);
layout->addWidget(m_glarea);
m_shell->setLayout(layout);
}
virtual ~sg_viewer() {
if(m_glarea) m_glarea->set_device_interactor(0);
if(m_shell && m_own_shell) {
m_session.delete_window(m_shell);
//m_session.sync();
}
}
protected:
sg_viewer(const sg_viewer& a_from)
:parent(a_from)
,m_session(a_from.m_session)
,m_shell(0)
,m_own_shell(false)
,m_glarea(0)
{}
sg_viewer& operator=(const sg_viewer& a_from){
parent::operator=(a_from);
return *this;
}
public:
bool has_window() const {return m_shell?true:false;} //for SWIG
bool show() {
if(!m_shell) return false;
m_shell->show();
return true;
}
void win_render() {
if(!m_glarea) return;
m_glarea->update();
}
public:
QWidget* shell() {return m_shell;}
void set_own_shell(bool a_value) {m_own_shell = a_value;}
Qt::glarea* glarea() {return m_glarea;}
void set_device_interactor(tools::sg::device_interactor* a_interactor) { //we do not have ownership.
if(!m_glarea) return;
m_glarea->set_device_interactor(a_interactor);
}
void enable_keyboard_focus() {
if(!m_glarea) return;
m_glarea->setFocusPolicy(::Qt::StrongFocus);
}
protected:
session& m_session;
QWidget* m_shell;
bool m_own_shell;
Qt::glarea* m_glarea;
};
}}
#endif
+418
View File
@@ -0,0 +1,418 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Windows_glarea
#define toolx_Windows_glarea
#include <windows.h>
#include <windowsx.h>
#include <wingdi.h>
#include <tools/sg/device_interactor>
#include <tools/sg/keys>
//#include <tools/log_file>
#include <string>
#if defined(_MSC_VER) && _MSC_VER < 1900
#else
#define TOOLX_WINDOWS_TOUCH
#endif
namespace toolx {
namespace Windows {
#ifdef TOOLX_WINDOWS_TOUCH
inline bool is_message_touch_event() {
// from https://stackoverflow.com/questions/29857587/detect-if-wm-mousemove-is-caused-by-touch-pen.
static const LONG_PTR c_SIGNATURE_MASK = 0xFFFFFF00;
static const LONG_PTR c_MOUSEEVENTF_FROMTOUCH = 0xFF515700;
LONG_PTR extraInfo = ::GetMessageExtraInfo();
return ( ( extraInfo & c_SIGNATURE_MASK ) == c_MOUSEEVENTF_FROMTOUCH );
}
#endif
class glarea {
static const std::string& s_class() {
static const std::string s_v("toolx::Windows::glarea");
return s_v;
}
static void register_class(){
static bool s_done = false; //not const, then not thread safe.
if(!s_done) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ::GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
wc.lpszMenuName = s_class().c_str();
wc.lpszClassName = s_class().c_str();
::RegisterClass(&wc);
s_done = true;
}
}
public:
virtual void resize(unsigned int,unsigned int){}
virtual void paint(unsigned int a_w,unsigned int a_h) {}
virtual void close(){}
virtual void left_button_up(unsigned int a_x,unsigned int a_y) {}
virtual void left_button_down(unsigned int a_x,unsigned int a_y) {}
virtual void mouse_move(unsigned int a_x,unsigned int a_y,bool) {}
public:
glarea(HWND a_parent)
:m_parent(a_parent)
,m_hwnd(0)
,m_context(0)
,m_HDC(0)
,m_touch_available(false)
,m_interactor(0)
{
register_class();
// The WS_BORDER is needed. Else probleme of size at startup.
RECT rect;
::GetClientRect(m_parent,&rect);
//printf("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
//toolx::log_file::get().writef("debug : glarea : ca : %d %d\n",rect.right-rect.left,rect.bottom-rect.top);
m_hwnd = ::CreateWindow(s_class().c_str(),
NULL,
WS_CHILD | WS_VISIBLE,
0,0,
rect.right-rect.left,
rect.bottom-rect.top,
m_parent,NULL,
GetWindowInstance(m_parent),
NULL);
if(!m_hwnd) return;
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
// initialize OpenGL rendering :
m_HDC = ::GetDC(m_hwnd);
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
m_context = ::wglCreateContext(m_HDC);
}
#ifdef TOOLX_WINDOWS_TOUCH
{BYTE digitizer_status = (BYTE)::GetSystemMetrics(SM_DIGITIZER);
if((digitizer_status & (0x80 + 0x40)) == 0) {
m_touch_available = false;
} else {
//BYTE nInputs = (BYTE)::GetSystemMetrics(SM_MAXIMUMTOUCHES);
m_touch_available = true;
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
}}
#endif
}
virtual ~glarea(){
if(::wglGetCurrentContext()!=NULL) ::wglMakeCurrent(NULL,NULL);
if(m_context) {
::wglDeleteContext(m_context);
m_context = 0;
}
if(m_HDC && m_hwnd) ::ReleaseDC(m_hwnd,m_HDC);
if(m_hwnd) {
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
::DestroyWindow(m_hwnd);
m_hwnd = 0;
}
}
protected:
glarea(const glarea& a_from)
:m_parent(a_from.m_parent)
,m_hwnd(0)
,m_context(0)
,m_HDC(0)
,m_touch_available(a_from.m_touch_available)
,m_interactor(0)
{
if(!m_parent) return;
register_class();
RECT rect;
::GetClientRect(m_parent,&rect);
m_hwnd = ::CreateWindow(s_class().c_str(),
NULL,
WS_CHILD | WS_VISIBLE,
0,0,
rect.right-rect.left,
rect.bottom-rect.top,
m_parent,NULL,
GetWindowInstance(m_parent),
NULL);
if(!m_hwnd) return;
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
// initialize OpenGL rendering :
m_HDC = ::GetDC(m_hwnd);
if(m_HDC && SetWindowPixelFormat(m_HDC) ) {
m_context = ::wglCreateContext(m_HDC);
}
#ifdef TOOLX_WINDOWS_TOUCH
if(a_from.m_touch_available) {
if(!::RegisterTouchWindow(m_hwnd,0)) m_touch_available = false;
}
#endif
}
protected:
glarea& operator=(const glarea&){return *this;}
public:
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
RECT rect;
::GetClientRect(m_hwnd,&rect);
::MoveWindow(m_hwnd,rect.left,rect.top,a_w,a_h,TRUE);
}
HWND hwnd() const {return m_hwnd;}
void post_WM_PAINT() const {
::PostMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
}
void send_WM_PAINT() const {
::SendMessage(m_hwnd,WM_PAINT,(WPARAM)0,(LPARAM)0);
}
void wm_paint() {
PAINTSTRUCT ps;
//HDC hDC =
BeginPaint(m_hwnd,&ps);
if(m_HDC && m_context) {
::wglMakeCurrent(m_HDC,m_context);
RECT rect;
::GetClientRect(m_hwnd,&rect);
unsigned int w = rect.right-rect.left;
unsigned int h = rect.bottom-rect.top;
//printf("debug : glarea : paint : %d %d\n",w,h);
//toolx::log_file::get().writef("debug : glarea : paint : %d %d\n",w,h);
paint(w,h);
::SwapBuffers(m_HDC);
::wglMakeCurrent(m_HDC,0);
}
EndPaint(m_hwnd,&ps);
}
public:
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
protected:
bool is_touch_event() {
#ifdef TOOLX_WINDOWS_TOUCH
if(!m_touch_available) return false;
return is_message_touch_event();
#else
return false;
#endif
}
protected:
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
switch (a_msg) {
case WM_SIZE:{
int width = LOWORD(a_lparam);
int height = HIWORD(a_lparam);
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
_this->resize(width,height);
} else {
// CreateWindow send a WM_SIZE but GWLP_USERDATA not yet set.
}
}return 0;
case WM_PAINT:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->wm_paint();
}return 0;
case WM_KEYDOWN:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::key_down_event event(_this->convert(a_wparam));
_this->m_interactor->key_press(event);
}
}
} return 0;
case WM_KEYUP:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::key_up_event event(_this->convert(a_wparam));
_this->m_interactor->key_release(event);
}
}
} return 0;
case WM_LBUTTONDOWN:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::mouse_down_event event(LOWORD(a_lparam),HIWORD(a_lparam));
_this->m_interactor->mouse_press(event);
} else {
RECT rect;
::GetClientRect(a_hwnd,&rect);
unsigned int h = rect.bottom-rect.top;
if(!_this->is_touch_event()) _this->left_button_down(LOWORD(a_lparam),h-HIWORD(a_lparam));
}
}
}return 0;
case WM_LBUTTONUP:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::mouse_up_event event(LOWORD(a_lparam),HIWORD(a_lparam));
_this->m_interactor->mouse_release(event);
} else {
RECT rect;
::GetClientRect(a_hwnd,&rect);
unsigned int h = rect.bottom-rect.top;
if(!_this->is_touch_event()) _this->left_button_up(LOWORD(a_lparam),h-HIWORD(a_lparam));
}
}
} return 0;
case WM_MOUSEMOVE:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::mouse_move_event event(LOWORD(a_lparam),HIWORD(a_lparam),0,0,false);
_this->m_interactor->mouse_move(event);
} else {
WPARAM state = a_wparam;
bool ldown = ((state & MK_LBUTTON)==MK_LBUTTON)?true:false;
RECT rect;
::GetClientRect(a_hwnd,&rect);
unsigned int h = rect.bottom-rect.top;
if(!_this->is_touch_event()) _this->mouse_move(LOWORD(a_lparam),h-HIWORD(a_lparam),ldown);
}
}
}return 0;
case WM_MOUSEWHEEL:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
if(_this->m_interactor) {
tools::sg::wheel_rotate_event event(GET_WHEEL_DELTA_WPARAM(a_wparam));
_this->m_interactor->wheel_rotate(event);
}
}
} return 0;
#ifdef TOOLX_WINDOWS_TOUCH
case WM_TOUCH:{
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this && _this->m_touch_available) {
RECT rect;
//::GetWindowRect(hwnd,&rect); ???
::GetClientRect(a_hwnd,&rect);
unsigned int h = rect.bottom-rect.top;
unsigned int num_inputs = (int)a_wparam;
//::printf("debug : WM_TOUCH : 001 : %d\n",num_inputs);
TOUCHINPUT* ti = new TOUCHINPUT[num_inputs];
POINT p;
if(::GetTouchInputInfo((HTOUCHINPUT)a_lparam,num_inputs,ti,sizeof(TOUCHINPUT))) {
for(unsigned int i=0;i<num_inputs; ++i) {
p.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
p.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
if(!::ScreenToClient(a_hwnd,&p)) {}
if(ti[i].dwFlags & TOUCHEVENTF_DOWN) {
//::printf("debug : TOUCHEVENTF_DOWN %lu %lu\n",p.x,p.y);
_this->left_button_down(p.x,h-p.y);
} else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
//::printf("debug : TOUCHEVENTF_UP %lu %lu\n",p.x,p.y);
_this->left_button_up(p.x,h-p.y);
} else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
bool ldown = true; //we assume that a TOUCHEVENT_DOWN had been done.
//::printf("debug : TOUCHEVENTF_MOVE %lu %lu\n",p.x,p.y);
_this->mouse_move(p.x,h-p.y,ldown);
}
}
}
::CloseTouchInputHandle((HTOUCHINPUT)a_lparam);
delete [] ti;
}
}return 0;
#endif //TOOLX_WINDOWS_TOUCH
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
}
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
}
static bool SetWindowPixelFormat(HDC a_HDC){
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags =
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_STEREO_DONTCARE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 8;
pfd.cRedShift = 16;
pfd.cGreenBits = 8;
pfd.cGreenShift = 8;
pfd.cBlueBits = 8;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 64;
pfd.cAccumRedBits = 16;
pfd.cAccumGreenBits = 16;
pfd.cAccumBlueBits = 16;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 32;
pfd.cStencilBits = 8;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
int pixelIndex = ::ChoosePixelFormat(a_HDC,&pfd);
if (pixelIndex==0) {
// Let's choose a default index.
pixelIndex = 1;
if (::DescribePixelFormat(a_HDC,
pixelIndex,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd)==0) {
return false;
}
}
if (::SetPixelFormat(a_HDC,pixelIndex,&pfd)==FALSE) return false;
return true;
}
static void wm__destroy(HWND a_hwnd) {
glarea* _this = (glarea*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) { //How to be sure that we have a glarea* ???
_this->close();
if(_this->m_hwnd!=a_hwnd) {
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
}
_this->m_hwnd = 0;
}
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
}
protected:
tools::key_code convert(WPARAM a_key) {
if(a_key==VK_SHIFT) return tools::sg::key_shift();
return (tools::key_code)a_key;
}
protected:
HWND m_parent;
HWND m_hwnd;
HGLRC m_context;
HDC m_HDC;
bool m_touch_available;
tools::sg::device_interactor* m_interactor;
};
}}
#endif
+73
View File
@@ -0,0 +1,73 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Windows_session
#define toolx_Windows_session
#include <windows.h>
#include <windowsx.h>
#include <ostream>
namespace toolx {
namespace Windows {
class session {
public:
session(std::ostream& a_out):m_out(a_out){}
virtual ~session() {}
protected:
session(const session& a_from):m_out(a_from.m_out){}
session& operator=(const session&){return *this;}
public:
std::ostream& out() const {return m_out;}
bool is_valid() const {return true;}
bool steer() {
while(true) {
MSG event;
BOOL status = ::GetMessage(&event,NULL,0,0);
if(status == -1) { // This may happen (dixit Microsoft doc).
break;
} else if(status == 0) { //WM_QUIT
break;
} else {
::TranslateMessage(&event);
::DispatchMessage (&event);
}
}
return true;
}
bool sync() {
MSG event;
while(::PeekMessage(&event,NULL,0,0,PM_REMOVE)) {
if(event.message==WM_QUIT) return false;
::TranslateMessage(&event);
::DispatchMessage(&event);
}
return true;
}
void show_window(HWND a_hwnd){
::SetForegroundWindow(a_hwnd);
::ShowWindow(a_hwnd,SW_SHOWDEFAULT);
::UpdateWindow(a_hwnd);
::DrawMenuBar(a_hwnd);
}
void set_size(HWND a_hwnd,unsigned int a_width,unsigned int a_height) {
::MoveWindow(a_hwnd,0,0,a_width,a_height,TRUE);
}
//void post(HWND a_hwnd,LPARAM a_msg){
// ::PostMessage(a_hwnd,WM_USER,(WPARAM)0,a_msg);
//}
protected:
std::ostream& m_out;
};
}}
#endif
@@ -0,0 +1,90 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Windows_sg_viewer
#define toolx_Windows_sg_viewer
#include "session"
#include "window"
#include "glarea"
#include "../sg/GL_viewer"
// disable the warning about the usage of "this" in the constructor.
#pragma warning(disable:4355)
namespace toolx {
namespace Windows {
class sg_viewer : public window, public sg::GL_viewer {
typedef window parent_window;
typedef sg::GL_viewer parent_viewer;
public:
virtual void close() {}
public:
sg_viewer(session& a_session,
int a_x = 0,int a_y = 0,
unsigned int a_width = 500,unsigned int a_height = 500,
const std::string& a_title = "")
:parent_window(a_title.c_str(),a_x,a_y,a_width,a_height)
,parent_viewer(a_session.out(),a_width,a_height)
,m_session(a_session)
,m_glarea(m_hwnd,*this)
{
parent_window::set_focus_hwnd(m_glarea.hwnd());
}
virtual ~sg_viewer() {}
protected:
sg_viewer(const sg_viewer& a_from)
:parent_window(a_from)
,parent_viewer(a_from)
,m_session(a_from.m_session)
,m_glarea(a_from.m_glarea)
{}
sg_viewer& operator=(const sg_viewer& a_from){
parent_window::operator=(a_from);
return *this;
}
public:
bool has_window() const {return m_hwnd?true:false;} //for SWIG
HWND window() const {return m_hwnd;}
bool show() {
if(!m_hwnd) return false;
m_session.show_window(m_hwnd);
return true;
}
void win_render() {m_glarea.wm_paint();}
public:
void set_device_interactor(tools::sg::device_interactor* a_interactor) { //we do not have ownership.
m_glarea.set_device_interactor(a_interactor);
}
protected:
class _glarea : public glarea {
public:
virtual void paint(unsigned int a_w,unsigned int a_h) {
m_viewer.set_size(a_w,a_h);
m_viewer.render();
}
public:
_glarea(HWND a_parent,parent_viewer& a_viewer)
:glarea(a_parent)
,m_viewer(a_viewer)
{}
protected:
parent_viewer& m_viewer;
};
protected:
session& m_session;
_glarea m_glarea;
};
}}
#endif
+250
View File
@@ -0,0 +1,250 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Windows_window
#define toolx_Windows_window
#include <windows.h>
#include <windowsx.h>
#include <string>
namespace toolx {
namespace Windows {
class window {
static const std::string& s_class() {
static const std::string s_v("toolx::Windows::window");
return s_v;
}
static void register_class(){
static bool s_done = false; //not const, then not thread safe.
if(!s_done) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ::GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
wc.lpszMenuName = s_class().c_str();
wc.lpszClassName = s_class().c_str();
::RegisterClass(&wc);
s_done = true;
}
}
public:
virtual void key_up(){}
virtual void key_down(){}
virtual void key_left(){}
virtual void key_right(){}
virtual void key_escape(){}
virtual void close(){
//if(m_hwnd) ::PostMessage(m_hwnd,WM_QUIT,0,0);
::PostQuitMessage(0);
}
public:
window(const char* a_title,int a_x,int a_y,unsigned int a_w,unsigned int a_h,unsigned int a_mask = WS_OVERLAPPEDWINDOW)
:m_hwnd(0)
,m_key_shift(false)
,m_key_ctrl(false)
,m_focus_hwnd(0)
{
// WARNING : given a_w,a_h may not be the client area because of various decorations.
// See set_client_area_size() method to enforce a client area size.
register_class();
m_hwnd = ::CreateWindow(s_class().c_str(),
NULL,
a_mask,
a_x,a_y,
a_w,a_h,
NULL,NULL,
::GetModuleHandle(NULL),
NULL);
if(!m_hwnd) return;
::SetWindowText(m_hwnd,a_title);
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
}
virtual ~window(){
if(m_hwnd) {
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
::DestroyWindow(m_hwnd);
m_hwnd = 0;
}
}
protected:
window(const window& a_from)
:m_hwnd(0)
,m_key_shift(a_from.m_key_shift)
,m_key_ctrl(a_from.m_key_ctrl)
,m_focus_hwnd(0)
{
/*
if(!a_from.m_hwnd) return;
int w,h;
get_size(a_from.m_hwnd,w,h);
register_class();
m_hwnd = ::CreateWindow(s_class().c_str(),
NULL,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
w,h,
NULL,NULL,
::GetModuleHandle(NULL),
NULL);
if(!m_hwnd) return;
::SetWindowLongPtr(m_hwnd,GWLP_USERDATA,LONG_PTR(this));
*/
}
window& operator=(const window& a_from){
m_key_shift = a_from.m_key_shift;
m_key_ctrl = a_from.m_key_ctrl;
return *this;
}
public:
const window& get_me() const {return *this;}
window& get_me() {return *this;}
bool key_shift() const {return m_key_shift;}
HWND hwnd() const {return m_hwnd;}
void set_client_area_size(unsigned int a_w,unsigned int a_h) {
if(!m_hwnd) return;
RECT wrect;
::GetWindowRect(m_hwnd,&wrect);
unsigned int ww = wrect.right-wrect.left;
unsigned int wh = wrect.bottom-wrect.top;
RECT carect;
::GetClientRect(m_hwnd,&carect);
unsigned int cw = carect.right-carect.left;
unsigned int ch = carect.bottom-carect.top;
unsigned int woffset = ww-cw;
unsigned int hoffset = wh-ch;
::MoveWindow(m_hwnd,wrect.left,wrect.top,a_w+woffset,a_h+hoffset,TRUE);
}
void move(unsigned int a_x,unsigned int a_y) {
if(!m_hwnd) return;
RECT rect;
::GetWindowRect(m_hwnd,&rect);
unsigned int w = rect.right-rect.left;
unsigned int h = rect.bottom-rect.top;
::MoveWindow(m_hwnd,a_x,a_y,w,h,TRUE);
}
void set_focus_hwnd(HWND a_hwnd) {m_focus_hwnd = a_hwnd;}
HWND focus_hwnd() const {return m_focus_hwnd;}
protected:
static LRESULT CALLBACK proc(HWND a_hwnd,UINT a_msg,WPARAM a_wparam,LPARAM a_lparam) {
switch (a_msg) {
// Else :
case WM_SIZE:{ // Assume one child window ! FIXME : have a message if not.
int width = LOWORD(a_lparam);
int height = HIWORD(a_lparam);
HWND hwnd = GetFirstChild(a_hwnd);
if(hwnd) {
::MoveWindow(hwnd,0,0,width,height,TRUE);
}
}return 0;
case WM_SETFOCUS:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) {
HWND hwnd = _this->focus_hwnd();
if(hwnd) ::SetFocus(hwnd);
}
}return 0;
case WM_KEYDOWN:{
switch(a_wparam){
case VK_SHIFT:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->m_key_shift = true;
return 0;
}
case VK_CONTROL:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->m_key_ctrl = true;
return 0;
}
case VK_UP:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->key_up();
return 0;
}
case VK_DOWN:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->key_down();
return 0;
}
case VK_LEFT:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->key_left();
return 0;
}
case VK_RIGHT:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->key_right();
return 0;
}
case VK_ESCAPE:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->key_escape();
return 0;
}
} //end switch(a_wparam)
break;
}
case WM_KEYUP:{
switch(a_wparam){
case VK_SHIFT:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->m_key_shift = false;
return 0;
}
case VK_CONTROL:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->m_key_ctrl = false;
return 0;
}
} //end switch(a_wparam)
break;
}
case WM_CLOSE:{
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) _this->close();
}break; //NOTE : can't be return 0.
case WM_DESTROY:wm__destroy(a_hwnd);return 0;
}
return (DefWindowProc(a_hwnd,a_msg,a_wparam,a_lparam));
}
static void wm__destroy(HWND a_hwnd) {
window* _this = (window*)::GetWindowLongPtr(a_hwnd,GWLP_USERDATA);
if(_this) { //How to be sure that we have a window* ???
if(_this->m_hwnd!=a_hwnd) {
//::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
}
_this->m_hwnd = 0;
}
::SetWindowLongPtr(a_hwnd,GWLP_USERDATA,LONG_PTR(NULL));
}
protected:
void get_size(HWND a_hwnd,int& a_w,int& a_h){
RECT rect;
::GetWindowRect(a_hwnd,&rect);
a_w = rect.right-rect.left;
a_h = rect.bottom-rect.top;
}
protected:
HWND m_hwnd;
bool m_key_shift;
bool m_key_ctrl;
HWND m_focus_hwnd;
};
}}
#endif
+392
View File
@@ -0,0 +1,392 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_X11_base_session
#define toolx_X11_base_session
// pure X11 code, no GL.
#include <ostream>
#include <vector>
#include "dispatcher"
#include <tools/forit>
#include <X11/Xatom.h> //XA_INTEGER
#include <X11/Xutil.h> //XVisualInfo
namespace toolx {
namespace X11 {
class base_session {
public:
//virtual bool make_current(Window) const {
// if(!m_display) return false;
// return true;
//}
//virtual bool swap_buffers(Window) const {
// if(!m_display) return false;
// return true;
//}
public:
base_session(std::ostream& a_out,unsigned int a_monitor = 0)
:m_out(a_out)
,m_monitor(a_monitor)
,m_display(0)
,m_WM_DELETE_WINDOW_atom(None)
,m_SESSION_EXIT_STEER_atom(None)
{
//NOTE : macOS : XOpenDisplay leaks 128 bytes.
m_display = ::XOpenDisplay(NULL);
if(!m_display) {
m_out << "toolx::X11::base_session::base_session : can't open display." << std::endl;
return;
}
int monitors = ::XScreenCount(m_display);
if(int(m_monitor)>=monitors) {
m_out << "toolx::X11::base_session::base_session : bad monitor index "
<< m_monitor << ". (#monitors " << monitors << ")." << std::endl;
::XCloseDisplay(m_display);
m_display = 0;
return;
}
m_WM_DELETE_WINDOW_atom = ::XInternAtom(m_display,"WM_DELETE_WINDOW",False);
if(m_WM_DELETE_WINDOW_atom==None) {
m_out << "toolx::X11::base_session::base_session : can't create WM_DELETE_WINDOW Atom." << std::endl;
::XCloseDisplay(m_display);
m_display = 0;
return;
}
m_SESSION_EXIT_STEER_atom = ::XInternAtom(m_display,"TOOLX_X11_SESSION_EXIT_STEER",False);
if(m_SESSION_EXIT_STEER_atom==None) {
m_out << "toolx::X11::base_session::base_session :"
<< " can't create TOOLX_X11_SESSION_EXIT_STEER Atom." << std::endl;
::XCloseDisplay(m_display);
m_display = 0;
return;
}
}
virtual ~base_session() {
clear_dispatchers();
if(m_display) ::XCloseDisplay(m_display);
m_display = 0;
//std::cout << "debug : ~base_session" << std::endl;
}
protected:
base_session(const base_session& a_from)
:m_out(a_from.m_out)
,m_monitor(a_from.m_monitor)
,m_display(0)
,m_WM_DELETE_WINDOW_atom(None)
,m_SESSION_EXIT_STEER_atom(None)
{}
base_session& operator=(const base_session& a_from){
if(&a_from==this) return *this;
return *this;
}
public:
std::ostream& out() const {return m_out;}
Atom WM_DELETE_WINDOW_atom() const {return m_WM_DELETE_WINDOW_atom;}
Atom SESSION_EXIT_STEER_atom() const {return m_SESSION_EXIT_STEER_atom;}
bool is_valid() const {return m_display?true:false;}
Display* display() const {return m_display;}
bool steer() {
if(!m_display) return false;
while(true) {
XEvent xevent;
::XNextEvent(m_display,&xevent);
if(xevent.type==ClientMessage) {
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) break;
}
dispatch(xevent);
}
return true;
}
bool sync() {
if(!m_display) return false;
//::glXWaitX();
::XSync(m_display,False);
while(true) {
XEvent xevent;
if(::XPending(m_display)) {
::XNextEvent(m_display,&xevent);
if(xevent.type==ClientMessage) {
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) return false;
}
dispatch(xevent);
} else {
break;
}
}
return true;
}
bool event_pending(bool& a_is) {
if(!m_display) {a_is = false;return false;}
a_is = ::XPending(m_display)?true:false;
return true;
}
bool next_event(bool& a_to_exit) {
if(!m_display) {a_to_exit = false;return false;}
XEvent xevent;
::XNextEvent(m_display,&xevent);
if(xevent.type==ClientMessage) {
if(xevent.xclient.data.l[0]==(long)m_SESSION_EXIT_STEER_atom) {
a_to_exit = true;
return true;
}
}
dispatch(xevent);
a_to_exit = false;
return true;
}
bool flush() {
if(!m_display) return false;
::XFlush(m_display);
return true;
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
if(!m_display) return 0L;
XSetWindowAttributes swa;
swa.event_mask = StructureNotifyMask | ExposureMask
| ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
| PointerMotionMask
| KeyPressMask;
swa.background_pixel = ::XWhitePixel(m_display,m_monitor);
Window window = ::XCreateWindow(m_display,
::XRootWindow(m_display,m_monitor),
a_x,a_y,a_width,a_height,
0,
(int)CopyFromParent,
InputOutput,
(Visual*)CopyFromParent,
CWEventMask|CWBackPixel,&swa);
if(window==0L) {
m_out << "toolx::X11::base_session::create_window : can't create a X11 window." << std::endl;
return 0L;
}
XTextProperty tp;
::XStringListToTextProperty((char**)&a_title,1,&tp);
XSizeHints sh;
sh.flags = USPosition | USSize;
::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0);
::XFree(tp.value);
::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1);
return window;
}
void map_raise_window(Window a_window) const {
if(!m_display) return;
::XMapWindow(m_display,a_window);
::XRaiseWindow(m_display,a_window);
}
void show_window(Window a_window) const {
if(!m_display) return;
XWindowAttributes watbs;
::XGetWindowAttributes(m_display,a_window,&watbs);
if(watbs.map_state!=IsUnmapped) return;
::XMapWindow(m_display,a_window);
::XRaiseWindow(m_display,a_window);
{XEvent event;
::XIfEvent(m_display,&event,wait_map_notify,(char*)a_window);}
}
void hide_window(Window a_window) const {
if(!m_display) return;
XWindowAttributes watbs;
::XGetWindowAttributes(m_display,a_window,&watbs);
if(watbs.map_state==IsUnmapped) return;
::XUnmapWindow(m_display,a_window);
{XEvent event;
::XIfEvent(m_display,&event,wait_unmap_notify,(char*)a_window);}
}
void resize_window(Window a_window,unsigned int a_width,unsigned int a_height) const {
if(!m_display) return;
unsigned int mask = CWWidth | CWHeight | CWBorderWidth;
XWindowChanges changes;
changes.border_width = 0;
changes.width = a_width;
changes.height = a_height;
::XConfigureWindow(m_display,a_window,mask,&changes);
}
bool window_size(Window a_window,int& a_width,int& a_height) const {
if(!m_display) {a_width = 0;a_height = 0;return false;}
XWindowAttributes watbs;
if(!XGetWindowAttributes(m_display,a_window,&watbs)) {a_width = 0;a_height = 0;return false;}
a_width = watbs.width;
a_height = watbs.height;
return true;
}
void delete_window(Window a_window) const {
if(!m_display) return;
::XDestroyWindow(m_display,a_window);
}
void set_override_redirect(Window a_window) const {
//must be executed before window is mapped.
if(!m_display) return;
XSetWindowAttributes swa;
swa.override_redirect = True;
::XChangeWindowAttributes(m_display,a_window,CWOverrideRedirect,&swa);
}
void set_wm_no_decorations(Window a_window) const {
//must be executed before window is mapped.
if(!m_display) return;
// struct, mwm_hints_decorations taken from OpenMotif MwmUtils.h.
struct{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long inputMode;
unsigned long status;
} prop;
//unsigned long mwm_hints_functions = 1L << 0;
unsigned long mwm_hints_decorations = 1L << 1;
Atom atom = ::XInternAtom(m_display,"_MOTIF_WM_HINTS",False);
if(atom==None) {
m_out << "toolx::X11::base_session::set_wm_no_decorations : can't create/get _MOTIF_WM_HINTS Atom." << std::endl;
return;
}
prop.flags = mwm_hints_decorations;
prop.functions = 0;
prop.decorations = 0;
::XChangeProperty(m_display,a_window,atom,atom,32,PropModeReplace,(unsigned char*)&prop,5);
}
bool post(Window a_win,
long a_0 = 0,long a_1 = 0,
long a_2 = 0,long a_3 = 0,
long a_4 = 0) const {
if(!m_display) return false;
XEvent event;
event.type = ClientMessage;
event.xclient.display = m_display;
event.xclient.window = a_win;
event.xclient.message_type = XA_INTEGER;
event.xclient.format = 8; /* put 8 because bug with 32 on VMCMS */
event.xclient.data.l[0] = a_0;
event.xclient.data.l[1] = a_1;
event.xclient.data.l[2] = a_2;
event.xclient.data.l[3] = a_3;
event.xclient.data.l[4] = a_4;
//lock();
Status stat = ::XSendEvent(m_display,a_win,False,0L,&event);
::XFlush(m_display);
//unlock();
return (stat==0?false:true);
}
bool post_EXIT_STEER(Window a_win) {
return post(a_win,SESSION_EXIT_STEER_atom());
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
void add_dispatcher(dispatcher* a_dispatcher) {
m_dispatchers.push_back(a_dispatcher); //take ownership.
}
void invalidate_dispatchers_with_window(Window a_win){
tools_vforit(dispatcher*,m_dispatchers,it) {
if((*it)->window()==a_win) (*it)->invalidate();
}
}
void remove_dispatchers_with_window(Window a_win){
tools_vforit_npp(dispatcher*,m_dispatchers,it) {
if((*it)->window()==a_win) {
dispatcher* obj = *it;
it = m_dispatchers.erase(it);
delete obj;
} else {
it++;
}
}
}
bool dispatch(XEvent& a_event) {
{tools_vforit_npp(dispatcher*,m_dispatchers,it) {
if(!(*it)->is_valid()) {
dispatcher* obj = *it;
it = m_dispatchers.erase(it);
delete obj;
} else {
it++;
}
}}
tools_vforit(dispatcher*,m_dispatchers,it) {
if((*it)->is_valid()) {
if((*it)->dispatch(a_event)) return true;
}
}
return false;
}
protected:
static Bool wait_map_notify(Display*,XEvent* a_event,char* a_arg){
return (a_event->type == MapNotify) && (a_event->xmap.window == (Window)a_arg);
}
static Bool wait_unmap_notify(Display*,XEvent* a_event,char* a_arg){
return (a_event->type == UnmapNotify) && (a_event->xmap.window == (Window)a_arg);
}
void clear_dispatchers() {
tools_vforit_npp(dispatcher*,m_dispatchers,it) {
dispatcher* obj = *it;
it = m_dispatchers.erase(it);
delete obj;
}
m_dispatchers.clear();
}
protected:
std::ostream& m_out;
unsigned int m_monitor;
Display* m_display;
Atom m_WM_DELETE_WINDOW_atom;
Atom m_SESSION_EXIT_STEER_atom;
std::vector<dispatcher*> m_dispatchers;
};
}}
#endif
+56
View File
@@ -0,0 +1,56 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_X11_dispatcher
#define toolx_X11_dispatcher
#include <X11/Xlib.h>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
namespace toolx {
namespace X11 {
class dispatcher {
protected:
#ifdef TOOLS_MEM
static const std::string& s_class() {
static const std::string s_v("toolx::X11::dispatcher");
return s_v;
}
#endif
public:
virtual bool dispatch(XEvent&) = 0;
virtual Window window() const = 0;
virtual dispatcher* copy() const = 0;
public:
dispatcher():m_is_valid(true){
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
virtual ~dispatcher(){
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
public:
dispatcher(const dispatcher& a_from):m_is_valid(a_from.m_is_valid){
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
dispatcher& operator=(const dispatcher& a_from) { m_is_valid = a_from.m_is_valid;return *this;}
public:
bool is_valid() const {return m_is_valid;}
void invalidate() {m_is_valid = false;}
protected:
bool m_is_valid;
};
}}
#endif
+207
View File
@@ -0,0 +1,207 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_X11_session
#define toolx_X11_session
#include "base_session"
#include <GL/glx.h>
namespace toolx {
namespace X11 {
class session : public base_session {
typedef base_session parent;
public:
//virtual bool make_current(Window a_window) const {
// if(!m_display) return false;
// if(::glXMakeCurrent(m_display,a_window,m_ctx)==False) {
// m_out << "toolx::X11::session::make_current : glXMakeCurrent failed." << std::endl;
// return false;
// }
// return true;
//}
//virtual bool swap_buffers(Window a_window) const {
// if(!m_display) return false;
// ::glXSwapBuffers(m_display,a_window);
// return true;
//}
public:
session(std::ostream& a_out,unsigned int a_monitor = 0)
:parent(a_out,a_monitor)
,m_vinfo(0)
,m_ctx(0)
,m_colormap(0)
{
if(!m_display) return;
{int glxMajor, glxMinor;
::glXQueryVersion(m_display,&glxMajor,&glxMinor);
if(glxMajor<=0) {
m_out << "toolx::X11::session::session : bad GLX-Version " << glxMajor << "." << glxMinor << std::endl;
::XCloseDisplay(m_display);
m_display = 0;
m_vinfo = 0;
m_ctx = 0;
return;
}}
static const int atbs_alpha[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None};
//NOTE : macOS : glXChooseVisual leaks 640 bytes.
m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs_alpha);
if(!m_vinfo) {
//m_out << "toolx::X11::session::initialize :"
// << " can't get a visual with alpha on screen " << m_monitor << ". Try without alpha..."
// << std::endl;
//m_out << "toolx::X11::session::initialize :"
// << " DefaultScreen(m_display): " << DefaultScreen(m_display) << "."
// << std::endl;
static const int atbs[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None};
m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs);
if(!m_vinfo) {
m_out << "toolx::X11::session::session :"
<< " can't choose a visual on screen " << m_monitor << "."
<< std::endl;
::XCloseDisplay(m_display);
m_display = 0;
m_vinfo = 0;
m_ctx = 0;
return;
}
}
m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_TRUE);
if(!m_ctx) {
m_out << "toolx::X11::session::session :"
<< " can't create a glX context with direct rendering."
<< std::endl;
m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_FALSE);
if(!m_ctx) {
m_out << "toolx::X11::session::session :"
<< " can't create a glX context."
<< std::endl;
::XCloseDisplay(m_display);
m_display = 0;
m_vinfo = 0;
m_ctx = 0;
return;
}
//} else {
//m_out << "toolx::X11::session::session :"
// << " glX context with direct rendering created."
// << std::endl;
}
// It is better to create a colormap adapted to the visual.
m_colormap = ::XCreateColormap(m_display,::XRootWindow(m_display,m_monitor),m_vinfo->visual,AllocNone);
//m_colormap = ::XDefaultColormap(m_display,m_monitor);
if(m_colormap==0L) {
m_out << "toolx::X11::session::session : XCreateColormap failed." << std::endl;
::XCloseDisplay(m_display);
m_display = 0;
m_vinfo = 0;
m_ctx = 0;
return;
}
}
virtual ~session() {
if(m_display) {
if(m_ctx) {
::glXDestroyContext(m_display,m_ctx);
m_ctx = 0;
}
if(m_colormap) {
::XFreeColormap(m_display,m_colormap);
m_colormap = 0;
}
::XCloseDisplay(m_display);
m_display = 0;
}
if(m_vinfo) {
::XFree(m_vinfo);
m_vinfo = 0;
}
//std::cout << "debug : ~session" << std::endl;
}
protected:
session(const session& a_from)
:parent(a_from)
,m_vinfo(0)
,m_ctx(0)
,m_colormap(0)
{}
session& operator=(const session& a_from){
if(&a_from==this) return *this;
parent::operator=(a_from);
return *this;
}
public:
GLXContext context() const {return m_ctx;}
Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) {
if(!m_display) return 0L;
XSetWindowAttributes swa;
swa.event_mask = StructureNotifyMask | ExposureMask
| ButtonPressMask | ButtonReleaseMask | ButtonMotionMask
| PointerMotionMask
| KeyPressMask;
swa.colormap = m_colormap;
swa.border_pixel = 0L;
Window window = ::XCreateWindow(m_display,
::XRootWindow(m_display,m_monitor),
a_x,a_y,a_width,a_height,
0,
m_vinfo->depth,
InputOutput,
m_vinfo->visual,
CWBorderPixel|CWColormap|CWEventMask,&swa);
if(window==0L) {
m_out << "toolx::X11::session::create_window :"
<< " can't create a X11 window."
<< std::endl;
return 0L;
}
XTextProperty tp;
::XStringListToTextProperty((char**)&a_title,1,&tp);
XSizeHints sh;
sh.flags = USPosition | USSize;
::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0);
::XFree(tp.value);
::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1);
return window;
}
protected:
XVisualInfo* m_vinfo;
GLXContext m_ctx;
Colormap m_colormap;
};
}}
#endif
+113
View File
@@ -0,0 +1,113 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_X11_sg_viewer
#define toolx_X11_sg_viewer
// not pure X11 version. The class inherits tools::sg::viewer that uses GL.
#include "session"
#include "../sg/GL_viewer"
#include "simple_dispatcher"
namespace tools{namespace sg{class device_interactor;}}
namespace toolx {
namespace X11 {
class sg_viewer : public sg::GL_viewer {
typedef sg::GL_viewer parent;
private:
class dispatcher : public simple_dispatcher {
typedef simple_dispatcher parent;
public:
virtual void win_render() {m_sg_viewer.win_render();}
virtual void set_size(unsigned int a_width,unsigned int a_height) {m_sg_viewer.set_size(a_width,a_height);}
virtual dispatcher* copy() const {return new dispatcher(*this);}
public:
dispatcher(sg_viewer& a_sg_viewer)
:parent(a_sg_viewer.m_session,a_sg_viewer.m_win)
,m_sg_viewer(a_sg_viewer){}
virtual ~dispatcher(){}
protected:
dispatcher(const dispatcher& a_from)
:parent(a_from)
,m_sg_viewer(a_from.m_sg_viewer)
{}
dispatcher& operator=(const dispatcher& a_from) {
parent::operator=(a_from);
return *this;
}
protected:
sg_viewer& m_sg_viewer;
};
public:
sg_viewer(session& a_session,
int a_x = 0,int a_y = 0,
unsigned int a_width = 500,unsigned int a_height = 500,
const std::string& a_win_title = "")
:parent(a_session.out(),a_width,a_height)
,m_session(a_session)
,m_win(0)
{
if(!m_session.display()) return; //throw
m_win = m_session.create_window(a_win_title.c_str(),a_x,a_y,a_width,a_height);
if(!m_win) return; //throw
m_session.add_dispatcher(new dispatcher(*this));
}
virtual ~sg_viewer() {
if(m_win) {
m_session.remove_dispatchers_with_window(m_win);
m_session.delete_window(m_win);
m_session.sync();
}
}
public:
sg_viewer(const sg_viewer& a_from)
:parent(a_from)
,m_session(a_from.m_session)
,m_win(a_from.m_win)
{}
sg_viewer& operator=(const sg_viewer& a_from){
parent::operator=(a_from);
m_win = a_from.m_win;
return *this;
}
public:
bool has_window() const {return m_win?true:false;} //for SWIG
Window window() const {return m_win;}
bool show() {
if(!m_win) return false;
m_session.show_window(m_win);
return true;
}
void win_render() {
if(!m_win) return;
if(::glXMakeCurrent(m_session.display(),m_win,m_session.context())==False){
m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent failed." << std::endl;
return;
}
render(); //viewer::render()
::glXSwapBuffers(m_session.display(),m_win);
if(::glXMakeCurrent(m_session.display(),None,NULL)==False){
m_session.out() << "toolx::X11::sg_viewer::win_render : glXMakeCurrent(None,NULL) failed." << std::endl;
}
}
public:
void set_device_interactor(tools::sg::device_interactor*) {}
protected:
session& m_session;
Window m_win;
};
}}
#endif
@@ -0,0 +1,63 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_X11_simple_dispatcher
#define toolx_X11_simple_dispatcher
#include "base_session"
#include <tools/saui>
namespace toolx {
namespace X11 {
class simple_dispatcher : public dispatcher {
typedef dispatcher parent;
public:
virtual void win_render() = 0;
virtual void set_size(unsigned int a_width,unsigned int a_height) = 0;
public:
virtual bool dispatch(XEvent& a_event) {
if(!m_win) return false;
if(a_event.xany.window!=m_win) return false;
if( (a_event.type==Expose) || (a_event.type==ConfigureNotify) ){
int width,height;
m_session.window_size(m_win,width,height);
set_size(width,height); //viewer::set_size()
win_render();
return true;
} else if(a_event.type==ClientMessage) {
if(a_event.xclient.data.l[0]==(long)m_session.WM_DELETE_WINDOW_atom()) {
m_session.post(m_win,m_session.SESSION_EXIT_STEER_atom());
return true;
}
}
return false;
}
virtual Window window() const {return m_win;}
public:
simple_dispatcher(base_session& a_session,Window a_win)
:parent()
,m_session(a_session)
,m_win(a_win)
{}
virtual ~simple_dispatcher(){}
public:
simple_dispatcher(const simple_dispatcher& a_from)
:parent(a_from)
,m_session(a_from.m_session)
,m_win(a_from.m_win)
{}
simple_dispatcher& operator=(const simple_dispatcher& a_from) {
parent::operator=(a_from);
m_win = a_from.m_win;
return *this;
}
protected:
base_session& m_session;
Window m_win;
};
}}
#endif
+481
View File
@@ -0,0 +1,481 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Xt_OpenGLArea
#define toolx_Xt_OpenGLArea
#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>
#include <X11/CompositeP.h>
#include <X11/StringDefs.h>
#include <GL/glx.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
namespace toolx {
namespace Xt {
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
typedef struct _OpenGLAreaClassRec* OpenGLAreaWidgetClass;
typedef struct _OpenGLAreaRec* OpenGLAreaWidget;
typedef struct {
int reason;
XEvent* event;
} XoAnyCallbackStruct;
#define XoNdoubleBufferOn "doubleBufferOn"
#define XoNpaintCallback "paintCallback"
#define XoNeventCallback "eventCallback"
#define XoCR_PAINT 1
#define XoCR_EVENT 2
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
typedef struct {
void* extension;
} OpenGLAreaClassPart;
typedef struct _OpenGLAreaClassRec {
CoreClassPart core_class;
CompositeClassPart composite_class;
OpenGLAreaClassPart openGLArea_class;
} OpenGLAreaClassRec;
typedef struct {
Boolean doubleBufferOn;
XtCallbackList paintCallback;
XtCallbackList eventCallback;
Visual* visual;
Boolean installColormap;
GLXContext glContext;
} OpenGLAreaPart;
typedef struct _OpenGLAreaRec {
CorePart core;
CompositePart composite;
OpenGLAreaPart openGLArea;
} OpenGLAreaRec;
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
class OpenGLArea {
public:
static void paint(Widget a_this) {
if(!XtIsRealized(a_this)) return;
if(make_current(a_this)==1) {
XoAnyCallbackStruct value;
value.reason = XoCR_PAINT;
value.event = 0;
::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
}
}
protected:
static void initialize_class(void) {}
static void initialize_widget(Widget a_request,Widget a_this,ArgList,Cardinal*) {
if(a_request->core.width<=0) a_this->core.width = 100;
if(a_request->core.height<=0) a_this->core.height = 100;
#ifdef OPENGLAREA_DEBUG
::printf ("debug : OpenGLArea : InitializeWidget : %s\n",::XtName(a_this));
#endif
OpenGLAreaPart& athis = _athis(a_this);
athis.visual = CopyFromParent;
athis.installColormap = False;
athis.glContext = NULL;
Display* display;
Screen* screen;
int iscreen;
XVisualInfo* vinfo;
display = XtDisplay(a_this);
screen = XtScreen(a_this);
iscreen = XScreenNumberOfScreen(screen);
{int error,event;
if(::glXQueryExtension(display,&error,&event)==0) {
CWarn ("X server does not have OpenGL extensions.\n");
}}
if(athis.doubleBufferOn==True) {
int atbs_1[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None
};
vinfo = ::glXChooseVisual (display,iscreen,atbs_1);
if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
int atbs_2[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None
};
vinfo = ::glXChooseVisual (display,iscreen,atbs_2);
}
} else {
int atbs_1[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None
};
vinfo = ::glXChooseVisual (display,iscreen,atbs_1);
if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
int atbs_2[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
None
};
vinfo = ::glXChooseVisual (display,iscreen,atbs_2);
}
}
if(vinfo==NULL) {
CWarn ("Can't choose a visual.\n");
} else {
a_this->core.depth = vinfo->depth;
athis.visual = vinfo->visual;
if( (vinfo->depth ==DefaultDepth (display,iscreen)) &&
(vinfo->visual==DefaultVisual(display,iscreen)) ) {
a_this->core.colormap = XDefaultColormap (display,iscreen);
athis.installColormap = False;
} else {
a_this->core.colormap =
XCreateColormap (display,XRootWindow(display,iscreen),vinfo->visual, AllocNone);
athis.installColormap = True;
}
if(a_this->core.colormap==0L) {
CWarn ("Can't get/create a X colormap.\n");
}
athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_TRUE);
if(athis.glContext==NULL) {
athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_FALSE);
if(athis.glContext==NULL) {
CWarn ("Can't create a GLX context.\n");
}
}
::XFree(vinfo);
}
::XtAddEventHandler
(a_this,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask,0,event_handler,NULL);
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : InitializeWidget : end\n");
#endif
}
static void realize_widget(Widget a_this,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : realize_widget : %s\n",XtName(a_this));
#endif
// Have to create window ourselves due to OpenGL that compells it's visual.
// In principle colormap is correctly set in a_watbsy.
OpenGLAreaPart& athis = _athis(a_this);
::XtCreateWindow(a_this,(unsigned int)InputOutput,athis.visual,*a_mask,a_watbs);
// Call the Realize procedure (XtInheritRealize) :
if(widget_class()->core_class.superclass->core_class.realize!=NULL)
(widget_class()->core_class.superclass->core_class.realize)(a_this, a_mask, a_watbs);
// If window is delete, all seems ok :
if(athis.installColormap==True) install_colormap(a_this);
//make_current(a_this);
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : realize_widget : end\n");
#endif
}
static void destroy_widget(Widget a_this) {
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : destroy_widget : begin\n");
#endif
OpenGLAreaPart& athis = _athis(a_this);
if(athis.installColormap==True) {
uninstall_colormap (a_this);
athis.installColormap = False;
::XFreeColormap(XtDisplay(a_this),a_this->core.colormap);
}
if(athis.glContext!=NULL) {
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
::glXDestroyContext(XtDisplay(a_this),athis.glContext);
athis.glContext = NULL;
}
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : destroy_widget : end\n");
#endif
}
static Boolean set_values(Widget a_current,Widget,Widget a_this,ArgList,Cardinal*) {
OpenGLAreaPart& athis = _athis(a_this);
if(athis.doubleBufferOn != ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn) {
// Can't change buffering here if X window is created.
// With OpenGL, buffering fix parameter of the X window.
// Buffering must be choosen before the execution of the
// Realize method that create the window.
if(XtIsRealized(a_this) && (athis.installColormap==True)) {
CWarn("Can't change buffering after \"realization\" of the widget.\n");
athis.doubleBufferOn = ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn;
}
}
return False;
}
static void change_widget_size(Widget a_this) {
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : change_widget_size : %s\n",XtName(a_this));
#endif
// Call the Resize procedure (XtInheritResize) :
if(widget_class()->core_class.superclass->core_class.resize!=NULL)
(widget_class()->core_class.superclass->core_class.resize)(a_this);
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : change_widget_size : end\n");
#endif
}
static void draw_widget(Widget a_this,XEvent* a_event,Region a_region) {
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : %s\n",XtName(a_this));
#endif
if(widget_class()->core_class.superclass->core_class.expose!=NULL)
(widget_class()->core_class.superclass->core_class.expose)(a_this,a_event,a_region);
if(make_current(a_this)==1) {
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : %s : make_current ok : call paintCallback...\n",XtName(a_this));
#endif
XoAnyCallbackStruct value;
value.reason = XoCR_PAINT;
value.event = a_event;
::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
::glXMakeCurrent(XtDisplay(a_this),None,NULL);
}
#ifdef OPENGLAREA_DEBUG
printf("debug : OpenGLArea : draw_widget : end\n");
#endif
}
protected:
static OpenGLAreaPart& _athis(Widget a_this) {return *(&(((OpenGLAreaWidget)a_this)->openGLArea));}
static void CWarn(const char* a_msg) {
::printf("%s",a_msg);
}
static void CWarnF(const char* a_format,...) {
va_list args;
va_start(args,a_format);
::vprintf(a_format,args);
va_end(args);
}
static int make_current(Widget a_this) {
if(!XtIsRealized(a_this)) return 0;
OpenGLAreaPart& athis = _athis(a_this);
if(athis.glContext==NULL) return 0;
return (int)::glXMakeCurrent(XtDisplay(a_this),XtWindow(a_this),athis.glContext);
}
static void event_handler(Widget a_this,XtPointer,XEvent* a_event ,Boolean*) {
XoAnyCallbackStruct value;
value.reason = XoCR_EVENT;
value.event = a_event;
::XtCallCallbacks(a_this,XoNeventCallback,(XtPointer)&value);
}
static void install_colormap(Widget a_this) {
// From Mesa/widgets/GLwDrawingArea.c/post_colormap routine.
// Could use also XtSetWMColormapWindows.
if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
Widget shell = get_shell(a_this);
if(shell==NULL) return;
Display* display = XtDisplay (a_this);
Window wthis = XtWindow (a_this);
Window wshell = XtWindow (shell);
Window* ws = NULL;
int wn = 0;
::XGetWMColormapWindows (display,wshell, &ws, &wn);
// Check if colormap of this is a colormap of a Window in list :
XWindowAttributes watbs;
XGetWindowAttributes (display,wthis,&watbs);
Colormap cmapthis = watbs.colormap;
int found = -1;
for(int count=0;count<wn;count++) {
Colormap cmap;
XGetWindowAttributes (display,ws[count],&watbs);
cmap = watbs.colormap;
if(cmap==cmapthis) {
::XFree (ws);
return;
}
if(ws[count]==wshell) {
found = count;
}
}
// Have to add window of this in list :
if(wn==0) {
if(ws!=NULL) ::XFree(ws);
ws = (Window*)::malloc( 2 * sizeof(Window));
} else {
ws = (Window*)::realloc(ws,(wn + 2) * sizeof(Window));
}
if(ws==NULL) return;
if(found==-1) {
// Window of shell not in list :
ws[wn] = wthis; wn++;
ws[wn] = wshell;wn++;
} else {
ws[found] = wthis;
ws[wn] = wshell; wn++; // Shell must be last.
}
if (::XSetWMColormapWindows(display,wshell, ws, wn)==0) {
CWarnF ("install_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
}
::free(ws);
}
static void uninstall_colormap(Widget a_this) {
if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
Widget shell = get_shell (a_this);
if(shell==NULL) return;
Display* display = XtDisplay (a_this);
Window wthis = XtWindow (a_this);
Window wshell = XtWindow (shell);
Window* ws = NULL;
int wn = 0;
::XGetWMColormapWindows (display,wshell, &ws, &wn);
if( (wn==0) || (ws==NULL) ) return;
Window* nws = (Window*)::malloc( wn * sizeof(Window));
if(nws==NULL) {
::XFree (ws);
return;
}
int nwn = 0;
for(int count=0;count<wn;count++) {
if(ws[count]!=wthis) {
nws[nwn] = ws[count];
nwn++;
}
}
if(wn!=nwn) {
if (::XSetWMColormapWindows(display,wshell, nws, nwn)==0) {
CWarnF("uninstall_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
}
}
::XFree (ws);
::free (nws);
}
static Widget get_shell(Widget a_this) {
Widget widget = a_this;
while(1) {
if(widget==NULL) return NULL;
if(XtIsShell(widget)) return widget;
widget = XtParent(widget);
}
}
public:
static WidgetClass widget_class() {
static XtResource s_resources [] = {
{(String)XoNdoubleBufferOn,(String)"DoubleBufferOn",XtRBoolean,sizeof(Boolean),
XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
{(String)XoNpaintCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
{(String)XoNeventCallback,XtCCallback,XtRCallback,sizeof(XtCallbackList),
XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
};
static OpenGLAreaClassRec s_openGLAreaClassRec = {
// Core Class Part :
{
(WidgetClass) &compositeClassRec, // pointer to superclass ClassRec
(String)"OpenGLArea", // widget resource class name
sizeof(OpenGLAreaRec), // size in bytes of widget record
initialize_class, // class_initialize
NULL, // dynamic initialization
FALSE, // has class been initialized?
initialize_widget, // initialize
NULL, // notify that initialize called
realize_widget, // XCreateWindow for widget
NULL, // widget semantics name to proc mapWidget
0, // number of entries in actions
s_resources, // resources for subclass fields
XtNumber(s_resources), // number of entries in resources
NULLQUARK, // resource class quarkified
TRUE, // compress MotionNotify for widget
TRUE, // compress Expose events for widget
TRUE, // compress enter and leave events
TRUE, // select for VisibilityNotify
destroy_widget, // free data for subclass pointers
change_widget_size, // geom manager changed widget size
draw_widget, // rediplay window
set_values, // set subclass resource values
NULL, // notify that SetValues called
XtInheritSetValuesAlmost, // SetValues got "Almost" geo reply
NULL, // notify that get_values called
XtInheritAcceptFocus, // assign input focus to widget
XtVersion, // version of intrinsics used
NULL, // list of callback offsets
XtInheritTranslations, // translations
XtInheritQueryGeometry, // return preferred geometry
XtInheritDisplayAccelerator, // display your accelerator
NULL // pointer to extension record
},
// Composite Class Part :
{
XtInheritGeometryManager, // geometry manager for children
XtInheritChangeManaged, // change managed state of child
XtInheritInsertChild, // physically add child to parent
XtInheritDeleteChild, // physically remove child
NULL // pointer to extension record
},
// OpenGLArea :
{
NULL
}
};
return (WidgetClass)&s_openGLAreaClassRec;
}
};
}}
#endif
+77
View File
@@ -0,0 +1,77 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Xt_session
#define toolx_Xt_session
#include <ostream>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
namespace toolx {
namespace Xt {
class session {
public:
session(std::ostream& a_out,int& a_argc,char** a_argv)
:m_out(a_out),m_app_context(0),m_app_widget(0)
{
//LookDSM_Problem();
Arg args[1];
XtSetArg(args[0],XtNgeometry,XtNewString("100x100"));
m_app_widget = ::XtAppInitialize(&m_app_context,"toolx::Xt::session",NULL,(Cardinal)0,&a_argc,a_argv,NULL,args,1);
if(!m_app_context || !m_app_widget) {
m_app_context = 0;
m_app_widget = 0;
}
}
virtual ~session() {
if(m_app_widget) {::XtDestroyWidget(m_app_widget);m_app_widget = 0;}
if(m_app_context) {::XtDestroyApplicationContext(m_app_context);m_app_context = 0;}
}
protected:
session(const session& a_from)
:m_out(a_from.m_out),m_app_context(0),m_app_widget(0)
{}
session& operator=(const session&){return *this;}
public:
std::ostream& out() const {return m_out;}
bool is_valid() {return m_app_context && m_app_widget?true:false;}
bool steer() {
if(!m_app_context) return false;
while(true) {
XEvent event;
::XtAppNextEvent(m_app_context,&event);
::XtDispatchEvent(&event);
//if(m_exit) break;
}
return true;
}
bool sync() {
//if(!m_app_widget) return false;
//Display* display = XtDisplay(m_app_widget);
//::XSync(display,False);
if(!m_app_context) return false;
while(true) {
XtInputMask input = ::XtAppPending(m_app_context);
if(input==0) break;
XEvent event;
::XtAppNextEvent(m_app_context,&event);
::XtDispatchEvent(&event);
}
return true;
}
public:
Widget get_app_widget() {return m_app_widget;}
protected:
std::ostream& m_out;
bool m_app_owner;
XtAppContext m_app_context;
Widget m_app_widget;
};
}}
#endif
+183
View File
@@ -0,0 +1,183 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_Xt_sg_viewer
#define toolx_Xt_sg_viewer
#include "session"
#include "../sg/GL_viewer"
#include "OpenGLArea"
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <tools/num2s>
#include <tools/sg/device_interactor>
#include <tools/sg/keys>
namespace toolx {
namespace Xt {
class sg_viewer : public sg::GL_viewer {
typedef sg::GL_viewer parent;
public:
sg_viewer(session& a_session,
int a_x = 0,int a_y = 0,
unsigned int a_width = 500,unsigned int a_height = 500,
const std::string& a_win_title = "")
:parent(a_session.out(),a_width,a_height)
,m_session(a_session)
,m_shell(0)
,m_glarea(0)
,m_interactor(0)
{
Widget app_widget = a_session.get_app_widget();
if(!app_widget) return;
std::string sgeom;
tools::numas(a_width,sgeom);
sgeom += "x";
tools::numas(a_height,sgeom);
sgeom += "+";
tools::numas(a_x,sgeom);
sgeom += "+";
tools::numas(a_y,sgeom);
Arg args[2];
XtSetArg(args[0],XtNgeometry,XtNewString(sgeom.c_str()));
XtSetArg(args[1],XtNborderWidth,0);
m_shell = ::XtAppCreateShell((char*)a_win_title.c_str(),
(char*)"sg_viewer_shell",
topLevelShellWidgetClass,XtDisplay(app_widget),args,2);
::XtSetMappedWhenManaged(m_shell,True);
m_glarea = ::XtCreateManagedWidget("glarea",OpenGLArea::widget_class(),m_shell,args,0);
::XtAddCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this);
::XtAddCallback(m_glarea,XoNeventCallback,event_cbk,(XtPointer)this);
::XtAddCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this);
::XtRealizeWidget(m_shell);
//Atom WM_DELETE_WINDOW_atom = ::XInternAtom(XtDisplay(m_shell),"WM_DELETE_WINDOW",False);
//::XSetWMProtocols(XtDisplay(m_shell),XtWindow(m_shell),&WM_DELETE_WINDOW_atom,1);
}
virtual ~sg_viewer() {
if(m_shell) {
::XtRemoveCallback(m_glarea,XoNpaintCallback,paint_cbk,(XtPointer)this);
::XtRemoveCallback(m_shell,XtNdestroyCallback,destroy_shell_callback,(XtPointer)this);
::XtDestroyWidget(m_shell);
}
m_shell = 0;
m_glarea = 0;
}
protected:
sg_viewer(const sg_viewer& a_from)
:parent(a_from)
,m_session(a_from.m_session)
,m_shell(0)
,m_glarea(0)
,m_interactor(0)
{}
sg_viewer& operator=(const sg_viewer& a_from){
parent::operator=(a_from);
return *this;
}
public:
bool has_window() const {return m_glarea?true:false;}
bool show() {
if(!m_shell) return false;
::XtRealizeWidget(m_shell);
::XtMapWidget(m_shell);
// Raise window :
if(XtIsWidget(m_shell) && XtIsRealized(m_shell) ) {
Display* display = XtDisplay(m_shell);
Atom atom = ::XInternAtom(display,"WM_DELETE_WINDOW",False);
::XSetWMProtocols(display,XtWindow(m_shell),&atom,1);
::XRaiseWindow(display,XtWindow(m_shell));
}
return true;
}
void win_render() {
if(m_glarea) OpenGLArea::paint(m_glarea);
}
public:
void set_device_interactor(tools::sg::device_interactor* a_interactor) {m_interactor = a_interactor;} //we do not have ownership.
protected:
static void paint_cbk(Widget a_widget,XtPointer a_tag,XtPointer){
unsigned int width = a_widget->core.width;
unsigned int height = a_widget->core.height;
//::printf("debug : toolx::Xt::sg_viewer::paint_cbk : %d %d\n",width,height);
sg_viewer* _this = (sg_viewer*)a_tag;
_this->set_size(width,height);
_this->render();
}
static void event_cbk(Widget,XtPointer a_tag,XtPointer a_data){
sg_viewer* _this = (sg_viewer*)a_tag;
if(!_this->m_interactor) return;
XoAnyCallbackStruct* data = (XoAnyCallbackStruct*)a_data;
XEvent* xevent = data->event;
switch( xevent->type ) {
case KeyPress:{
KeySym key_sym;
::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL);
tools::sg::key_down_event event(_this->convert(key_sym));
_this->m_interactor->key_press(event);
}return;
case KeyRelease:{
KeySym key_sym;
::XLookupString(&(xevent->xkey),NULL,0,&key_sym,NULL);
tools::sg::key_up_event event(_this->convert(key_sym));
_this->m_interactor->key_release(event);
}return;
case ButtonPress:{
if(xevent->xbutton.button==Button4) { //4=wheel down, or move down double touch on trackpad = zoom in.
tools::sg::wheel_rotate_event event(8); //8=cooking.
_this->m_interactor->wheel_rotate(event);
} else if(xevent->xbutton.button==Button5) { //5=wheel up, or move up double touch on trackpad = zoom out.
tools::sg::wheel_rotate_event event(-8); //8=cooking.
_this->m_interactor->wheel_rotate(event);
} else {
tools::sg::mouse_down_event event(xevent->xbutton.x,xevent->xbutton.y);
_this->m_interactor->mouse_press(event);
}
}return;
case ButtonRelease:{
tools::sg::mouse_up_event event(xevent->xbutton.x,xevent->xbutton.y);
_this->m_interactor->mouse_release(event);
}return;
case MotionNotify:{
tools::sg::mouse_move_event event(xevent->xmotion.x,xevent->xmotion.y,0,0,false);
_this->m_interactor->mouse_move(event);
}return;
default:return;}
}
static void destroy_shell_callback(Widget,XtPointer a_tag,XtPointer) {
sg_viewer* _this = (sg_viewer*)a_tag;
_this->m_shell = 0;
_this->m_glarea = 0;
}
protected:
tools::key_code convert(KeySym a_key) {
if(a_key==XK_Shift_L) return tools::sg::key_shift();
if(a_key==XK_Shift_R) return tools::sg::key_shift();
return a_key;
}
protected:
session& m_session;
Widget m_shell;
Widget m_glarea;
tools::sg::device_interactor* m_interactor;
};
}}
#endif
+29
View File
@@ -0,0 +1,29 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_glbuf
#define toolx_glbuf
//define of TOOLX_HAS_GL_VBO decided in the build systems.
// To have prototypes of glGenBuffers,etc...
#ifdef TOOLX_HAS_GL_VBO
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif
#if TARGET_OS_IPHONE
#elif defined(ANDROID)
#elif _WIN32
#include <GL/glext.h>
#elif __APPLE__
#include <OpenGL/glext.h> //Cocoa
#else
#include <GL/glext.h>
#endif
#endif //TOOLX_HAS_GL_VBO
#endif
File diff suppressed because it is too large Load Diff
+72
View File
@@ -0,0 +1,72 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_atb
#define toolx_hdf5_atb
// The below is internal methods in the HDF5 lib.
#include "hdf5_h"
#include <cstring>
namespace toolx {
namespace hdf5 {
inline herr_t H5LT_get_attribute_mem(hid_t obj_id,const char *attr_name,hid_t mem_type_id,void *data ) {
hid_t attr_id;
if ( ( attr_id = ::H5Aopen_name( obj_id, attr_name ) ) < 0 ) return -1;
if ( ::H5Aread( attr_id, mem_type_id, data ) < 0 ) {
::H5Aclose( attr_id );
return -1;
}
if ( ::H5Aclose( attr_id ) < 0 ) return -1;
return 0;
}
inline herr_t find_attr( hid_t loc_id, const char *name, void *op_data) {
int ret = 0;
char *attr_name = (char*)op_data;
if( ::strcmp( name, attr_name ) == 0 ) ret = 1;
(void)loc_id;
return ret;
}
inline herr_t H5LT_find_attribute( hid_t loc_id, const char* attr_name ) {
unsigned int attr_num;
attr_num = 0;
return toolx_H5Aiterate( loc_id, &attr_num, find_attr, (void *)attr_name );
}
inline herr_t H5LT_get_attribute_disk( hid_t loc_id,const char *attr_name,void *attr_out ) {
hid_t attr_id;
if ( ( attr_id = ::H5Aopen_name( loc_id, attr_name ) ) < 0 ) return -1;
hid_t attr_type;
if ( (attr_type = ::H5Aget_type( attr_id )) < 0 ) {
::H5Tclose( attr_type );
::H5Aclose( attr_id );
return -1;
}
if ( ::H5Aread( attr_id, attr_type, attr_out ) < 0 ) {
::H5Tclose( attr_type );
::H5Aclose( attr_id );
return -1;
}
if ( ::H5Tclose( attr_type ) < 0 ) {
::H5Tclose( attr_type );
::H5Aclose( attr_id );
return -1;
}
if ( ::H5Aclose( attr_id ) < 0 ) return -1;
return 0;
}
}}
#endif
@@ -0,0 +1,49 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_group_exists
#define toolx_hdf5_group_exists
#include "hdf5_h"
#include <string>
namespace toolx {
namespace hdf5 {
class group_exists_struct {
public:
group_exists_struct(const std::string& a_what):m_what(a_what),m_found(false){}
virtual ~group_exists_struct() {}
protected:
group_exists_struct(const group_exists_struct& a_from):m_what(a_from.m_what),m_found(a_from.m_found){}
group_exists_struct& operator=(const group_exists_struct&){return *this;}
public:
std::string m_what;
bool m_found;
};
inline herr_t group_exists_visit(hid_t a_id,const char* a_name,void* a_tag){ //a_id = parent of a_name object.
group_exists_struct* visitor = (group_exists_struct*)a_tag;
H5G_stat_t statbuf;
::H5Gget_objinfo(a_id,a_name,0,&statbuf);
switch(statbuf.type) {
case H5G_GROUP:{
if(a_name==visitor->m_what) {visitor->m_found=true;return 0;} //found
//::H5Giterate(a_id,a_name,NULL,group_exists_visit,visitor);
}break;
default:
break;
}
return 0;
}
inline bool group_exists(hid_t a_file_id,const std::string& a_name) {
group_exists_struct visitor(a_name);
::H5Giterate(a_file_id,".",NULL,group_exists_visit,&visitor);
return visitor.m_found;
}
}}
#endif
+342
View File
@@ -0,0 +1,342 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_h2file
#define toolx_hdf5_h2file
#include "tools"
#include "T_tools"
#include <tools/histo/histo_data>
#include <tools/sout>
#include <ostream>
namespace toolx {
namespace hdf5 {
}}
#include <map>
namespace toolx {
namespace hdf5 {
inline bool write_std_map_ss(hid_t a_loc,const std::string& a_name,const std::map<std::string,std::string>& a_map,
unsigned int /*a_chunked*/ = 0,unsigned int /*a_compress*/ = 0) {
if(!write_scalar<tools::uint64>(a_loc,a_name+"_size",a_map.size())) return false;
unsigned int count = 0; //uint for num2s.
std::string scount;
tools_mforcit(std::string,std::string,a_map,it) {
tools::num2s(count,scount);
if(!write_string(a_loc,a_name+"_elem_"+scount+"_first",(*it).first)) return false;
if(!write_string(a_loc,a_name+"_elem_"+scount+"_secon",(*it).second)) return false;
count++;
}
return true;
}
inline bool read_std_map_ss(hid_t a_loc,const std::string& a_name,std::map<std::string,std::string>& a_map,
unsigned int /*a_chunked*/ = 0,unsigned int /*a_compress*/ = 0) {
a_map.clear();
tools::uint64 sz;
if(!read_scalar<tools::uint64>(a_loc,a_name+"_size",sz)) return false;
std::string scount,key,value;
for(tools::uint64 count=0;count<sz;count++) {
tools::num2s(count,scount);
if(!read_string(a_loc,a_name+"_elem_"+scount+"_first",key)) return false;
if(!read_string(a_loc,a_name+"_elem_"+scount+"_secon",value)) return false;
a_map[key] = value;
}
return true;
}
typedef tools::histo::histo_data<double,unsigned int,unsigned int,double> histo_data_t;
inline bool write_hdata(hid_t a_loc,const histo_data_t& a_hdata) {
if(!write_string(a_loc,"title",a_hdata.m_title)) return false;
if(!write_scalar<unsigned int>(a_loc,"dimension",a_hdata.m_dimension)) return false;
if(!write_scalar<unsigned int>(a_loc,"bin_number",a_hdata.m_bin_number)) return false;
if(!write_std_vec<unsigned int>(a_loc,"bin_entries",a_hdata.m_bin_entries)) return false;
if(!write_std_vec<double>(a_loc,"bin_Sw",a_hdata.m_bin_Sw)) return false;
if(!write_std_vec<double>(a_loc,"bin_Sw2",a_hdata.m_bin_Sw2)) return false;
if(!write_std_vec_vec<double>(a_loc,"bin_Sxw",a_hdata.m_bin_Sxw)) return false;
if(!write_std_vec_vec<double>(a_loc,"bin_Sx2w",a_hdata.m_bin_Sx2w)) return false;
// axes :
{std::string name,saxis;
for(unsigned int iaxis=0;iaxis<a_hdata.m_dimension;iaxis++) {
tools::num2s(iaxis,saxis);
name = "axis_"+saxis+"_";
const histo_data_t::axis_t& _axis = a_hdata.m_axes[iaxis];
if(!write_scalar<unsigned int>(a_loc,name+"offset",_axis.m_offset)) return false;
if(!write_scalar<unsigned int>(a_loc,name+"number_of_bins",_axis.m_number_of_bins)) return false;
if(!write_scalar<double>(a_loc,name+"minimum_value",_axis.m_minimum_value)) return false;
if(!write_scalar<double>(a_loc,name+"maximum_value",_axis.m_maximum_value)) return false;
if(!write_scalar<bool>(a_loc,name+"fixed",_axis.m_fixed)) return false;
if(!write_scalar<double>(a_loc,name+"bin_width",_axis.m_bin_width)) return false;
if(!write_std_vec<double>(a_loc,name+"edges",_axis.m_edges)) return false;
}}
// etc :
if(!write_std_vec<double>(a_loc,"in_range_plane_Sxyw",a_hdata.m_in_range_plane_Sxyw)) return false;
// m_annotations :
if(!write_std_map_ss(a_loc,"annotations",a_hdata.m_annotations)) return false;
return true;
}
template <class HISTO>
inline bool write_histo(std::ostream& a_out,hid_t a_loc,const std::string& a_name,const HISTO& a_histo) {
hid_t histo = toolx_H5Gcreate(a_loc,a_name.c_str(),0);
if(histo<0) {
a_out << "toolx::hdf5::write_histo : can't create group for histo " << tools::sout(a_name) << "." << std::endl;
::H5Gclose(histo);
return false;
}
if(!write_atb(histo,"type","object")) {
a_out << "toolx::hdf5::write_histo : write_atb() class failed." << std::endl;
::H5Gclose(histo);
return false;
}
if(!write_atb(histo,"class",a_histo.s_cls())) {
a_out << "toolx::hdf5::write_histo : write_atb() class failed." << std::endl;
::H5Gclose(histo);
return false;
}
int v = 1;
if(!write_scalar_atb<int>(histo,"version",v)) {
a_out << "toolx::hdf5::write_histo : write_scalar_atb() version failed." << std::endl;
::H5Gclose(histo);
return false;
}
if(!write_hdata(histo,a_histo.dac())) {::H5Gclose(histo);return false;}
::H5Gclose(histo);
a_histo.not_a_profile(); //trick to be sure to use this function on an histo and not a profile.
return true;
}
template <class PROFILE>
inline bool write_profile(std::ostream& a_out,hid_t a_loc,const std::string& a_name,const PROFILE& a_histo) {
hid_t histo = toolx_H5Gcreate(a_loc,a_name.c_str(),0);
if(histo<0) {
a_out << "toolx::hdf5::write_profile : can't create group for histo " << tools::sout(a_name) << "." << std::endl;
::H5Gclose(histo);
return false;
}
if(!write_atb(histo,"type","object")) {
a_out << "toolx::hdf5::write_profile : write_atb() class failed." << std::endl;
::H5Gclose(histo);
return false;
}
if(!write_atb(histo,"class",a_histo.s_cls())) {
a_out << "toolx::hdf5::write_profile : write_atb() class failed." << std::endl;
::H5Gclose(histo);
return false;
}
int v = 1;
if(!write_scalar_atb<int>(histo,"version",v)) {
a_out << "toolx::hdf5::write_profile : write_scalar_atb() version failed." << std::endl;
::H5Gclose(histo);
return false;
}
typename PROFILE::pd_t pdata = a_histo.get_histo_data();
if(!write_hdata(histo,pdata)) {::H5Gclose(histo);return false;}
if(!write_bool(histo,"is_profile",pdata.m_is_profile)) {::H5Gclose(histo);return false;}
if(!write_std_vec<double>(histo,"bin_Svw",pdata.m_bin_Svw)) {::H5Gclose(histo);return false;}
if(!write_std_vec<double>(histo,"bin_Sv2w",pdata.m_bin_Sv2w)) {::H5Gclose(histo);return false;}
if(!write_bool(histo,"cut_v",pdata.m_cut_v)) {::H5Gclose(histo);return false;}
if(!write_scalar<double>(histo,"min_v",pdata.m_min_v)) {::H5Gclose(histo);return false;}
if(!write_scalar<double>(histo,"max_v",pdata.m_max_v)) {::H5Gclose(histo);return false;}
::H5Gclose(histo);
return true;
}
inline bool read_hdata(hid_t a_loc,histo_data_t& a_hdata) {
if(!read_string(a_loc,"title",a_hdata.m_title)) return false;
if(!read_scalar<unsigned int>(a_loc,"dimension",a_hdata.m_dimension)) return false;
if(!read_scalar<unsigned int>(a_loc,"bin_number",a_hdata.m_bin_number)) return false;
if(!read_std_vec<unsigned int>(a_loc,"bin_entries",a_hdata.m_bin_entries)) return false;
if(!read_std_vec<double>(a_loc,"bin_Sw",a_hdata.m_bin_Sw)) return false;
if(!read_std_vec<double>(a_loc,"bin_Sw2",a_hdata.m_bin_Sw2)) return false;
if(!read_std_vec_vec<double>(a_loc,"bin_Sxw",a_hdata.m_bin_Sxw)) return false;
if(!read_std_vec_vec<double>(a_loc,"bin_Sx2w",a_hdata.m_bin_Sx2w)) return false;
// axes :
{a_hdata.m_axes.resize(a_hdata.m_dimension);
std::string name,saxis;
for(unsigned int iaxis=0;iaxis<a_hdata.m_dimension;iaxis++) {
tools::num2s(iaxis,saxis);
name = "axis_"+saxis+"_";
histo_data_t::axis_t& _axis = a_hdata.m_axes[iaxis];
if(!read_scalar<unsigned int>(a_loc,name+"offset",_axis.m_offset)) return false;
if(!read_scalar<unsigned int>(a_loc,name+"number_of_bins",_axis.m_number_of_bins)) return false;
if(!read_scalar<double>(a_loc,name+"minimum_value",_axis.m_minimum_value)) return false;
if(!read_scalar<double>(a_loc,name+"maximum_value",_axis.m_maximum_value)) return false;
if(!read_scalar<bool>(a_loc,name+"fixed",_axis.m_fixed)) return false;
if(!read_scalar<double>(a_loc,name+"bin_width",_axis.m_bin_width)) return false;
if(!read_std_vec<double>(a_loc,name+"edges",_axis.m_edges)) return false;
}}
// etc :
if(!read_std_vec<double>(a_loc,"in_range_plane_Sxyw",a_hdata.m_in_range_plane_Sxyw)) return false;
// m_annotations :
if(!read_std_map_ss(a_loc,"annotations",a_hdata.m_annotations)) return false;
return true;
}
template <class HISTO>
inline bool read_histo(std::ostream& a_out,hid_t a_loc,const std::string& a_name,HISTO*& a_histo,bool a_verb_class = true) {
a_histo = 0;
//if(::H5Gget_objinfo(a_loc,a_name.c_str(),0,NULL)<0) {return false;}
hid_t histo = toolx_H5Gopen(a_loc,a_name.c_str());
if(histo<0) {
a_out << "toolx::hdf5::read_histo : can't open group." << std::endl;
return false;
}
std::string sclass;
if(!read_atb(histo,"class",sclass)) {
a_out << "toolx::hdf5::read_histo : can't read_atb() class." << std::endl;
::H5Gclose(histo);
return false;
}
if(sclass!=HISTO::s_class()) {
if(a_verb_class) {
a_out << "toolx::hdf5::read_histo :"
<< " read class " << tools::sout(sclass) << " not " << tools::sout(HISTO::s_class()) << std::endl;
}
::H5Gclose(histo);
return false;
}
int v;
if(!read_atb(histo,"version",v)) {
a_out << "toolx::hdf5::read_histo : read_atb version failed." << std::endl;
::H5Gclose(histo);
return false;
}
histo_data_t hdata;
if(!read_hdata(histo,hdata)) {::H5Gclose(histo);return false;}
::H5Gclose(histo);
hdata.update_fast_getters();
a_histo = new HISTO;
a_histo->copy_from_data(hdata);
a_histo->not_a_profile(); //trick to be sure to use this function on an histo and not a profile.
return true;
}
template <class PROFILE>
inline bool read_profile(std::ostream& a_out,hid_t a_loc,const std::string& a_name,PROFILE*& a_histo,bool a_verb_class = true) {
a_histo = 0;
hid_t histo = toolx_H5Gopen(a_loc,a_name.c_str());
if(histo<0) {
a_out << "toolx::hdf5::read_profile : can't open group." << std::endl;
return false;
}
std::string sclass;
if(!read_atb(histo,"class",sclass)) {
a_out << "toolx::hdf5::read_profile : can't read_atb() class." << std::endl;
::H5Gclose(histo);
return false;
}
if(sclass!=PROFILE::s_class()) {
if(a_verb_class) {
a_out << "toolx::hdf5::read_profile :"
<< " read class " << tools::sout(sclass) << " not " << tools::sout(PROFILE::s_class()) << std::endl;
}
::H5Gclose(histo);
return false;
}
int v;
if(!read_atb(histo,"version",v)) {
a_out << "toolx::hdf5::read_profile : read_atb version failed." << std::endl;
::H5Gclose(histo);
return false;
}
typename PROFILE::pd_t pdata;
if(!read_hdata(histo,pdata)) {::H5Gclose(histo);return false;}
if(!read_bool(histo,"is_profile",pdata.m_is_profile)) {::H5Gclose(histo);return false;}
if(!read_std_vec<double>(histo,"bin_Svw",pdata.m_bin_Svw)) {::H5Gclose(histo);return false;}
if(!read_std_vec<double>(histo,"bin_Sv2w",pdata.m_bin_Sv2w)) {::H5Gclose(histo);return false;}
if(!read_bool(histo,"cut_v",pdata.m_cut_v)) {::H5Gclose(histo);return false;}
if(!read_scalar<double>(histo,"min_v",pdata.m_min_v)) {::H5Gclose(histo);return false;}
if(!read_scalar<double>(histo,"max_v",pdata.m_max_v)) {::H5Gclose(histo);return false;}
::H5Gclose(histo);
pdata.update_fast_getters();
a_histo = new PROFILE;
a_histo->copy_from_data(pdata);
return true;
}
inline bool read_class_version(std::ostream& a_out,hid_t a_loc,const std::string& a_name,
std::string& a_class,int& a_version,bool a_verbose = true) {
hid_t id = toolx_H5Gopen(a_loc,a_name.c_str());
if(id<0) {
if(a_verbose) a_out << "toolx::hdf5::read_class_version : can't open group." << std::endl;
a_class.clear();
a_version = 0;
return false;
}
if(!read_atb(id,"class",a_class)) {
if(a_verbose) a_out << "toolx::hdf5::read_class_version : can't read_atb() class." << std::endl;
::H5Gclose(id);
a_class.clear();
a_version = 0;
return false;
}
if(!read_atb(id,"version",a_version)) {
if(a_verbose) a_out << "toolx::hdf5::read_class_version : read_atb version failed." << std::endl;
::H5Gclose(id);
a_class.clear();
a_version = 0;
return false;
}
::H5Gclose(id);
return true;
}
}}
#endif
+31
View File
@@ -0,0 +1,31 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_h
#define toolx_hdf5_h
#include <hdf5.h>
#if (H5_VERS_MAJOR>=1) && (H5_VERS_MINOR<=6)
#define toolx_H5Dopen H5Dopen
#define toolx_H5Dcreate H5Dcreate
#define toolx_H5Acreate H5Acreate
#define toolx_H5Tarray_create H5Tarray_create
#define toolx_H5Tget_array_dims H5Tget_array_dims
#define toolx_H5Gcreate H5Gcreate
#define toolx_H5Gopen H5Gopen
#define toolx_H5Aiterate H5Aiterate
#define toolx_H5free_memory free
#else
#define toolx_H5Dopen H5Dopen1
#define toolx_H5Dcreate H5Dcreate1
#define toolx_H5Acreate H5Acreate1
#define toolx_H5Tarray_create H5Tarray_create1
#define toolx_H5Tget_array_dims H5Tget_array_dims1
#define toolx_H5Gcreate H5Gcreate1
#define toolx_H5Gopen H5Gopen1
#define toolx_H5Aiterate H5Aiterate1
#define toolx_H5free_memory H5free_memory
#endif
#endif
+37
View File
@@ -0,0 +1,37 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_header
#define toolx_hdf5_header
#include "tools"
#include "T_tools"
namespace toolx {
namespace hdf5 {
inline bool write_header(hid_t a_file,int a_version = 1) {
hid_t header = toolx_H5Gcreate(a_file,"header",0);
if(header<0) return false;
if(!write_atb(header,"writer","exlib")) {::H5Gclose(header);return false;}
if(!write_scalar_atb<int>(header,"data_schema_version",a_version)) {::H5Gclose(header);return false;}
::H5Gclose(header);
return true;
}
inline bool read_header(hid_t a_file,std::string& a_writer,int& a_data_schema_version) {
hid_t header = toolx_H5Gopen(a_file,"header");
if(header<0) {a_writer.clear();a_data_schema_version=0;return false;}
if(!read_atb(header,"writer",a_writer)) {::H5Gclose(header);a_writer.clear();a_data_schema_version=0;return false;}
if(!read_atb(header,"data_schema_version",a_data_schema_version)) {
::H5Gclose(header);
a_writer.clear();a_data_schema_version=0;
return false;
}
::H5Gclose(header);
return true;
}
}}
#endif
File diff suppressed because it is too large Load Diff
+319
View File
@@ -0,0 +1,319 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_pages
#define toolx_hdf5_pages
#include "T_tools"
#include "tools"
#include <tools/S_STRING>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
#include <ostream>
namespace toolx {
namespace hdf5 {
TOOLS_GLOBAL_STRING(pages)
TOOLS_GLOBAL_STRING(entries)
TOOLS_GLOBAL_STRING(columns)
TOOLS_GLOBAL_STRING(names)
TOOLS_GLOBAL_STRING(forms)
class pages {
TOOLS_SCLASS(toolx::hdf5::pages)
public:
pages(std::ostream& a_out,
hid_t a_group,const std::string& a_name,const std::string& a_form,
bool a_write,unsigned int a_compress)
:m_out(a_out),m_name(a_name),m_form(a_form)
//,m_type(0),m_size(0)
,m_group(-1),m_dataset(-1),m_write(a_write),m_compress(a_compress),m_entries(0),m_pos(0){
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
if(m_write) {
m_group = toolx_H5Gcreate(a_group,m_name.c_str(),0);
if(m_group<0) {
m_out << "pages::pages : can't create group for column " << m_name << "." << std::endl;
m_group = -1;
return;
}
if(!write_atb(m_group,"class",s_class())) {
m_out << "pages::pages : write_atb(class) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
int v = 1;
if (!write_scalar_atb<int>(m_group,"version",v)) {
m_out << "pages::pages : write_scalar_atb(version) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
} else {
m_group = toolx_H5Gopen(a_group,m_name.c_str());
if(m_group<0) {
m_out << "pages::pages : can't open group for column " << m_name << "." << std::endl;
m_group = -1;
return;
}
if(!read_scalar<tools::uint64>(m_group,s_entries(),m_entries)) {
m_out << "pages::pages : read_scalar(entries) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
}
}
virtual ~pages(){
if(m_write) {
if(!write_scalar<tools::uint64>(m_group,s_entries(),m_entries)) {
m_out << "pages::~pages : write_scalar(entries) failed." << std::endl;
}
if(m_dataset>=0) ::H5Dclose(m_dataset);
}
::H5Gclose(m_group);
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
pages(const pages& a_from):m_out(a_from.m_out){
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
pages& operator=(const pages&){return *this;}
public:
bool is_valid() const {return m_group<0?false:true;}
const std::string& name() const {return m_name;}
const std::string& form() const {return m_form;}
//int type() const {return m_type;}
//unsigned int size() const {return m_size;}
tools::uint64 entries() const {return m_entries;}
tools::uint64 pos() const {return m_pos;}
void reset_pos() {m_pos = 0;}
template <class TYPE>
bool write_page(size_t a_size,const TYPE* a_array) {
if(!m_pos) {
if(!write_array<TYPE>(m_group,s_pages(),a_size,a_array,a_size?a_size:32,m_compress)) {
m_out << "pages::write_page : write_array<TYPE>() failed. Pos " << m_pos << std::endl;
return false;
}
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
if(m_dataset<0) {
m_out << "pages::write_page : H5Dopen failed. Pos " << m_pos << std::endl;
return false;
}
} else {
if(!write_append_array_dataset<TYPE>(m_dataset,a_size,a_array)) {
m_out << "pages::write_page : write_append_array_dataset<TYPE>() failed. Pos " << m_pos << std::endl;
return false;
}
}
m_pos += a_size;
m_entries = m_pos;
return true;
}
template <class TYPE>
bool read_page(size_t a_size,TYPE* a_array) {
//it is assumed that a_array can contain a_size*sizeof(TYPE) bytes.
unsigned int _size = a_size;
unsigned int n = 0;
TYPE* array = 0;
if(!read_sub_array<TYPE>(m_group,s_pages(),(unsigned int)m_pos,(unsigned int)_size,n,array)) {
m_out << "pages::read_page : read_sub_array<TYPE>() failed." << std::endl;
return false;
}
if(n!=_size) {
m_out << "pages::read_page : size mismatch. Requested " << _size << ", got "<< n << "." << std::endl;
delete [] array;
return false;
}
{TYPE* rpos = (TYPE*)array;
TYPE* wpos = (TYPE*)a_array;
for(size_t i=0;i<n;i++,rpos++,wpos++) *wpos = *rpos;
for(size_t i=n;i<_size;i++,rpos++,wpos++) *wpos = TYPE();}
delete [] array;
m_pos += n;
return true;
}
template <class TYPE>
bool write_vlen(size_t a_size,const TYPE* a_array) {
if(!m_pos) {
if(!hdf5::write_vlen<TYPE>(m_group,s_pages(),a_size,a_array,a_size?a_size:32,m_compress)) {
m_out << "pages::write_vlen : write_vlen<TYPE>() failed. Pos " << m_pos << std::endl;
return false;
}
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
if(m_dataset<0) {
m_out << "pages::write_vlen : H5Dopen failed. Pos " << m_pos << std::endl;
return false;
}
} else {
if(!write_append_vlen_dataset<TYPE>(m_dataset,a_size,a_array)) {
m_out << "pages::write_vlen : write_append_vlen_dataset<TYPE>() failed. Pos " << m_pos << std::endl;
return false;
}
}
m_pos++;
m_entries++;
return true;
}
template <class TYPE>
bool read_vlen(size_t& a_size,TYPE*& a_array) {
//it is assumed that a_array can contain a_size*sizeof(TYPE) bytes.
unsigned int sz;
if(!read_sub_vlen<TYPE>(m_group,s_pages(),(unsigned int)m_pos,sz,a_array)) {
m_out << "pages::read_vlen : read_sub_vlen<TYPE>() failed." << std::endl;
a_size = 0;
a_array = 0;
return false;
}
a_size = sz;
m_pos++;
m_entries++;
return true;
}
bool write_string(const std::string& a_string) {
if(!m_pos) {
if(!hdf5::write_string_dataset(m_group,s_pages(),a_string,128,m_compress)) { //32=>enforce extendable.
m_out << "pages::write_string : hdf5::write_string() failed. Pos " << m_pos << std::endl;
return false;
}
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
if(m_dataset<0) {
m_out << "pages::write_string : H5Dopen failed. Pos " << m_pos << std::endl;
return false;
}
} else {
if(!write_append_string_dataset(m_dataset,a_string)) {
m_out << "pages::write_string : write_append_string_dataset() failed. Pos " << m_pos << std::endl;
return false;
}
}
m_pos++;
m_entries++;
return true;
}
bool read_string(std::string& a_string) {
if(!read_sub_string(m_group,s_pages(),(unsigned int)m_pos,a_string)) {
m_out << "pages::read_string : read_sub_string() failed." << std::endl;
a_string.clear();
return false;
}
m_pos++;
m_entries++;
return true;
}
/*
bool write_string(const std::string& a_string) {return write_vlen<char>(a_string.size(),a_string.c_str());}
bool read_string(std::string& a_string) {
size_t sz;char* _data;
if(!read_vlen<char>(sz,_data)) {a_string.clear();return false;}
a_string.resize(sz);
for(size_t index=0;index<sz;index++) a_string[index] = _data[index];
delete [] _data;
return true;
}
*/
/*
bool write_strings(size_t a_number,void* a_array) {
size_t sz = m_size*a_number;
char* buffer = new char[sz];
{char* pos = buffer;
for(size_t index=0;index<sz;index++,pos++) *pos = ' ';}
{char** strings = (char**)a_array;
char* pos = buffer;
size_t ls;
for(size_t index=0;index<a_number;index++) {
char* ss = strings[index];
ls = ::strlen(ss);
::memcpy(pos,ss,ls); //do not copy the ending 0.
*(pos+m_size-1) = 0;
pos += m_size;
}}
if(!m_pos) {
unsigned int chunked = 32*m_size; //<size>A strings.
if(!write_array<char>(m_group,s_pages(),sz,buffer,chunked,m_compress)) {
m_out << "pages::write_strings : write_strings() failed. Pos " << m_pos << std::endl;
return false;
}
m_dataset = toolx_H5Dopen(m_group,s_pages().c_str());
if(m_dataset<0) {
m_out << "pages::write_strings : H5Dopen failed. Pos " << m_pos << std::endl;
return false;
}
} else {
if(!write_append_array_dataset<char>(m_dataset,sz,buffer)) {
m_out << "pages::write_strings : write_append_strings() failed. Pos " << m_pos << std::endl;
return false;
}
}
m_pos += a_number;
m_entries = m_pos;
return true;
}
bool read_strings(size_t a_size,char* a_array) {
unsigned int _size = a_size*m_size;
unsigned int n = 0;
char* array = 0;
if(!read_sub_array<char>(m_group,s_pages(),m_pos,_size,n,array)) {
m_out << "pages::read_strings : read_sub_array<char>() failed." << std::endl;
return false;
}
if(n!=_size) {
m_out << "pages::read_strings : size mismatch. Requested " << _size << ", got "<< n << "." << std::endl;
delete [] array;
return false;
}
char* pos = array;
{char** strings = (char**)a_array;
for(size_t index=0;index<a_size;index++) {
::memcpy(strings[index],pos,m_size*sizeof(char));
pos += m_size;
}}
delete [] array;
m_pos += n;
return true;
}
*/
protected:
std::ostream& m_out;
std::string m_name;
std::string m_form;
//int m_type;
//unsigned int m_size;
hid_t m_group;
hid_t m_dataset;
bool m_write;
unsigned int m_compress; //if write.
tools::uint64 m_entries;
tools::uint64 m_pos;
};
}}
#endif
+205
View File
@@ -0,0 +1,205 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_hdf5_store
#define toolx_hdf5_store
#include "pages"
#include <tools/vmanip>
#include <tools/sout>
namespace toolx {
namespace hdf5 {
class store {
public:
TOOLS_SCLASS(toolx::hdf5::store)
public:
store(std::ostream& a_out,hid_t a_group,const std::string& a_name,bool a_write,unsigned int a_compress)
:m_out(a_out)
,m_write(a_write)
,m_compress(a_compress) //used at write.
,m_group(-1)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
if(m_write) {
if(a_name.empty()) {
a_out << "toolx::hdf5::store::store : string a_name is empty." << std::endl;
m_group = -1;
return;
}
m_group = toolx_H5Gcreate(a_group,a_name.c_str(),0);
if(m_group<0) {
a_out << "toolx::hdf5::store::store : can't create " << a_name << " group." << std::endl;
m_group = -1;
return;
}
if(!write_atb(m_group,"type","object")) {
m_out << "toolx::hdf5::store::store : write_atb(type) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
if(!write_atb(m_group,"class",s_class())) {
m_out << "toolx::hdf5::store::store : write_atb(class) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
int v = 2; //1->2 add "type" atb.
if(!write_scalar_atb<int>(m_group,"version",v)) {
m_out << "toolx::hdf5::store::store : write_scalar_atb(version) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
} else { // to read.
m_group = toolx_H5Gopen(a_group,a_name.c_str());
if(m_group<0) {
a_out << "toolx::hdf5::store::store : can't open " << a_name << " group." << std::endl;
m_group = -1;
return;
}
std::vector<std::string> names;
if(!read_array_string(m_group,s_names(),names)) {
m_out << "toolx::hdf5::store::store : read_array_string(names) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
std::vector<std::string> TFORMs;
if(!read_array_string(m_group,s_forms(),TFORMs)) {
m_out << "toolx::hdf5::store::store : read_array_string(tforms) failed." << std::endl;
::H5Gclose(m_group);
m_group = -1;
return;
}
if(names.size()!=TFORMs.size()) {
m_out << "toolx::hdf5::store::store : names/TFORMs size mismatch." << std::endl;
m_out << "names :" << std::endl;
{tools_vforcit(std::string,names,it) m_out << *it << std::endl;}
m_out << "TFORMs :" << std::endl;
{tools_vforcit(std::string,TFORMs,it) m_out << *it << std::endl;}
::H5Gclose(m_group);
m_group = -1;
return;
}
for(size_t index=0;index<names.size();index++) {
if(!create_pages(names[index],TFORMs[index])) {
m_out << "toolx::hdf5::store::store : can't create hdf5_column "
<< tools::sout(names[index]) << "." << std::endl;
tools::safe_clear(m_pagess);
::H5Gclose(m_group);
m_group = -1;
return;
}
}
}
}
virtual ~store(){
if(m_write) {
tools::uint64 _entries;
if(!entries(_entries)) {
m_out << "toolx::hdf5::store::~store : not same entries on all columns. Write 0." << std::endl;
}
if(m_group<0) { //constructor may have failed.
} else {
if(!write_scalar<tools::uint64>(m_group,s_entries(),_entries)) {
m_out << "toolx::hdf5::store::~store : write_scalar(entries) failed." << std::endl;
}
if(!write_scalar<unsigned int>(m_group,s_columns(),m_pagess.size())) {
m_out << "toolx::hdf5::store::~store : write_scalar(columns) failed." << std::endl;
}
{std::vector<std::string> names;
tools_vforcit(pages*,m_pagess,it) names.push_back((*it)->name());
//{m_out << "debug : write : names :" << std::endl;
// tools_vforcit(std::string,names,it) m_out << *it << std::endl;}
if(!write_array_string(m_group,s_names(),names)) {
m_out << "toolx::hdf5::store::~store : write_array_string(names) failed." << std::endl;
}}
{std::vector<std::string> TFORMs;
tools_vforcit(pages*,m_pagess,it) TFORMs.push_back((*it)->form());
//{m_out << "debug : write : TFORMs :" << std::endl;
// tools_vforcit(std::string,TFORMs,it) m_out << *it << std::endl;}
if(!write_array_string(m_group,s_forms(),TFORMs)) {
m_out << "toolx::hdf5::store::~store : write_array_string(tforms) failed." << std::endl;
}}
}
}
tools::safe_clear(m_pagess);
if(m_group<0) { //constructor may have failed.
} else {
::H5Gclose(m_group);
}
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
store(const store& a_from)
:m_out(a_from.m_out)
,m_name(a_from.m_name)
,m_compress(a_from.m_compress)
,m_group(-1)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
store& operator=(const store&){return *this;}
public:
std::ostream& out() const {return m_out;}
//bool fill(tools::uint32 &a_n){a_n = 0;return true;}
bool entries(tools::uint64& a_entries) const {
if(m_pagess.empty()) {a_entries = 0;return true;}
a_entries = m_pagess.front()->entries();
tools_vforcit(pages*,m_pagess,it) {
if((*it)->entries()!=a_entries) {
m_out << "toolx::hdf5::store::entries : not same entries on all columns."
<< " Front " << a_entries << ", it " << (*it)->entries() << "." << std::endl;
a_entries = 0;
return false;
}
}
return true;
}
pages* create_pages(const std::string& a_name,const std::string& a_form) {
//::printf("debug : create_pages %s %s\n",a_name.c_str(),a_form.c_str());
pages* _pages = new pages(m_out,m_group,a_name,a_form,m_write,m_compress);
if(!_pages->is_valid()) {
m_out << "toolx::hdf5::store::create_column : can't create pages." << std::endl;
delete _pages;
return 0;
}
m_pagess.push_back(_pages);
return _pages;
}
/*
pages* find_column(unsigned int a_index) {
if(a_index>=m_pagess.size()) {
m_out << "toolx::hdf5::store::find_column : out of range index." << std::endl;
return 0;
}
return m_pagess[a_index];
}
const std::vector<pages*>& columns() const {return m_pagess;}*/
hid_t group() const {return m_group;}
unsigned int compress_level() const {return m_compress;}
protected:
std::ostream& m_out;
std::string m_name;
bool m_write;
unsigned int m_compress;
hid_t m_group;
std::vector<pages*> m_pagess;
};
}}
#endif
File diff suppressed because it is too large Load Diff
+266
View File
@@ -0,0 +1,266 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_mpi_hmpi
#define toolx_mpi_hmpi
// code to send, receive histos through MPI.
#include <tools/histo/hmpi>
#include <tools/histo/hd2mpi>
#include <tools/histo/h1d>
#include <tools/histo/h2d>
#include <tools/histo/h3d>
#include <tools/histo/p1d>
#include <tools/histo/p2d>
#include "wrmpi"
namespace toolx {
namespace mpi {
class hmpi : public virtual tools::histo::hmpi {
typedef tools::histo::hmpi parent;
protected:
typedef unsigned int num_t;
static const std::string& s_class() {
static const std::string s_v("toolx::mpi::hmpi");
return s_v;
}
public:
virtual bool pack(const tools::histo::h1d& a_h) {
if(!m_wrmpi.spack(a_h.s_cls())) return false;
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
return true;
}
virtual bool pack(const tools::histo::h2d& a_h) {
if(!m_wrmpi.spack(a_h.s_cls())) return false;
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
return true;
}
virtual bool pack(const tools::histo::h3d& a_h) {
if(!m_wrmpi.spack(a_h.s_cls())) return false;
if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false;
return true;
}
virtual bool pack(const tools::histo::p1d& a_h) {
if(!m_wrmpi.spack(a_h.s_cls())) return false;
if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false;
return true;
}
virtual bool pack(const tools::histo::p2d& a_h) {
if(!m_wrmpi.spack(a_h.s_cls())) return false;
if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false;
return true;
}
public:
virtual bool beg_send(unsigned int a_nhist) {
m_wrmpi.pack_reset();
return m_wrmpi.pack(a_nhist);
}
virtual bool send(int a_dest) {
if(::MPI_Send(m_wrmpi.buffer(),m_wrmpi.ipos(),MPI_CHAR,a_dest,m_tag,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::hmpi::send : rank " << m_rank << " : MPI_Send failed." << std::endl;
return false;
}
m_wrmpi.pack_reset();
return true;
}
public:
virtual bool wait_histos(int a_src,std::vector< std::pair<std::string,void*> >& a_hists) {
a_hists.clear();
typedef std::pair<std::string,void*> class_pointer;
MPI_Status status;
if(::MPI_Probe(a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Probe : failed." << std::endl;
return false;
}
int buffer_size = 0;
if(::MPI_Get_count(&status,MPI_CHAR,&buffer_size)!=MPI_SUCCESS) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Get_count : failed." << std::endl;
return false;
}
if(!buffer_size) {
m_out << "exlb::mpi::wait_histos : MPI_Get_count returns zero data." << std::endl;
return false;
}
if(m_verbose) m_out << "rank " << m_rank << " : get_count " << buffer_size << std::endl;
char* buffer = new char[buffer_size];
if(!buffer) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : can't alloc buffer of size " << buffer_size << std::endl;
return false;
}
if(::MPI_Recv(buffer,buffer_size,MPI_CHAR,a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Recv : failed." << std::endl;
delete [] buffer;
return false;
}
if(m_verbose) m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : unpack data ..." << std::endl;
wrmpi _mpi(m_out,m_comm,buffer_size,buffer); //give ownership of buffer to _mpi.
num_t nhist;
if(!_mpi.unpack(nhist)) return false;
if(m_verbose)
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank << " : number of histos to unpack " << nhist << std::endl;
{for(num_t ihist=0;ihist<nhist;ihist++) {
std::string scls;
if(!_mpi.sunpack(scls)) return false;
if(scls==tools::histo::h1d::s_class()) {
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
tools::histo::h1d* h = new tools::histo::h1d("",10,0,1);
h->copy_from_data(hdata);
if(m_verbose) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got a " << scls
<< ", title " << h->title()
<< ", mean_x " << h->mean() << ", rms " << h->rms()
<< std::endl;
}
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
} else if(scls==tools::histo::h2d::s_class()) {
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
tools::histo::h2d* h = new tools::histo::h2d("",10,0,1,10,0,1);
h->copy_from_data(hdata);
if(m_verbose) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got a " << scls
<< ", title " << h->title()
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
<< std::endl;
}
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
} else if(scls==tools::histo::h3d::s_class()) {
tools::histo::histo_data<double,unsigned int,unsigned int,double> hdata;
if(!histo_data_duiuid_unpack(_mpi,hdata)) return false;
tools::histo::h3d* h = new tools::histo::h3d("",10,0,1,10,0,1,10,0,1);
h->copy_from_data(hdata);
if(m_verbose) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got a " << scls
<< ", title " << h->title()
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
<< ", mean_z " << h->mean_z() << ", rms_z " << h->rms_z()
<< std::endl;
}
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
} else if(scls==tools::histo::p1d::s_class()) {
tools::histo::profile_data<double,unsigned int,unsigned int,double,double> pdata;
if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false;
tools::histo::p1d* h = new tools::histo::p1d("",10,0,1);
h->copy_from_data(pdata);
if(m_verbose) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got a " << scls
<< ", title " << h->title()
<< ", mean_x " << h->mean() << ", rms " << h->rms()
<< std::endl;
}
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
} else if(scls==tools::histo::p2d::s_class()) {
tools::histo::profile_data<double,unsigned int,unsigned int,double,double> pdata;
if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false;
tools::histo::p2d* h = new tools::histo::p2d("",10,0,1,10,0,1);
h->copy_from_data(pdata);
if(m_verbose) {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got a " << scls
<< ", title " << h->title()
<< ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x()
<< ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y()
<< std::endl;
}
a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h.
} else {
m_out << "toolx::mpi::hmpi::wait_histos : rank " << m_rank
<< " : got not treated class " << scls
<< std::endl;
}
}} //ihist
return true;
}
public:
virtual int rank() const { return m_rank;}
virtual bool comm_rank(int& a_rank) const {
if(::MPI_Comm_rank(m_comm,&a_rank)!=MPI_SUCCESS) {a_rank=-1;return false;}
return true;
}
virtual bool comm_size(int& a_size) const {
if(::MPI_Comm_size(m_comm,&a_size)!=MPI_SUCCESS) {a_size=0;return false;}
return true;
}
public:
hmpi(std::ostream& a_out,int a_rank,int a_tag,const MPI_Comm& a_comm,bool a_verbose = false)
:m_out(a_out)
,m_rank(a_rank)
,m_tag(a_tag)
,m_comm(a_comm)
,m_verbose(a_verbose)
,m_wrmpi(a_out,a_comm)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
virtual ~hmpi(){
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
hmpi(const hmpi& a_from)
:parent(a_from)
,m_out(a_from.m_out)
,m_rank(a_from.m_rank)
,m_tag(a_from.m_tag)
,m_comm(a_from.m_comm)
,m_verbose(a_from.m_verbose)
,m_wrmpi(a_from.m_out,a_from.m_comm)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
hmpi& operator=(const hmpi& a_from){
m_rank = a_from.m_rank;
m_tag = a_from.m_tag;
m_verbose = a_from.m_verbose;
return *this;
}
protected:
std::ostream& m_out;
int m_rank;
int m_tag;
const MPI_Comm& m_comm;
bool m_verbose;
wrmpi m_wrmpi;
};
}}
#endif
+66
View File
@@ -0,0 +1,66 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_mpi_wait_buffer
#define toolx_mpi_wait_buffer
#include <mpi.h>
#include <ostream>
namespace toolx {
namespace mpi {
inline bool wait_buffer(std::ostream& a_out,int a_rank,int a_src,int a_tag,const MPI_Comm& a_comm,
int& a_buffer_size,char*& a_buffer,int& a_probe_src,bool a_verbose = false) {
a_buffer = 0;
a_buffer_size = 0;
a_probe_src = -1;
MPI_Status status;
if(::MPI_Probe(a_src,a_tag,a_comm,&status)!=MPI_SUCCESS) {
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Probe : failed." << std::endl;
return false;
}
if(::MPI_Get_count(&status,MPI_CHAR,&a_buffer_size)!=MPI_SUCCESS) {
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Get_count : failed." << std::endl;
a_buffer_size = 0;
return false;
}
a_probe_src = status.MPI_SOURCE;
if(!a_buffer_size) {
a_out << "exlb::mpi::wait_buffer : MPI_Get_count returns zero data." << std::endl;
a_probe_src = -1;
return false;
}
if(a_verbose) a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : get_count " << a_buffer_size << std::endl;
a_buffer = new char[a_buffer_size];
if(!a_buffer) {
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : can't alloc buffer of size " << a_buffer_size << std::endl;
a_buffer_size = 0;
a_probe_src = -1;
return false;
}
if(::MPI_Recv(a_buffer,a_buffer_size,MPI_CHAR,status.MPI_SOURCE,status.MPI_TAG,a_comm,&status)!=MPI_SUCCESS) {
a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : MPI_Recv : failed." << std::endl;
a_buffer_size = 0;
delete [] a_buffer;
a_buffer = 0;
a_probe_src = -1;
return false;
}
if(a_verbose) a_out << "toolx::mpi::wait_buffer : rank " << a_rank << " : unpack data ..." << std::endl;
return true;
}
}}
#endif
+71
View File
@@ -0,0 +1,71 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_mpi_world
#define toolx_mpi_world
// code to wrap MPI global things by having an interface (toolx::mpi).
#include <tools/impi_world>
#include <mpi.h>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
namespace toolx {
namespace mpi {
class world : public virtual tools::impi_world {
typedef tools::impi_world parent;
#ifdef TOOLS_MEM
protected:
static const std::string& s_class() {
static const std::string s_v("toolx::mpi::world");
return s_v;
}
#endif
public:
virtual bool init(int* a_argc,char*** a_argv) {
if(::MPI_Init(a_argc,a_argv)!=MPI_SUCCESS) return false;
return true;
}
virtual bool rank(int& a_rank) const {
if(::MPI_Comm_rank(MPI_COMM_WORLD,&a_rank)!=MPI_SUCCESS) {a_rank=-1;return false;}
return true;
}
virtual bool size(int& a_size) const {
if(::MPI_Comm_size(MPI_COMM_WORLD,&a_size)!=MPI_SUCCESS) {a_size=0;return false;}
return true;
}
virtual bool processor_name(std::string& a_s) const {
char name[MPI_MAX_PROCESSOR_NAME];
int lname;
if(::MPI_Get_processor_name(name,&lname)!=MPI_SUCCESS) {a_s.clear();return false;}
a_s = std::string(name);
return true;
}
public:
world() {
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
virtual ~world(){
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
world(const world& a_from):parent(a_from) {
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
world& operator=(const world&) {return *this;}
};
}}
#endif
+528
View File
@@ -0,0 +1,528 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_mpi_wrmpi
#define toolx_mpi_wrmpi
#include "wait_buffer"
#include <tools/impi>
#include <tools/vdata>
#include <tools/realloc>
#include <tools/mnmx>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
// the below must be in sync with tools/typedefs
#ifdef _MSC_VER
//typedef __int64 int64;
//typedef unsigned __int64 uint64;
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG_LONG
#define TOOLX_MPI_INT64 MPI_LONG_LONG
#elif defined(_LP64)
// 64 Bit Platforms
//typedef long int64;
//typedef unsigned long uint64;
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG
#define TOOLX_MPI_INT64 MPI_LONG
#else
// 32-Bit Platforms
//typedef long long int64;
//typedef unsigned long long uint64;
#define TOOLX_MPI_UINT64 MPI_UNSIGNED_LONG_LONG
#define TOOLX_MPI_INT64 MPI_LONG_LONG
#endif
namespace toolx {
namespace mpi {
class wrmpi : public virtual tools::impi {
typedef tools::impi parent;
public:
typedef unsigned int num_t;
protected:
static const std::string& s_class() {
static const std::string s_v("toolx::mpi::wrmpi");
return s_v;
}
public: //tools::impi
virtual bool pack(char a_val) {
tools::uint32 sz = tools::uint32(sizeof(char));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(char) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(short a_val) {
tools::uint32 sz = tools::uint32(sizeof(short));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_SHORT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(short) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(int a_val) {
tools::uint32 sz = tools::uint32(sizeof(int));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(int) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(unsigned int a_val) {
tools::uint32 sz = tools::uint32(sizeof(unsigned int));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(unsigned int) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(tools::uint64 a_val) {
tools::uint32 sz = tools::uint32(sizeof(tools::uint64));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,TOOLX_MPI_UINT64,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(uint64) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(tools::int64 a_val) {
tools::uint32 sz = tools::uint32(sizeof(tools::int64));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,TOOLX_MPI_INT64,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(int64) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(float a_val) {
tools::uint32 sz = tools::uint32(sizeof(float));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_FLOAT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(float) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(double a_val) {
tools::uint32 sz = tools::uint32(sizeof(double));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(double) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool bpack(bool a_val) {
tools::uint32 sz = tools::uint32(sizeof(unsigned char));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
unsigned char val = a_val?1:0;
if(::MPI_Pack(&val,1,MPI_UNSIGNED_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Pack(bool) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool spack(const std::string& a_s) {
if(!pack((num_t)a_s.size())) return false;
tools::uint32 sz = (tools::uint32)a_s.size();
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(a_s.c_str(),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::string) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool vpack(const std::vector<unsigned int>& a_v) {
if(!pack((num_t)a_v.size())) return false;
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(unsigned int));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<unsigned int*>(tools::vec_data(a_v)),a_v.size(),
MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<unsigned int>) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool vpack(const std::vector<int>& a_v) {
if(!pack((num_t)a_v.size())) return false;
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(int));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<int*>(tools::vec_data(a_v)),a_v.size(),MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<int>) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool vpack(const std::vector<double>& a_v) {
if(!pack((num_t)a_v.size())) return false;
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(double));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<double*>(tools::vec_data(a_v)),a_v.size(),MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(std::vector<double>) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(tools::uint32 a_size,const char* a_buffer) {
if(!pack((num_t)a_size)) return false;
tools::uint32 sz = (tools::uint32)(a_size*sizeof(char));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<char*>(a_buffer),a_size,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(a_buffer,a_size,MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(char*) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(tools::uint32 a_size,const int* a_buffer) {
if(!pack((num_t)a_size)) return false;
tools::uint32 sz = (tools::uint32)(a_size*sizeof(int));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
if(::MPI_Pack(const_cast<int*>(a_buffer),a_size,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(a_buffer,a_size,MPI_INT,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "toolx::mpi::wrmpi : MPI_Pack(int*) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
public: //tools::impi
virtual bool unpack(char& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(char) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(short& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_SHORT,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(short) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(int& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_INT,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(unsigned int& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(unsigned int) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(tools::uint64& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,TOOLX_MPI_UINT64,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(uint64) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(tools::int64& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,TOOLX_MPI_INT64,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int64) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(float& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_FLOAT,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(float) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(double& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(double) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool bunpack(bool& a_val) {
typedef unsigned char bool_t;
bool_t val;
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&val,1,MPI_UNSIGNED_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(bool) failed." << std::endl;
a_val = false;
return false;
}
a_val = val==1?true:false;
return true;
}
virtual bool vunpack(std::vector<unsigned int>& a_v) {
num_t num;
if(!unpack(num)) {a_v.clear();return false;}
a_v.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<unsigned int>) failed." << std::endl;
a_v.clear();
return false;
}
return true;
}
virtual bool vunpack(std::vector<int>& a_v) {
num_t num;
if(!unpack(num)) {a_v.clear();return false;}
a_v.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_INT,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<int>) failed." << std::endl;
a_v.clear();
return false;
}
return true;
}
virtual bool vunpack(std::vector<double>& a_v) {
num_t num;
if(!unpack(num)) {a_v.clear();return false;}
a_v.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::vector<double>) failed." << std::endl;
a_v.clear();
return false;
}
return true;
}
virtual bool sunpack(std::string& a_s) {
num_t num;
if(!unpack(num)) {a_s.clear();return false;}
a_s.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(std::string) failed." << std::endl;
a_s.clear();
return false;
}
return true;
}
virtual bool unpack(tools::uint32& a_size,char*& a_buffer) {
num_t num;
if(!unpack(num)) {a_size = 0;a_buffer = 0;return false;}
a_buffer = new char[num];
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,a_buffer,num,MPI_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(char*) failed." << std::endl;
delete [] a_buffer;
a_size = 0;
a_buffer = 0;
return false;
}
a_size = num;
return true;
}
virtual bool unpack(tools::uint32& a_size,int*& a_buffer) {
num_t num;
if(!unpack(num)) {a_size = 0;a_buffer = 0;return false;}
a_buffer = new int[num];
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,a_buffer,num,MPI_INT,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi : MPI_Unpack(int*) failed." << std::endl;
delete [] a_buffer;
a_size = 0;
a_buffer = 0;
return false;
}
a_size = num;
return true;
}
virtual void pack_reset() {
delete [] m_buffer;
m_size = 128;
m_buffer = new char[m_size];
//if(!m_buffer) {}
m_max = m_buffer+m_size;
m_pos = m_buffer;
m_ipos = 0; //IMPORTANT
}
virtual bool send_buffer(int a_dest,int a_tag) { // used in tools/mpi/pntuple.
if(::MPI_Send(m_buffer,m_ipos,MPI_CHAR,a_dest,a_tag,m_comm)!=MPI_SUCCESS) {
m_out << "toolx::mpi::wrmpi::send_buffer : MPI_Send() failed for rank destination " << a_dest << "." << std::endl;
return false;
}
return true;
}
virtual bool wait_buffer(int a_rank,int a_src,int a_tag,int& a_probe_src,bool a_verbose = false) {
int buffer_size = 0;
char* _buffer = 0;
if (!mpi::wait_buffer(m_out,a_rank,a_src,a_tag,m_comm,buffer_size,_buffer,a_probe_src,a_verbose)) {
m_out << "toolx::mpi::wrmpi::wait_buffer : failed for rank " << a_rank << " and source " << a_src <<"." << std::endl;
return false;
}
// we take ownership of buffer :
delete [] m_buffer;
m_size = buffer_size;
m_buffer = _buffer;
m_max = m_buffer+m_size;
m_pos = m_buffer;
m_ipos = 0; //IMPORTANT
return true;
}
virtual bool wait_buffer(int a_rank,int a_tag,int& a_probe_src,bool a_verbose = false) {
return wait_buffer(a_rank,MPI_ANY_SOURCE,a_tag,a_probe_src,a_verbose);
}
public:
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size = 128) // we expect a_size!=0
:m_out(a_out)
,m_comm(a_comm)
,m_size(0)
,m_buffer(0)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
m_size = a_size;
m_buffer = new char[m_size];
//if(!m_buffer) {}
m_max = m_buffer+m_size;
m_pos = m_buffer;
}
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size,char* a_buffer) //we take ownership of a_buffer.
:m_out(a_out)
,m_comm(a_comm)
,m_size(a_size)
,m_buffer(a_buffer)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
m_max = m_buffer+m_size;
m_pos = m_buffer;
}
virtual ~wrmpi(){
delete [] m_buffer;
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
wrmpi(const wrmpi& a_from)
:parent(a_from)
,m_out(a_from.m_out)
,m_comm(a_from.m_comm)
,m_size(0)
,m_buffer(0)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
wrmpi& operator=(const wrmpi&){return *this;}
public:
int ipos() const {return m_ipos;}
#if defined(TOOLX_USE_MPI_PACK_NOT_CONST) || defined(TOOLS_USE_MPI_PACK_NOT_CONST)
char* buffer() {return m_buffer;}
#else
const char* buffer() const {return m_buffer;}
#endif
protected:
bool expand2(tools::uint32 a_new_size) {return expand(tools::mx<tools::uint32>(2*m_size,a_new_size));} //CERN-ROOT logic.
bool expand(tools::uint32 a_new_size) {
tools::diff_pointer_t len = m_pos-m_buffer;
if(!tools::realloc<char>(m_buffer,a_new_size,m_size)) {
m_out << "toolx::mpi::wrmpi::expand :"
<< " can't realloc " << a_new_size << " bytes."
<< std::endl;
m_size = 0;
m_max = 0;
m_pos = 0;
//m_wb.set_eob(m_max);
return false;
}
m_size = a_new_size;
m_max = m_buffer + m_size;
m_pos = m_buffer + len;
return true;
}
protected:
std::ostream& m_out;
const MPI_Comm& m_comm;
tools::uint32 m_size;
char* m_buffer;
char* m_max;
char* m_pos;
//
int m_ipos;
};
}}
#ifdef TOOLX_MPI_UINT64
#undef TOOLX_MPI_UINT64
#endif
#ifdef TOOLX_MPI_INT64
#undef TOOLX_MPI_INT64
#endif
#endif
+72
View File
@@ -0,0 +1,72 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_raxml
#define toolx_raxml
#include <tools/xml/aidas>
#include "xml/loader"
namespace toolx {
class raxml : public tools::xml::aidas, public xml::loader {
typedef tools::xml::aidas parent_aidas;
typedef xml::loader parent;
public:
raxml(tools::xml::factory& a_fac,std::ostream& a_out,bool a_verbose = false)
:parent_aidas()
,parent(a_fac,a_out,a_verbose)
,m_read_tag(0)
{
set_default_tags(parent::m_tags);
}
virtual ~raxml() {}
public:
void set_read_tag(void* a_tag) {m_read_tag = a_tag;}
protected:
raxml(const raxml& a_from)
:parent_aidas(a_from)
,parent(a_from)
{}
raxml& operator=(const raxml& a_from){
parent_aidas::operator=(a_from);
parent::operator=(a_from);
return *this;
}
public:
bool load_file(const std::string& a_file,bool a_compressed){
m_objects.clear();
if(!parent::load_file(a_file,a_compressed)) return false;
tools::xml::tree* top = top_item();
if(!top) return false;
const std::string& tag_name = top->tag_name();
if(tag_name!=s_aida()) return false;
{tools::xml::looper _for(*top);
while(tools::xml::tree* _tree = _for.next_tree()) {
const std::string& _tag_name = _tree->tag_name();
reader rder = find_reader(_tag_name);
if(!rder) {
m_out << "toolx::raxml::load_file :"
<< " reader not found for " << tools::sout(_tag_name)
<< std::endl;
//m_objects.clear(); //keep already loaded objects.
return false;
} else {
tools::raxml_out ro = rder(*_tree,m_out,m_verbose,m_read_tag);
if(ro.object()) m_objects.push_back(ro);
}
}}
return true;
}
protected:
void* m_read_tag;
};
}
#endif
+660
View File
@@ -0,0 +1,660 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_action
#define toolx_sg_GL_action
#include "GL_manager"
#include <tools/sg/render_action>
//#include <tools/mathf>
//#include <tools/lina/matout>
namespace toolx {
namespace sg {
class GL_action : public tools::sg::render_action {
TOOLS_ACTION(GL_action,toolx::sg::GL_action,tools::sg::render_action)
public:
virtual void draw_vertex_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs){
size_t num = a_floatn/3;
if(!num) return;
_draw_v(a_mode,num,a_xyzs);
}
virtual void draw_vertex_array_xy(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xys){
size_t num = a_floatn/2;
if(!num) return;
#ifdef _WIN32
float* vp = new float[num*3];
if(!vp) return;
float* pos = vp;
float* pda = (float*)a_xys;
for(size_t index=0;index<num;index++){
*pos = *pda;pos++;pda++;
*pos = *pda;pos++;pda++;
*pos = 0;pos++; //Windows GL needs a z = 0.
}
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,vp);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
delete [] vp;
#else
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(2,GL_FLOAT,0,a_xys);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
#endif
}
virtual void draw_vertex_color_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_rgbas){
// Used in atb_vertices.
// We expect a_rgbas of size : 4*(a_floatn/3)
// (then one RGBA color per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vc(a_mode,num,a_xyzs,a_rgbas);
}
virtual void draw_vertex_normal_array(tools::gl::mode_t a_mode,size_t a_floatn,const float* a_xyzs,const float* a_nms){
// We expect a_nms of size : 3*(a_floatn/3)
// (then one normal per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vn(a_mode,num,a_xyzs,a_nms);
}
virtual void draw_vertex_color_normal_array(tools::gl::mode_t a_mode,
size_t a_floatn,const float* a_xyzs,const float* a_rgbas,const float* a_nms){
// Used in atb_vertices.
// We expect a_nms of size : 3*(a_floatn/3)
// (then one normal per 3D point).
// We expect a_rgbas of size : 4*(a_floatn/3)
// (then one RGBA color per 3D point).
size_t num = a_floatn/3;
if(!num) return;
_draw_vcn(a_mode,num,a_xyzs,a_rgbas,a_nms);
}
/////////////////////////////////////////////////////////////////
/// texture /////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void draw_vertex_array_texture(tools::gl::mode_t a_mode,
size_t a_floatn,
const float* a_xyzs,
gstoid a_tex,
const float* a_tex_coords) {
size_t num = a_floatn/3;
if(!num) return;
//expect 2*num a_tex_coords.
::glEnable(GL_TEXTURE_2D);
m_mgr.bind_gsto(a_tex);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
::glBindTexture(GL_TEXTURE_2D,0);
::glDisable(GL_TEXTURE_2D);
}
virtual void draw_vertex_normal_array_texture(tools::gl::mode_t a_mode,
size_t a_floatn,
const float* a_xyzs,
const float* a_nms,
gstoid a_tex,
const float* a_tex_coords) {
size_t num = a_floatn/3;
if(!num) return;
//expect 2*num a_tex_coords.
::glEnable(GL_TEXTURE_2D);
m_mgr.bind_gsto(a_tex);
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_xyzs);
::glNormalPointer(GL_FLOAT,0,a_nms);
::glTexCoordPointer(2,GL_FLOAT,0,a_tex_coords);
::glDrawArrays(a_mode,0,(GLsizei)num);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
::glBindTexture(GL_TEXTURE_2D,0);
::glDisable(GL_TEXTURE_2D);
}
/////////////////////////////////////////////////////////////////
/// VBO /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void begin_gsto(gstoid a_id) {
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
m_mgr.bind_gsto(a_id);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
m_gsto = a_id;
m_created = false;
m_gl_id = m_mgr.gsto_gl_list_id(a_id,m_created);
if(m_gl_id && m_created) {
::glNewList(m_gl_id,GL_COMPILE);
}
#endif
}break;
case tools::sg::gsto_memory:{
m_gsto = a_id;
}break;
}
}
virtual void end_gsto() {
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
::glBindBuffer(GL_ARRAY_BUFFER,0);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
if(m_gl_id && m_created) {
::glEndList();
}
if(m_gl_id) ::glCallList(m_gl_id);
m_created = false;
m_gl_id = 0;
m_gsto = 0;
#endif
}break;
case tools::sg::gsto_memory:{
m_gsto = 0;
}break;
}
}
typedef tools::sg::bufpos bufpos;
virtual void draw_gsto_v(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_v(a_mode,a_elems,(char*)NULL+a_pos_xyzs);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
for(size_t index=0;index<a_elems;index++,pos+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
_draw_v(a_mode,a_elems,pos_xyzs);
}break;
}
}
virtual void draw_gsto_vc(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vc(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
float* pco = (float*)pos_rgbas;
for(size_t index=0;index<a_elems;index++,pos+=3,pco+=4) {
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
_draw_vc(a_mode,a_elems,pos_xyzs,pos_rgbas);
}break;
}
}
virtual void draw_gsto_vn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_nms){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_nms);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
//void* pos_nms = (char*)buffer+a_pos_nms;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
for(size_t index=0;index<a_elems;index++,pos+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_nms = (char*)buffer+a_pos_nms;
_draw_vn(a_mode,a_elems,pos_xyzs,pos_nms);
}break;
}
}
virtual void draw_gsto_vcn(tools::gl::mode_t a_mode,size_t a_elems,bufpos a_pos_xyzs,bufpos a_pos_rgbas,bufpos a_pos_nms){
switch(m_mgr.get_gsto_mode()){
case tools::sg::gsto_gl_vbo:{
#ifdef TOOLX_HAS_GL_VBO
_draw_vcn(a_mode,a_elems,(char*)NULL+a_pos_xyzs,(char*)NULL+a_pos_rgbas,(char*)NULL+a_pos_nms);
#endif
}break;
case tools::sg::gsto_gl_list:{
#ifdef TOOLX_HAS_GL_LIST
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
void* pos_nms = (char*)buffer+a_pos_nms;
if(m_gl_id && m_created) {
::glBegin(a_mode);
float* pos = (float*)pos_xyzs;
float* pco = (float*)pos_rgbas;
float* pnm = (float*)pos_nms;
for(size_t index=0;index<a_elems;
index++,pos+=3,pco+=4,pnm+=3) {
::glVertex3f(*(pos+0),*(pos+1),*(pos+2));
::glColor4f (*(pco+0),*(pco+1),*(pco+2),*(pco+3));
::glNormal3f(*(pnm+0),*(pnm+1),*(pnm+2));
}
::glEnd();
}
#endif
}break;
case tools::sg::gsto_memory:{
float* buffer = m_mgr.gsto_data(m_gsto);
if(!buffer) return;
void* pos_xyzs = (char*)buffer+a_pos_xyzs;
void* pos_rgbas = (char*)buffer+a_pos_rgbas;
void* pos_nms = (char*)buffer+a_pos_nms;
_draw_vcn(a_mode,a_elems,pos_xyzs,pos_rgbas,pos_nms);
}break;
}
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
virtual void clear_color(float a_r,float a_g,float a_b,float a_a){
::glClearColor(a_r,a_g,a_b,a_a);
::glClear(GL_COLOR_BUFFER_BIT);
}
virtual void color4f(float a_r,float a_g,float a_b,float a_a){
::glColor4f(a_r,a_g,a_b,a_a);
}
virtual void line_width(float a_v){::glLineWidth(a_v);}
virtual void point_size(float a_v){::glPointSize(a_v);}
virtual void set_polygon_offset(bool a_v) {
if(a_v) ::glEnable(GL_POLYGON_OFFSET_FILL);
else ::glDisable(GL_POLYGON_OFFSET_FILL);
::glPolygonOffset(1.,1.);
}
virtual void normal(float a_x,float a_y,float a_z) {
::glNormal3f(a_x,a_y,a_z);
}
virtual void set_winding(tools::sg::winding_type a_v) {
if(a_v==tools::sg::winding_ccw)
::glFrontFace(GL_CCW);
else
::glFrontFace(GL_CW);
}
virtual void set_shade_model(tools::sg::shade_type a_v) {
if(a_v==tools::sg::shade_smooth)
::glShadeModel(GL_SMOOTH);
else
::glShadeModel(GL_FLAT);
}
virtual void set_cull_face(bool a_on) {
if(a_on) ::glEnable(GL_CULL_FACE);
else ::glDisable(GL_CULL_FACE);
}
virtual void set_point_smooth(bool a_on) {
if(a_on) ::glEnable(GL_POINT_SMOOTH);
else ::glDisable(GL_POINT_SMOOTH);
}
virtual void set_line_smooth(bool a_on) {
if(a_on) ::glEnable(GL_LINE_SMOOTH);
else ::glDisable(GL_LINE_SMOOTH);
}
virtual void set_depth_test(bool a_on) {
if(a_on) ::glEnable(GL_DEPTH_TEST);
else ::glDisable(GL_DEPTH_TEST);
}
virtual void load_proj_matrix(const tools::mat4f& a_mtx) {
::glMatrixMode(GL_PROJECTION);
::glLoadMatrixf(a_mtx.data());
}
virtual void load_model_matrix(const tools::mat4f& a_mtx) {
::glMatrixMode(GL_MODELVIEW);
::glLoadMatrixf(a_mtx.data());
/*
tools::mat4f tmp(a_mtx);
tmp.no_translate();
tools::mat4f normal_matrix;
if(!tmp.invert(normal_matrix)) {
m_out << "toolx::WebGL::render::load_model_matrix :"
<< " can't invert model matrix."
<< std::endl;
}
normal_matrix.transpose();
tools::mat4f to_check(a_mtx);
to_check.no_translate();
float fepsilon = 1e-10;
if(!normal_matrix.equal_prec(to_check,fepsilon,tools::ffabs)) {
mat_dump(m_out,"problem with normal_matrix ",normal_matrix);
mat_dump(m_out,"expected",to_check);
}
*/
}
virtual unsigned int max_lights() {return GL_MAX_LIGHTS;}
virtual void enable_light(unsigned int a_light,
float a_dx,float a_dy,float a_dz,
float a_r,float a_g,float a_b,float a_a){
::glEnable(GL_LIGHTING);
GLenum light = GL_LIGHT0+a_light;
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
float params[4];
params[0] = -a_dx;
params[1] = -a_dy;
params[2] = -a_dz;
params[3] = 0; //0 tells that it is a directional light.
::glLightfv(light,GL_POSITION,params);
//params[0] = a_dir[0];
//params[1] = a_dir[1];
//params[2] = a_dir[2];
//::glLightfv(light,GL_SPOT_DIRECTION,params);
params[0] = a_r;
params[1] = a_g;
params[2] = a_b;
params[3] = a_a;
::glLightfv(light,GL_DIFFUSE,params);
::glLightfv(light,GL_SPECULAR,params); //coin/SoDirectionalLight does that.
params[0] = 0;
params[1] = 0;
params[2] = 0;
params[3] = 1;
::glLightfv(light,GL_AMBIENT,params); //coin/SoDirectionalLight does that.
// coin/SoDirectionalLight does the below :
::glLightf(light, GL_SPOT_EXPONENT, 0.0);
::glLightf(light, GL_SPOT_CUTOFF, 180.0);
::glLightf(light, GL_CONSTANT_ATTENUATION, 1);
::glLightf(light, GL_LINEAR_ATTENUATION, 0);
::glLightf(light, GL_QUADRATIC_ATTENUATION, 0);
//::printf("debug : GL_MAX_LIGHTS %d\n",GL_MAX_LIGHTS);
::glEnable(light);
}
virtual void set_lighting(bool a_on) {
if(a_on) ::glEnable(GL_LIGHTING);
else ::glDisable(GL_LIGHTING);
}
virtual void set_blend(bool a_on) {
if(a_on) ::glEnable(GL_BLEND);
else ::glDisable(GL_BLEND);
}
virtual void restore_state(unsigned int a_ret_num_light) {
const tools::sg::state& _state = state();
::glMatrixMode(GL_PROJECTION);
::glLoadMatrixf(_state.m_proj.data());
::glMatrixMode(GL_MODELVIEW);
::glLoadMatrixf(_state.m_model.data());
if(_state.m_GL_LIGHTING) ::glEnable(GL_LIGHTING);
else ::glDisable(GL_LIGHTING);
if(_state.m_GL_DEPTH_TEST) ::glEnable(GL_DEPTH_TEST);
else ::glDisable(GL_DEPTH_TEST);
if(_state.m_GL_CULL_FACE) ::glEnable(GL_CULL_FACE);
else ::glDisable(GL_CULL_FACE);
if(_state.m_GL_POINT_SMOOTH) ::glEnable(GL_POINT_SMOOTH);
else ::glDisable(GL_POINT_SMOOTH);
if(_state.m_GL_LINE_SMOOTH) ::glEnable(GL_LINE_SMOOTH);
else ::glDisable(GL_LINE_SMOOTH);
if(_state.m_GL_POLYGON_OFFSET_FILL) ::glEnable(GL_POLYGON_OFFSET_FILL);
else ::glDisable(GL_POLYGON_OFFSET_FILL);
if(_state.m_GL_TEXTURE_2D) ::glEnable(GL_TEXTURE_2D);
else ::glDisable(GL_TEXTURE_2D);
if(_state.m_GL_BLEND) ::glEnable(GL_BLEND);
else ::glDisable(GL_BLEND);
if(_state.m_winding==tools::sg::winding_ccw) {
::glFrontFace(GL_CCW);
} else {
::glFrontFace(GL_CW);
}
if(_state.m_shade_model==tools::sg::shade_smooth)
::glShadeModel(GL_SMOOTH);
else
::glShadeModel(GL_FLAT);
::glColor4f(_state.m_color.r(),
_state.m_color.g(),
_state.m_color.b(),
_state.m_color.a());
::glNormal3f(_state.m_normal.x(),
_state.m_normal.y(),
_state.m_normal.z());
// The "return of separator" state had ret_num_light.
// The restored state has m_light.
// We have to glDisable lights with index in [m_light,ret_num_light-1]
for(unsigned int index=_state.m_light;index<a_ret_num_light;index++) {
::glDisable(GL_LIGHT0+index);
}
::glLineWidth(_state.m_line_width);
::glPointSize(_state.m_point_size);
#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
}
virtual tools::sg::render_manager& render_manager() {return m_mgr;}
public:
GL_action(GL_manager& a_mgr,std::ostream& a_out,unsigned int a_ww,unsigned int a_wh)
:parent(a_out,a_ww,a_wh)
,m_mgr(a_mgr)
,m_gsto(0)
#ifdef TOOLX_HAS_GL_LIST
,m_created(false)
,m_gl_id(0)
#endif
{}
virtual ~GL_action(){}
public:
GL_action(const GL_action& a_from)
:parent(a_from)
,m_mgr(a_from.m_mgr)
,m_gsto(0)
#ifdef TOOLX_HAS_GL_LIST
,m_created(false)
,m_gl_id(0)
#endif
{}
GL_action& operator=(const GL_action& a_from){
render_action::operator=(a_from);
m_gsto = 0;
#ifdef TOOLX_HAS_GL_LIST
m_created = false;
m_gl_id = 0;
#endif
return *this;
}
protected:
void _draw_v(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs){
::glEnableClientState(GL_VERTEX_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vc(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_COLOR_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_nms){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
void _draw_vcn(tools::gl::mode_t a_mode,size_t a_elems,const void* a_pos_xyzs,const void* a_pos_rgbas,const void* a_pos_nms){
::glEnableClientState(GL_VERTEX_ARRAY);
::glEnableClientState(GL_COLOR_ARRAY);
::glEnableClientState(GL_NORMAL_ARRAY);
::glVertexPointer(3,GL_FLOAT,0,a_pos_xyzs);
::glColorPointer(4,GL_FLOAT,0,a_pos_rgbas);
::glNormalPointer(GL_FLOAT,0,a_pos_nms);
::glDrawArrays(a_mode,0,(GLsizei)a_elems);
::glDisableClientState(GL_COLOR_ARRAY);
::glDisableClientState(GL_NORMAL_ARRAY);
::glDisableClientState(GL_VERTEX_ARRAY);
}
protected:
GL_manager& m_mgr;
gstoid m_gsto;
#ifdef TOOLX_HAS_GL_LIST
bool m_created;
gstoid m_gl_id;
#endif
};
}}
#endif
+696
View File
@@ -0,0 +1,696 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_manager
#define toolx_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 toolx {
namespace sg {
class GL_manager : public virtual tools::sg::render_manager {
typedef tools::sg::render_manager parent;
public:
TOOLS_SCLASS(toolx::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 TOOLX_HAS_GL_VBO
#if GL_ARB_framebuffer_object
if(::glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) {
//m_out << "toolx::sg::GL_manager::begin_render :"
// << " frame buffer not complete."
// << std::endl;
return false;
}
#endif //GL_ARB_framebuffer_object
#endif //TOOLX_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,"toolx::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 << "toolx::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 << "toolx::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 << "toolx::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,"toolx::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,"toolx::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 TOOLX_HAS_GL_VBO
unsigned int gl_id = 0;
::glGenBuffers(1,&gl_id);
if(!gl_id) {
if(!m_warned) {
m_warned = true;
m_out << "toolx::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,"toolx::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 //!TOOLX_HAS_GL_VBO
m_out << "toolx::sg::GL_manager::create_gsto_from_data :"
<< " gsto mode is gl_vbo but class not compiled with TOOLX_HAS_GL_VBO."
<< std::endl;
return 0;
#endif //TOOLX_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 TOOLX_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 TOOLX_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 TOOLX_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 TOOLX_HAS_GL_VBO
a_vs.push_back(tools::sg::s_gsto_gl_vbo());
#endif
#ifdef TOOLX_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 TOOLX_HAS_GL_VBO
a_v = tools::sg::s_gsto_gl_vbo();
#endif
#ifdef TOOLX_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 TOOLX_HAS_GL_VBO
,m_gsto_mode(tools::sg::gsto_gl_vbo) //priority to GL VBOs.
#elif TOOLX_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 = tools::_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 TOOLX_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 TOOLX_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 TOOLX_HAS_GL_VBO
return (::glIsBuffer(m_gl_id)==GL_TRUE?true:false);
#endif
} else if(m_kind==kind_list) {
#ifdef TOOLX_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 TOOLX_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
+78
View File
@@ -0,0 +1,78 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_GL_viewer
#define toolx_sg_GL_viewer
#include <tools/sg/viewer>
#include "GL_manager"
#include "GL_action"
namespace toolx {
namespace sg {
class GL_viewer : public tools::sg::viewer {
TOOLS_HEADER(GL_viewer,toolx::sg::GL_viewer,tools::sg::viewer)
public:
void render() {
if(!m_ww) return;
if(!m_wh) return;
m_gl_mgr.begin_render(0,0,m_ww,m_wh,
m_clear_color.r(),
m_clear_color.g(),
m_clear_color.b(),
m_clear_color.a());
GL_action action(m_gl_mgr,m_out,m_ww,m_wh);
action.state().m_use_gsto = m_use_gsto;
action.set_do_transparency(false);
action.set_have_to_do_transparency(false);
m_sg.render(action);
if(!action.end()) { //check that matrices stack are ok.
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
} else {
if(action.have_to_do_transparency()) {
action.set_do_transparency(true);
m_sg.render(action);
if(!action.end()) { //check that matrices stack are ok.
m_out << "toolx::sg::GL_viewer : bad gl_action end." << std::endl;
}
}
}
//after_render();
m_gl_mgr.end_render();
}
public:
GL_viewer(std::ostream& a_out,unsigned int a_width,unsigned int a_height)
:parent(a_out,a_width,a_height)
,m_gl_mgr(a_out)
{}
virtual ~GL_viewer(){
//WARNING : nodes may refer m_gl_mgr (to handle gstos/texs), then
// we have to delete them first.
m_sg.clear();
}
public:
GL_viewer(const GL_viewer& a_from)
:parent(a_from)
,m_gl_mgr(a_from.m_gl_mgr)
{}
GL_viewer& operator=(const GL_viewer& a_from){
parent::operator=(a_from);
m_gl_mgr = a_from.m_gl_mgr;
return *this;
}
protected:
GL_manager m_gl_mgr;
};
}}
#endif
+110
View File
@@ -0,0 +1,110 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_gl
#define toolx_sg_gl
#include "../OpenGL"
#include <tools/platform> //for APPLE TargetConditionals.h
#include <tools/img>
#include <ostream>
namespace toolx {
namespace sg {
//namespace gl : no, problem with g4tools.
inline void gl_clear_errors() {
GLenum glerror = ::glGetError();
while(glerror!=GL_NO_ERROR) {
glerror = ::glGetError();
}
}
inline bool gl_dump_if_errors(std::ostream& a_out,const std::string& a_head) {
bool retval = false;
GLenum glerror = ::glGetError();
if(glerror!=GL_NO_ERROR) {
a_out << a_head
<< " we have gl errors :"
<< std::endl;
retval = true;
}
while(glerror!=GL_NO_ERROR) {
//#define GL_NO_ERROR 0
//#define GL_INVALID_ENUM 0x0500
//#define GL_INVALID_VALUE 0x0501
//#define GL_INVALID_OPERATION 0x0502
//#define GL_STACK_OVERFLOW 0x0503
//#define GL_STACK_UNDERFLOW 0x0504
//#define GL_OUT_OF_MEMORY 0x0505
//#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
a_out << "0x" << std::hex << glerror << std::endl;
glerror = ::glGetError();
}
return retval;
}
inline void gl_dump_infos(std::ostream& a_out) {
std::string gl_version;
{const char* _sv = (const char*)::glGetString(GL_VERSION);
if(_sv) gl_version = _sv;}
std::string gl_vendor;
{const char* _sv = (const char*)::glGetString(GL_VENDOR);
if(_sv) gl_vendor = _sv;}
std::string gl_renderer;
{const char* _sv = (const char*)::glGetString(GL_RENDERER);
if(_sv) gl_renderer = _sv;}
std::string gl_extensions;
{const char* _sv = (const char*)::glGetString(GL_EXTENSIONS);
if(_sv) gl_extensions = _sv;}
GLint gl_texture_size;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_texture_size);
//GLint gl_buffer_size;
//::glGetIntegerv(GL_BUFFER_SIZE, &gl_buffer_size);
a_out << "toolx::sg::gl::dump_infos :" << std::endl;
a_out << " GL_VERSION " << gl_version << std::endl;
a_out << " GL_VENDOR " << gl_vendor << std::endl;
a_out << " GL_RENDERER " << gl_renderer << std::endl;
a_out << " GL_EXTENSIONS " << gl_extensions << std::endl;
a_out << " GL_MAX_TEXTURE_SIZE " << gl_texture_size << std::endl;
//a_out << " GL_BUFFER_SIZE " << gl_buffer_size << std::endl;
}
inline bool gl_tex_img(std::ostream& a_out,const tools::img_byte& a_img) {
if(a_img.bpp()==1) {
//to pass eiffel-tower.png
#if defined(ANDROID) || TARGET_OS_IPHONE
tools::img_byte res;
if(!a_img.bw2x(3,res)) {
a_out << "toolx::sg::gl::tex_img : toolx::img.bw2x() failed." << std::endl;
return false;
}
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,res.width(),res.height(),0,GL_RGB,GL_UNSIGNED_BYTE,res.buffer());
#else
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_LUMINANCE,GL_UNSIGNED_BYTE,a_img.buffer());
#endif
} else if(a_img.bpp()==3) {
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,a_img.width(),a_img.height(),0,GL_RGB,GL_UNSIGNED_BYTE,a_img.buffer());
} else if(a_img.bpp()==4) {
::glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,a_img.width(),a_img.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,a_img.buffer());
} else {
a_out << "toolx::sg::gl::tex_img : img.bpp() " << a_img.bpp() << " not treated." << std::endl;
return false;
}
return true;
}
}}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,264 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_sg_text_freetype_marker
#define toolx_sg_text_freetype_marker
#include "text_freetype"
namespace toolx {
namespace sg {
class text_freetype_marker : public text_freetype {
TOOLS_NODE(text_freetype_marker,toolx::sg::text_freetype_marker,text_freetype)
public:
virtual bool draw_in_frame_buffer() const {return true;}
virtual void render(tools::sg::render_action& a_action) {
{bool _color_touched = color_touched(a_action.state());
bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_color_touched||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
const tools::sg::state& state = a_action.state();
a_action.set_lighting(false); //Same logic as Inventor SoLightModel.model = BASE_COLOR.
a_action.set_depth_test(false);
if(m_wndg==wndg_ccw) a_action.set_winding(tools::sg::winding_ccw);
else if(m_wndg==wndg_cw) a_action.set_winding(tools::sg::winding_cw);
float x,y,z;
a_action.projected_origin(x,y,z);
float zz = 0;
a_action.load_matrices_to_identity();
{tools::mat4f _mtx;
_mtx.set_translate(x,y,zz);
if(!m_bitmaps.size()) {
if(state.m_ww) _mtx.mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
}
a_action.load_model_matrix(_mtx);}
///////////////////////////////////////////////////////////
/// lines /////////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t pos = item.first;
size_t num = item.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
a_action.draw_vertex_array_xy(tools::gl::line_strip(),num*2,data);
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t pos = item.second.first;
size_t num = item.second.second;
if(!num) continue;
//a_out << "toolx::sg::text_freetype_marker::render :"
// << " num points " << num
// << std::endl;
const float* data = tools::vec_data<float>(m_xys)+pos;
a_action.draw_vertex_array_xy((*it).first,num*2,data);
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
if(m_bitmaps.size()) {
#if defined(ANDROID) /*|| TARGET_OS_IPHONE*/
// we do not have transparent texture here (see also gl/tex_img() that does img/4-bytes => img/3-bytes) :
{tools::sg::state& _state = a_action.state();
tools::colorf old_color = _state.m_color;
_state.m_color = tools::colorf_white();
a_action.color4f(_state.m_color);
m_bitmaps.render(a_action);
_state.m_color = old_color;
a_action.color4f(_state.m_color);}
#else
m_bitmaps.render(a_action);
#endif
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
a_action.load_matrices_from_state();
a_action.set_depth_test(state.m_GL_DEPTH_TEST);
a_action.set_lighting(state.m_GL_LIGHTING);
a_action.set_winding(state.m_winding);
}
virtual void pick(tools::sg::pick_action& a_action) {
const tools::sg::state& state = a_action.state();
{bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
float x,y,z;
a_action.projected_origin(x,y,z);
float zz = 0;
a_action.set_matrices_to_identity();
a_action.model_matrix().set_translate(x,y,zz);
if(!m_bitmaps.size()) {
if(state.m_ww) a_action.model_matrix().mul_scale(float(state.m_wh)/float(state.m_ww),1,1);
}
///////////////////////////////////////////////////////////
/// lines /////////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t pos = item.first;
size_t num = item.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
float* vp = _trans2(num,data,x,y);
if(!vp) continue;
if(a_action.add__line_strip_xy(*this,2*num,vp,true)) {
delete [] vp;
a_action.set_matrices_from_state();
return;
}
delete [] vp;
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t pos = item.second.first;
size_t num = item.second.second;
if(!num) continue;
const float* data = tools::vec_data<float>(m_xys)+pos;
float* vp = _trans2(num,data,x,y);
if(!vp) continue;
if(a_action.add__primitive_xy(*this,item.first,2*num,vp,true)){
delete [] vp;
a_action.set_matrices_from_state();
return;
}
delete [] vp;
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
if(m_bitmaps.size()) {
m_bitmaps.pick(a_action);
}
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
a_action.set_matrices_from_state();
}
virtual void bbox(tools::sg::bbox_action& a_action) {
{bool _char_height_touched = char_height_touched(a_action.state());
if(touched()||_char_height_touched) {
update_sg(a_action.out(),font.touched(),a_action.state());
reset_touched();
}}
a_action.add_one_point(0,0,0);
/*
{tools_vforcit(line_t,m_lines,it) {
const line_t& item = *it;
size_t num = item.second;
const float* data = tools::vec_data<float>(m_xys)+item.first;
float px,py,pz;
float* pos = (float*)data;
for(size_t index=0;index<num;index++) {
px = *pos;pos++;
py = *pos;pos++;
pz = 0;
a_action.add_one_point(px,py,pz);
}
}}
///////////////////////////////////////////////////////////
/// triangles /////////////////////////////////////////////
///////////////////////////////////////////////////////////
{tools_vforcit(gl_triangle_t,m_triangles,it) {
const std::pair<GLUenum,triangle_t>& item = *it;
size_t num = item.second.second;
const float* data = tools::vec_data<float>(m_xys)+item.second.first;
float px,py,pz;
float* pos = (float*)data;
for(size_t index=0;index<num;index++) {
px = *pos;pos++;
py = *pos;pos++;
pz = 0;
a_action.add_one_point(px,py,pz);
}
}}
///////////////////////////////////////////////////////////
/// bitmap ////////////////////////////////////////////////
///////////////////////////////////////////////////////////
m_bitmaps.bbox(a_action);
*/
}
public:
text_freetype_marker():parent(){
height = 10; //pixels
}
virtual ~text_freetype_marker(){}
public:
text_freetype_marker(const text_freetype_marker& a_from):parent(a_from) {}
text_freetype_marker& operator=(const text_freetype_marker& a_from){parent::operator=(a_from);return *this;}
protected:
void update_sg(std::ostream& a_out,bool a_load_font,const tools::sg::state& a_state) {
if(!a_state.m_wh) {parent::update_sg(a_out,a_load_font);return;}
float sy = 2.0f*float(height.value())/float(a_state.m_wh); //in [-1,1]
float old_height = height.value();
height.value_no_cmp(sy);
//update_what what = lines;
//if(modeling==tools::sg::font_filled) what = faces_and_lines;
parent::update_sg(a_out,a_load_font);
height.value_no_cmp(old_height);
}
float* _trans2(size_t a_num,const float* a_data,float a_x,float a_y) {
float* vp = new float[a_num*2];
if(!vp) return 0;
float* pos = vp;
float* pda = (float*)a_data;
for(size_t index=0;index<a_num;index++){
*pos = *pda + a_x;pos++;pda++;
*pos = *pda + a_y;pos++;pda++;
}
return vp;
}
};
}}
#endif
+578
View File
@@ -0,0 +1,578 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_xml_loader
#define toolx_xml_loader
#include <tools/xml/tree>
#include <tools/file>
#include <tools/mnmx>
#include <cstdio>
#include <cctype> //iscntrl
#include <expat.h>
#ifdef TOOLS_MEM
#include <tools/mem>
namespace toolx {
extern "C" {
inline void* xml_malloc(size_t a_size){
tools::mem::increment(tools::s_malloc().c_str());
return ::malloc(a_size);
}
inline void* xml_realloc(void* a_ptr,size_t a_size){
if(a_ptr==NULL) tools::mem::increment(tools::s_malloc().c_str());
return ::realloc(a_ptr,a_size);
}
inline void xml_free(void* a_ptr){
if(a_ptr!=NULL) tools::mem::decrement(tools::s_malloc().c_str());
::free(a_ptr);
}
}}
#endif
namespace toolx {
namespace xml {
class loader {
#ifdef TOOLS_MEM
TOOLS_SCLASS(toolx::xml::loader)
#endif
public:
loader(tools::xml::factory& a_factory,
std::ostream& a_out,bool a_verbose = false)
:m_factory(a_factory)
,m_out(a_out)
,m_verbose(a_verbose)
,m_take_cntrl(false)
,m_errors(0)
,m_top(0) // Used to cleanup in case XML parsing failed.
,m_current(0)
,m_compressed_reader(0)
,m_depth(0)
,m_abort(false)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
virtual ~loader(){
delete m_compressed_reader;
clear();
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
loader(const loader& a_from)
:m_factory(a_from.m_factory)
,m_out(a_from.m_out)
,m_verbose(a_from.m_verbose)
,m_take_cntrl(a_from.m_take_cntrl)
,m_errors(0)
,m_top(0) // Used to cleanup in case XML parsing failed.
,m_current(0)
,m_compressed_reader(0)
,m_depth(0)
,m_abort(false)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
loader& operator=(const loader& a_from){
if(&a_from==this) return *this;
m_verbose = a_from.m_verbose;
m_take_cntrl = a_from.m_take_cntrl;
m_errors = 0;
m_top = 0;
m_current = 0;
m_compressed_reader = 0;
m_depth = 0;
m_abort = false;
return *this;
}
public:
virtual bool visit_end_element(tools::xml::tree&,bool& a_keep) {
a_keep = true;
return true;
}
public:
void set_take_cntrl_chars(bool a_value) {m_take_cntrl = a_value;}
std::ostream& out() const {return m_out;}
void set_compressed_reader(tools::file::reader* aReader){
delete m_compressed_reader;
m_compressed_reader = aReader; //take ownership.
}
unsigned int errors() const {return m_errors;}
void set_tags(const std::vector<std::string>& a_tags){m_tags=a_tags;}
void add_tag(const std::string& a_tag){m_tags.push_back(a_tag);}
bool load_file(const std::string& a_file,bool a_compressed) {
clear();
if(!parse_file(a_file,
(XML_StartElementHandler)start_element,
(XML_EndElementHandler)end_element,
this,a_compressed)) {
clear();
return false;
}
if(m_current) m_current->set_file(a_file);
return true;
}
bool load_string(const std::string& a_string){
clear();
if(!parse_buffer(a_string.size(),a_string.c_str(),
(XML_StartElementHandler)start_element,
(XML_EndElementHandler)end_element,
this)) {
clear();
return false;
}
return true;
}
bool load_buffer(size_t aSize,const char* aBuffer){
clear();
if(!parse_buffer(aSize,aBuffer,
(XML_StartElementHandler)start_element,
(XML_EndElementHandler)end_element,
this)) {
clear();
return false;
}
return true;
}
const tools::xml::tree* top_item() const {return m_current;}
tools::xml::tree* top_item(){return m_current;}
void empty(){m_top = 0;m_current = 0;}
bool is_tag(const std::string& a_string) const {
size_t number = m_tags.size();
for(size_t index=0;index<number;index++) {
if(a_string==m_tags[index]) return true;
}
return false;
}
protected:
void clear(){
// In case of problem, deleting m_current is not sufficient.
delete m_top;
m_top = 0;
m_current = 0;
}
bool parse_buffer(size_t aSize,const char* aBuffer,
XML_StartElementHandler a_start,XML_EndElementHandler a_end,
void* a_tag){
m_errors = 0;
if(!aSize) return true; //nothing to do.
m_depth = 0;
m_abort = false;
#ifdef TOOLS_MEM
XML_Memory_Handling_Suite mem;
mem.malloc_fcn = xml_malloc;
mem.realloc_fcn = xml_realloc;
mem.free_fcn = xml_free;
XML_Parser _parser = XML_ParserCreate_MM(NULL,&mem,NULL);
#else
XML_Parser _parser = XML_ParserCreate(NULL);
#endif
XML_SetUserData(_parser,a_tag);
XML_SetElementHandler(_parser,a_start,a_end);
XML_SetCharacterDataHandler(_parser,(XML_CharacterDataHandler)character_data_handler);
//XML_SetProcessingInstructionHandler(_parser,processingInstructionHandler);
char* buf = (char*)aBuffer;
size_t l = aSize;
int done = 0;
do {
size_t len = tools::mn<size_t>(l,BUFSIZ); //BUFSIZ in cstdio
done = len < BUFSIZ ? 1 : 0;
if(XML_Parse(_parser, buf, (int)len, done)==XML_STATUS_ERROR) {
m_out << "parse_buffer :"
<< " " << XML_ErrorString(XML_GetErrorCode(_parser))
<< " at line " << (int)XML_GetCurrentLineNumber(_parser)
<< " at byte index " << (int)XML_GetCurrentByteIndex(_parser)
<< std::endl;
{XML_Index pos = XML_GetCurrentByteIndex(_parser);
XML_Index pmn = tools::mx<XML_Index>(pos-10,0);
XML_Index pmx = tools::mn<XML_Index>(pos+10,XML_Index(aSize)-1);
std::string c = " ";
{for(XML_Index p=pmn;p<=pmx;p++) {c[0] = *(aBuffer+p);m_out << c;}
m_out << std::endl;}
{for(XML_Index p=pmn;p<pos;p++) m_out << " ";
m_out << "^" << std::endl;}}
XML_ParserFree(_parser);
return false;
}
if(m_abort) {
XML_ParserFree(_parser);
return false;
}
buf += len;
l -= len;
} while (!done);
XML_ParserFree(_parser);
return true;
}
bool parse_file(const std::string& a_file,
XML_StartElementHandler a_start,XML_EndElementHandler a_end,
void* a_tag,bool a_compressed){
if(m_verbose) {
m_out << "parse_file :"
<< " parse file " << tools::sout(a_file) << "..." << std::endl;
}
m_errors = 0;
bool use_zlib = false;
if(a_compressed) {
if(m_verbose) {
m_out << "parse_file :"
<< " uncompress requested for file "
<< tools::sout(a_file) << "."
<< std::endl;
}
use_zlib = true;
} else {
// may be compressed anyway :
bool compressed;
if(!tools::file::is_gzip(a_file,compressed)) {
m_out << "parse_file :"
<< " tools::file::is_gzip() failed for " << a_file << "."
<< std::endl;
return false;
}
if(compressed) use_zlib = true;
}
tools::file::reader* freader = 0;
bool delete_freader = false;
if(use_zlib) {
if(!m_compressed_reader) {
m_out << "parse_file :"
<< " no compressed reader given."
<< std::endl;
return false;
}
freader = m_compressed_reader;
} else {
freader = new tools::FILE_reader();
delete_freader = true;
}
if(!freader->open(a_file)) {
m_out << "parse_file :"
<< " can't open file " << a_file << std::endl;
if(delete_freader) delete freader;
return false;
}
m_depth = 0;
m_abort = false;
#ifdef TOOLS_MEM
XML_Memory_Handling_Suite mem;
mem.malloc_fcn = xml_malloc;
mem.realloc_fcn = xml_realloc;
mem.free_fcn = xml_free;
XML_Parser _parser = XML_ParserCreate_MM(NULL,&mem,NULL);
#else
XML_Parser _parser = XML_ParserCreate(NULL);
#endif
XML_SetUserData(_parser,a_tag);
XML_SetElementHandler(_parser,a_start,a_end);
XML_SetCharacterDataHandler(_parser,(XML_CharacterDataHandler)character_data_handler);
//XML_SetProcessingInstructionHandler(_parser,
// processingInstructionHandler);
//char buf[1024 * BUFSIZ];
char buf[BUFSIZ];
int done = 0;
do {
size_t len;
if(!freader->read(buf,sizeof(buf),len)) {
XML_ParserFree(_parser);
freader->close();
if(delete_freader) delete freader;
return false;
}
done = len < sizeof(buf) ? 1 : 0;
if(XML_Parse(_parser, buf, (int)len, done)==XML_STATUS_ERROR) {
m_out << "parse_file :"
<< " in file " << tools::sout(a_file)
<< " " << XML_ErrorString(XML_GetErrorCode(_parser))
<< " at line " << (int)XML_GetCurrentLineNumber(_parser)
<< std::endl;
XML_ParserFree(_parser);
freader->close();
if(delete_freader) delete freader;
return false;
}
if(m_abort) {
XML_ParserFree(_parser);
freader->close();
if(delete_freader) delete freader;
return false;
}
} while (!done);
XML_ParserFree(_parser);
freader->close();
if(m_verbose) {
m_out << "parse_file :"
<< " parse file " << tools::sout(a_file) << " done." << std::endl;
}
if(delete_freader) delete freader;
return true;
}
protected:
static void character_data_handler(void* aUserData,const XML_Char* a_string,int aLength){
loader* This = (loader*)aUserData;
std::string _s;
_s.resize(aLength);
size_t count = 0;
char* p = (char*)a_string;
for (int i = 0; i < aLength; i++, p++) {
if(This->m_take_cntrl || (!iscntrl(*p))) {
_s[count] = *p;
count++;
}
}
if(count) {
_s.resize(count);
This->m_value += _s;
}
}
static void start_element(void* aUserData,const XML_Char* a_name,const XML_Char** a_atbs){
loader* This = (loader*)aUserData;
if(This->m_abort) return; //Do nothing.
This->m_depth++;
This->m_value = "";
std::string name = a_name; //Can't be empty
if(This->is_tag(name)) {
if(!This->m_current) {
if(This->m_depth==1) {
// Ok. Head.
} else {
This->m_out << "start_element :"
<< " no tag with a depth of " << This->m_depth
<< std::endl;
This->m_abort = true;
return;
}
} else {
int delta = This->m_current->depth() - This->m_depth;
if(delta>=1) {
This->m_out << "start_element :"
<< " for element " << tools::sout(name)
<< " tag with a delta depth of " << delta
<< std::endl;
This->m_abort = true;
return;
}
}
std::vector<tools::xml::tree::atb> atbs;
{const XML_Char** a_atts = a_atbs;
while((*a_atts)&&(*(a_atts+1))) {
atbs.push_back(tools::xml::tree::atb(*a_atts,*(a_atts+1)));
a_atts+=2;
}}
tools::xml::tree* parent = This->m_current;
tools::xml::tree* _tree = This->m_factory.create(name,atbs,parent);
if(!_tree) {
This->m_out << "start_element :"
<< " can't create a tree for tag " << tools::sout(name)
<< std::endl;
This->m_abort = true;
return;
}
//out << "start_element :" << std::endl;
//_tree->print_xml(*(This->m_printer),"debug : ");
if(parent) parent->add_child(_tree);
/*
if(This->m_current && !This->m_current->parent()) {
This->m_out << "start_element :"
<< " warning : current tree without parent."
<< " Potential mem leak."
<< std::endl;
}
*/
This->m_current = _tree;
_tree->set_depth(This->m_depth); // Internal only.
if(!This->m_top) This->m_top = _tree;
} else {
if(!This->m_current) {
// Can't be in a non-tag without a tag !
This->m_out << "start_element :"
<< " for element " << tools::sout(name)
<< " non-tag without some parent tag."
<< std::endl;
This->m_abort = true;
return;
} else {
int delta = This->m_depth - This->m_current->depth();
if(delta>1) {
This->m_out << "start_element :"
<< " for element " << tools::sout(name)
<< " grand child of a tag."
<< std::endl;
This->m_abort = true;
return;
} else if(delta==1) { //ok
This->m_atbs.clear();
{const XML_Char** a_atts = a_atbs;
while((*a_atts)&&(*(a_atts+1))) {
This->m_atbs.push_back(tools::xml::tree::atb(*a_atts,*(a_atts+1)));
a_atts+=2;
}}
} else {
This->m_out << "start_element :"
<< " for element " << tools::sout(name)
<< " non-tag with a delta depth of " << delta
<< std::endl;
This->m_abort = true;
return;
}
}
}
}
static void end_element(void* aUserData,const XML_Char* a_name){
loader* This = (loader*)aUserData;
if(This->m_abort) return; //Do nothing.
if(This->m_current) {
tools::xml::tree* tr = This->m_current;
int delta = This->m_depth - tr->depth();
if(delta==0) { //Back to a tag :
tools::xml::tree* parent = tr->parent();
bool keep = false;
bool cont = This->visit_end_element(*tr,keep);
if(keep) {
if(parent) {
/*
if(!This->m_current->parent()) {
This->m_out << "end_element :"
<< " warning : current tree without parent (1)."
<< " Potential mem leak."
<< std::endl;
}
*/
This->m_current = parent;
}
} else {
//FIXME : the top could be recreated !
if(This->m_top==tr) This->m_top = 0;
if(parent) {
parent->remove_child(tr); //delete the tr
} else {
delete tr;
}
/*
if(!This->m_current->parent()) {
This->m_out << "end_element :"
<< " warning : current tree without parent (2)."
<< " Potential mem leak."
<< std::endl;
}
*/
This->m_current = parent; //parent could be 0 : ok.
}
if(!cont) This->m_abort = true;
} else if(delta==1) { //Back to a child of tag :
//FIXME : correct m_value ? (Can we pick the one of a sub item ?)
tr->add_element(std::string(a_name),This->m_atbs,This->m_value);
//This->m_value = "";
} else {
This->m_out << "end_element :"
<< " problem for element " << tools::sout(std::string(a_name))
<< " : delta depth of " << delta
<< std::endl;
This->m_abort = true;
}
}
This->m_depth--;
}
protected:
tools::xml::factory& m_factory;
std::ostream& m_out;
protected:
bool m_verbose;
bool m_take_cntrl;
unsigned int m_errors;
std::vector<std::string> m_tags;
tools::xml::tree* m_top;
tools::xml::tree* m_current;
//std::vector<tools::xml::tree::atb> m_atbs;
std::vector< std::pair<std::string,std::string> > m_atbs;
std::string m_value;
tools::file::reader* m_compressed_reader;
unsigned int m_depth;
bool m_abort;
};
}}
#endif
+44
View File
@@ -0,0 +1,44 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_xml_style
#define toolx_xml_style
#include <tools/xml/styles>
#include "loader"
namespace toolx {
namespace xml {
inline bool load_style_file(std::ostream&,const std::string& a_file,tools::xml::styles& a_styles) {
tools::xml::default_factory factory;
toolx::xml::loader ml(factory,a_styles.out(),false);
std::vector<std::string> tags;
tags.push_back("styles");
tags.push_back("style");
tags.push_back("plotter_style");
ml.set_tags(tags);
if(!ml.load_file(a_file,false)) return false;
tools::xml::tree* top = ml.top_item();
if(!top) return true; //File could be empty.
return scan_style_tree(a_styles,*top);
}
inline bool load_style_string(tools::xml::styles& a_styles,const std::string& a_string) {
tools::xml::default_factory factory;
toolx::xml::loader ml(factory,a_styles.out(),false);
std::vector<std::string> tags;
tags.push_back("styles");
tags.push_back("style");
tags.push_back("plotter_style");
ml.set_tags(tags);
if(!ml.load_string(a_string)) return false;
tools::xml::tree* top = ml.top_item();
if(!top) return true;
return scan_style_tree(a_styles,*top);
}
}}
#endif
+230
View File
@@ -0,0 +1,230 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef toolx_zlib
#define toolx_zlib
// what is needed for root file compression with zlib.
//NOTE : zlib contains deflate/inflate and also the gz functions to write/read a .gz file.
// The gz functions use also deflate/inflate.
#include <zlib.h>
#include <ostream>
namespace toolx {
inline bool compress_buffer(std::ostream& a_out,
unsigned int a_level,
unsigned int a_srcsize,const char* a_src,
unsigned int a_tgtsize,char* a_tgt,
unsigned int& a_irep) {
z_stream stream; // decompression stream
stream.next_in = (Bytef*)(a_src);
stream.avail_in = (uInt)(a_srcsize);
stream.next_out = (Bytef*)a_tgt;
stream.avail_out = (uInt)(a_tgtsize);
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
stream.total_in = 0; /*to quiet Coverity.*/
stream.total_out = 0; /*to quiet Coverity.*/
int err = deflateInit(&stream,a_level);
if(err!=Z_OK) {
a_out << "toolx::compress_buffer :"
<< " error in zlib/deflateInit." << std::endl;
a_irep = 0;
return false;
}
err = deflate(&stream, Z_FINISH);
if(err!=Z_STREAM_END) {
deflateEnd(&stream);
a_out << "toolx::compress_buffer :"
<< " error in zlib/deflate." << std::endl;
a_irep = 0;
return false;
}
deflateEnd(&stream);
//a_out << "toolx::compress_buffer : ok "
// << stream.total_out << std::endl;
a_irep = stream.total_out;
return true;
}
inline bool decompress_buffer(std::ostream& a_out,
unsigned int a_srcsize,const char* a_src,
unsigned int a_tgtsize,char* a_tgt,
unsigned int& a_irep) {
z_stream stream; // decompression stream
stream.next_in = (Bytef*)(a_src);
stream.avail_in = (uInt)(a_srcsize);
stream.next_out = (Bytef*)a_tgt;
stream.avail_out = (uInt)(a_tgtsize);
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
stream.total_in = 0; /*to quiet Coverity.*/
stream.total_out = 0; /*to quiet Coverity.*/
int err = inflateInit(&stream);
if (err != Z_OK) {
a_out << "toolx::decompress_buffer :"
<< " error " << err << " in zlib/inflateInit." << std::endl;
return false;
}
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
a_out << "toolx::decompress_buffer :"
<< " error " << err << " in zlib/inflate." << std::endl;
return false;
}
inflateEnd(&stream);
//a_out << "toolx::decompress_buffer : zlib : ok "
// << stream.total_out << std::endl;
a_irep = stream.total_out;
return true;
}
}
#if ZLIB_VERNUM <= 0x1140
#include <cstdio>
#endif
namespace toolx {
#if ZLIB_VERNUM <= 0x1140
inline int gunzip_get_byte(char*& a_buffer) {
int c = *a_buffer;a_buffer++;
return c;
}
inline int gunzip_check_header(char*& a_buffer) {
#define TOOLX_ZLIB_HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define TOOLX_ZLIB_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define TOOLX_ZLIB_ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define TOOLX_ZLIB_COMMENT 0x10 /* bit 4 set: file comment present */
#define TOOLX_ZLIB_RESERVED 0xE0 /* bits 5..7: reserved */
uInt len;
int c;
/* Check the gzip magic header */
for (len = 0; len < 2; len++) {
c = gunzip_get_byte(a_buffer);
/*
if (c != gz_magic[len]) {
if (len != 0) s->stream.avail_in++, s->stream.next_in--;
if (c != EOF) {
s->stream.avail_in++, s->stream.next_in--;
s->transparent = 1;
}
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
return;
}
*/
}
int method = gunzip_get_byte(a_buffer);
int flags = gunzip_get_byte(a_buffer);
if (method != Z_DEFLATED || (flags & TOOLX_ZLIB_RESERVED) != 0) {
return Z_DATA_ERROR;
}
/* Discard time, xflags and OS code: */
for (len = 0; len < 6; len++) (void)gunzip_get_byte(a_buffer);
if ((flags & TOOLX_ZLIB_EXTRA_FIELD) != 0) { /* skip the extra field */
len = (uInt)gunzip_get_byte(a_buffer);
len += ((uInt)gunzip_get_byte(a_buffer))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && gunzip_get_byte(a_buffer) != EOF) ;
}
if ((flags & TOOLX_ZLIB_ORIG_NAME) != 0) { /* skip the original file name */
while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ;
}
if ((flags & TOOLX_ZLIB_COMMENT) != 0) { /* skip the .gz file comment */
while ((c = gunzip_get_byte(a_buffer)) != 0 && c != EOF) ;
}
if ((flags & TOOLX_ZLIB_HEAD_CRC) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) (void)gunzip_get_byte(a_buffer);
}
//s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
return Z_OK;
#undef TOOLX_ZLIB_HEAD_CRC
#undef TOOLX_ZLIB_EXTRA_FIELD
#undef TOOLX_ZLIB_ORIG_NAME
#undef TOOLX_ZLIB_COMMENT
#undef TOOLX_ZLIB_RESERVED
}
#endif //ZLIB_VERNUM <= 0x1140
inline bool gunzip_buffer(std::ostream& a_out,
unsigned int a_srcsize,const char* a_src,
unsigned int a_tgtsize,char* a_tgt,
unsigned int& a_irep) {
z_stream stream; // decompression stream
#if ZLIB_VERNUM <= 0x1140
char* pos = (char*)a_src;
if(gunzip_check_header(pos)!=Z_OK) return false;
stream.next_in = (Bytef*)pos;
stream.avail_in = (uInt)(a_srcsize-(pos-a_src));
#else
stream.next_in = (Bytef*)a_src;
stream.avail_in = (uInt)a_srcsize;
#endif //ZLIB_VERNUM
stream.next_out = (Bytef*)a_tgt;
stream.avail_out = (uInt)a_tgtsize;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
#if ZLIB_VERNUM <= 0x1140
int err = inflateInit2(&stream,-MAX_WBITS);
#else
int err = inflateInit2(&stream,MAX_WBITS+16);
#endif
if (err != Z_OK) {
a_out << "toolx::gunzip_buffer :"
<< " error " << err << " in zlib/inflateInit2." << std::endl;
return false;
}
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
a_out << "toolx::gunzip_buffer :"
<< " error " << err << " in zlib/inflate." << std::endl;
return false;
}
inflateEnd(&stream);
a_irep = stream.total_out;
return true;
}
}
#endif