ultimatepp/uppsrc/GLCtrl/XGLCtrl.cpp

158 lines
3.1 KiB
C++

#include "GLCtrl.h"
#ifdef PLATFORM_POSIX
#include <GL/glx.h>
#include <GL/gl.h>
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#define Status int
#ifdef GUI_GTK
#include <gdk/gdkx.h>
#endif
#undef Time
#undef Font
#undef Display
#undef Picture
#undef Status
namespace Upp {
static XVisualInfo *s_XVisualInfo;
static Colormap s_Colormap;
static GLXContext s_GLXContext;
static ::XDisplay *s_Display;
void GLCtrl::Create()
{
MemoryIgnoreLeaksBlock __;
Ctrl *top = GetTopCtrl();
if(!top)
return;
#ifdef GUI_GTK
GdkWindow *gdk = top->gdk();
if(!gdk)
return;
Window w = gdk_x11_window_get_xid(gdk);
#else
Window w = top->GetWindow();
#endif
ONCELOCK {
#ifdef GUI_GTK
s_Display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
#else
s_Display = Xdisplay;
#endif
int samples = numberOfSamples;
do {
Vector<int> attr;
attr << GLX_RGBA << GLX_DEPTH_SIZE << depthSize
<< GLX_STENCIL_SIZE << stencilSize;
if(doubleBuffering)
attr << GLX_DOUBLEBUFFER;
if(samples > 1)
attr << GLX_SAMPLE_BUFFERS_ARB << 1 << GLX_SAMPLES_ARB << samples;
attr << 0;
samples >>= 1;
s_XVisualInfo = glXChooseVisual(s_Display, DefaultScreen(s_Display), attr);
}
while(!s_XVisualInfo && samples > 0);
if(!s_XVisualInfo)
return;
s_Colormap = XCreateColormap(s_Display, RootWindow(s_Display, s_XVisualInfo->screen), s_XVisualInfo->visual, AllocNone);
s_GLXContext = glXCreateContext(s_Display, s_XVisualInfo, NULL, GL_TRUE);
}
if(!s_GLXContext)
return;
XSetWindowAttributes swa;
swa.colormap = s_Colormap;
swa.border_pixel = 0;
swa.event_mask = 0;
win = XCreateWindow(s_Display, w, 0, 0, 1, 1, 0,
s_XVisualInfo->depth, InputOutput, s_XVisualInfo->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);
visible = false;
position = Null;
}
void GLCtrl::Sync()
{
MemoryIgnoreLeaksBlock __;
if(win) {
Rect r = GetScreenView() - GetTopCtrl()->GetScreenRect().TopLeft();
bool b = IsVisible() && r.GetWidth() > 0 && r.GetHeight() > 0;
if(b != visible) {
visible = b;
position = Null;
if(b)
XMapWindow(s_Display, win);
else
XUnmapWindow(s_Display, win);
}
if(r != position && visible) {
position = r;
XMoveResizeWindow(s_Display, win, r.left, r.top, r.Width(), r.Height());
}
}
}
void GLCtrl::State(int reason)
{
switch(reason) {
case CLOSE:
XDestroyWindow(s_Display, win);
break;
case OPEN:
Create();
default:
Sync();
break;
}
}
void GLCtrl::ExecuteGL(Event<> paint, bool swap_buffers)
{
MemoryIgnoreLeaksBlock __;
glXMakeCurrent(s_Display, win, s_GLXContext);
ONCELOCK {
glewInit();
}
paint();
if(swap_buffers)
glXSwapBuffers(s_Display, win);
else
glFlush();
glXMakeCurrent(s_Display, None, NULL);
}
void GLCtrl::Paint(Draw& w)
{
Size sz = GetSize();
if(!s_GLXContext || sz.cx == 0 || sz.cy == 0)
return;
ExecuteGL([&] { DoGLPaint(); }, doubleBuffering);
}
}
#endif