Files
2025-12-05 08:54:02 +01:00

181 lines
4.6 KiB
Plaintext

// 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:
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) {
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;
}
}
// 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);
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;
}
}
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