// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_X11_session #define tools_X11_session #include "base_session" #include namespace tools { 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 << "tools::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(!initialize_gl()) {} //throw } virtual ~session() { finalize_gl(); //std::cout << "debug : ~session" << std::endl; } public: session(const session& a_from) :parent(a_from) ,m_vinfo(0) ,m_ctx(0) ,m_colormap(0) { if(!initialize_gl()) {} //throw } session& operator=(const session& a_from){ if(&a_from==this) return *this; parent::operator=(a_from); finalize_gl(); if(!initialize_gl()) {} //throw return *this; } protected: bool initialize_gl() { if(!m_display) { m_display = 0; m_vinfo = 0; m_ctx = 0; return false; } {int glxMajor, glxMinor; ::glXQueryVersion(m_display,&glxMajor,&glxMinor); if(glxMajor<=0) { m_out << "tools::X11::session::initialize : bad GLX-Version " << glxMajor << "." << glxMinor << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return false; }} 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 << "tools::X11::session::initialize :" // << " can't get a visual with alpha on screen " << m_monitor << ". Try without alpha..." // << std::endl; //m_out << "tools::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 << "tools::X11::session::initialize :" << " can't choose a visual on screen " << m_monitor << "." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return false; } } m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_TRUE); if(!m_ctx) { m_out << "tools::X11::session::initialize :" << " 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 << "tools::X11::session::initialize :" << " can't create a glX context." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return false; } //} else { //m_out << "tools::X11::session::initialize :" // << " 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 << "tools::X11::session::initialize : XCreateColormap failed." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return false; } return true; } void finalize_gl() { if(!m_display) return; if(m_ctx) { ::glXDestroyContext(m_display,m_ctx); m_ctx = 0; } if(m_vinfo) { ::XFree(m_vinfo); m_vinfo = 0; } if(m_colormap) { ::XFreeColormap(m_display,m_colormap); m_colormap = 0; } } 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 << "tools::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