*
**************************************************************************/
-#include "glimports.hpp"
+#include <stdlib.h>
+#include <iostream>
+
#include "glws.hpp"
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+
namespace glws {
+static Display *display = NULL;
+static int screen = 0;
+
+
class GlxVisual : public Visual
{
public:
};
+static void describeEvent(const XEvent &event) {
+ if (0) {
+ switch (event.type) {
+ case ConfigureNotify:
+ std::cerr << "ConfigureNotify";
+ break;
+ case Expose:
+ std::cerr << "Expose";
+ break;
+ case KeyPress:
+ std::cerr << "KeyPress";
+ break;
+ case MapNotify:
+ std::cerr << "MapNotify";
+ break;
+ case ReparentNotify:
+ std::cerr << "ReparentNotify";
+ break;
+ default:
+ std::cerr << "Event " << event.type;
+ }
+ std::cerr << " " << event.xany.window << "\n";
+ }
+}
+
+static void waitForEvent(Window window, int type) {
+ XFlush(display);
+ XEvent event;
+ do {
+ XNextEvent(display, &event);
+ describeEvent(event);
+ } while (event.type != type ||
+ event.xany.window != window);
+}
+
+
class GlxDrawable : public Drawable
{
public:
- Display *display;
Window window;
- GlxDrawable(const Visual *vis, Display *dpy, Window win) :
- Drawable(vis),
- display(dpy),
- window(win)
- {}
+ GlxDrawable(const Visual *vis, int w, int h) :
+ Drawable(vis, w, h)
+ {
+ XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
+
+ Window root = RootWindow(display, screen);
+
+ /* window attributes */
+ XSetWindowAttributes attr;
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+
+ unsigned long mask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ int x = 0, y = 0;
+
+ window = XCreateWindow(
+ display, root,
+ x, y, width, height,
+ 0,
+ visinfo->depth,
+ InputOutput,
+ visinfo->visual,
+ mask,
+ &attr);
+
+ XSizeHints sizehints;
+ sizehints.x = x;
+ sizehints.y = y;
+ sizehints.width = width;
+ sizehints.height = height;
+ sizehints.flags = USSize | USPosition;
+ XSetNormalHints(display, window, &sizehints);
+
+ const char *name = "glretrace";
+ XSetStandardProperties(
+ display, window, name, name,
+ None, (char **)NULL, 0, &sizehints);
+
+ glXWaitX();
+ }
~GlxDrawable() {
XDestroyWindow(display, window);
}
-
+
void
- resize(unsigned w, unsigned h) {
+ resize(int w, int h) {
+ glXWaitGL();
+
+ // We need to ensure that pending events are processed here, and XSync
+ // with discard = True guarantees that, but it appears the limited
+ // event processing we do so far is sufficient
+ //XSync(display, True);
+
Drawable::resize(w, h);
+
XResizeWindow(display, window, w, h);
+
+ // Tell the window manager to respect the requested size
+ XSizeHints *size_hints;
+ size_hints = XAllocSizeHints();
+ size_hints->max_width = size_hints->min_width = w;
+ size_hints->max_height = size_hints->min_height = h;
+ size_hints->flags = PMinSize | PMaxSize;
+ XSetWMNormalHints(display, window, size_hints);
+ XFree(size_hints);
+
+ waitForEvent(window, ConfigureNotify);
+
+ glXWaitX();
+ }
+
+ void show(void) {
+ if (!visible) {
+ XMapWindow(display, window);
+
+ waitForEvent(window, Expose);
+
+ Drawable::show();
+ }
}
void swapBuffers(void) {
class GlxContext : public Context
{
public:
- Display *display;
GLXContext context;
-
- GlxContext(const Visual *vis, Display *dpy, GLXContext ctx) :
+
+ GlxContext(const Visual *vis, GLXContext ctx) :
Context(vis),
- display(dpy),
context(ctx)
{}
class GlxWindowSystem : public WindowSystem
{
-private:
- Display *display;
- int screen;
-
public:
GlxWindowSystem() {
- display = XOpenDisplay(NULL);
- screen = DefaultScreen(display);
+ if (!display) {
+ display = XOpenDisplay(NULL);
+ if (!display) {
+ std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
+ exit(1);
+ }
+ screen = DefaultScreen(display);
+ }
}
~GlxWindowSystem() {
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_STENCIL_SIZE, 1,
None
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
GLX_STENCIL_SIZE, 1,
};
XVisualInfo *visinfo;
-
+
visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
return new GlxVisual(visinfo);
}
-
+
Drawable *
- createDrawable(const Visual *visual)
+ createDrawable(const Visual *visual, int width, int height)
{
- XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
-
- Window root = RootWindow(display, screen);
-
- /* window attributes */
- XSetWindowAttributes attr;
- attr.background_pixel = 0;
- attr.border_pixel = 0;
- attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
- attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
-
- unsigned long mask;
- mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
-
- int x = 0, y = 0, width = 256, height = 256;
-
- Window window = XCreateWindow(
- display, root,
- x, y, width, height,
- 0,
- visinfo->depth,
- InputOutput,
- visinfo->visual,
- mask,
- &attr);
-
- XSizeHints sizehints;
- sizehints.x = x;
- sizehints.y = y;
- sizehints.width = width;
- sizehints.height = height;
- sizehints.flags = USSize | USPosition;
- XSetNormalHints(display, window, &sizehints);
-
- const char *name = "glretrace";
- XSetStandardProperties(
- display, window, name, name,
- None, (char **)NULL, 0, &sizehints);
-
- XMapWindow(display, window);
-
- return new GlxDrawable(visual, display, window);
+ return new GlxDrawable(visual, width, height);
}
Context *
- createContext(const Visual *visual)
+ createContext(const Visual *visual, Context *shareContext)
{
XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
- GLXContext context = glXCreateContext(display, visinfo, NULL, True);
- return new GlxContext(visual, display, context);
+ GLXContext share_context = NULL;
+ GLXContext context;
+
+ if (shareContext) {
+ share_context = dynamic_cast<GlxContext*>(shareContext)->context;
+ }
+
+ context = glXCreateContext(display, visinfo,
+ share_context, True);
+ return new GlxContext(visual, context);
}
bool
makeCurrent(Drawable *drawable, Context *context)
{
if (!drawable || !context) {
- return glXMakeCurrent(display, NULL, NULL);
+ return glXMakeCurrent(display, None, NULL);
} else {
GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
bool
processEvents(void) {
+ XFlush(display);
while (XPending(display) > 0) {
XEvent event;
XNextEvent(display, &event);
- // TODO
+ describeEvent(event);
}
return true;
}