X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glws_glx.cpp;h=3c49de81309dd25983da7a3eca51efee5d14f3a1;hb=9b42f061b37a00a0bcd314a830924803a956e17d;hp=efc11c4362fc7c7a72bc4915ddfde5346db30862;hpb=53d224eb79529d0c0f45fa4f68251822c9c7bb6a;p=apitrace diff --git a/glws_glx.cpp b/glws_glx.cpp index efc11c4..3c49de8 100644 --- a/glws_glx.cpp +++ b/glws_glx.cpp @@ -23,12 +23,15 @@ * **************************************************************************/ +#include #include + #include -#include "glimports.hpp" #include "glws.hpp" +#include "glproc.hpp" + namespace glws { @@ -36,18 +39,25 @@ namespace glws { static Display *display = NULL; static int screen = 0; +static unsigned glxVersion = 0; +static const char *extensions = 0; +static bool has_GLX_ARB_create_context = false; + class GlxVisual : public Visual { public: + GLXFBConfig fbconfig; XVisualInfo *visinfo; - GlxVisual(XVisualInfo *vi) : - visinfo(vi) + GlxVisual() : + fbconfig(0), + visinfo(0) {} ~GlxVisual() { XFree(visinfo); + XFree(fbconfig); } }; @@ -77,17 +87,6 @@ static void describeEvent(const XEvent &event) { } } -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: @@ -105,7 +104,7 @@ public: attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + attr.event_mask = StructureNotifyMask; unsigned long mask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; @@ -135,18 +134,27 @@ public: display, window, name, name, None, (char **)NULL, 0, &sizehints); - XMapWindow(display, window); - - waitForEvent(window, Expose); glXWaitX(); } + void waitForEvent(int type) { + XEvent event; + do { + XWindowEvent(display, window, StructureNotifyMask, &event); + describeEvent(event); + } while (event.type != type); + } + ~GlxDrawable() { XDestroyWindow(display, window); } void resize(int w, int h) { + if (w == width && h == height) { + return; + } + glXWaitGL(); // We need to ensure that pending events are processed here, and XSync @@ -158,11 +166,34 @@ public: XResizeWindow(display, window, w, h); - waitForEvent(window, ConfigureNotify); + // Tell the window manager to respect the requested size + XSizeHints size_hints; + 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); + + waitForEvent(ConfigureNotify); glXWaitX(); } + void show(void) { + if (visible) { + return; + } + + glXWaitGL(); + + XMapWindow(display, window); + + waitForEvent(MapNotify); + + glXWaitX(); + + Drawable::show(); + } + void swapBuffers(void) { glXSwapBuffers(display, window); } @@ -184,106 +215,135 @@ public: } }; - -class GlxWindowSystem : public WindowSystem -{ -public: - GlxWindowSystem() { - if (!display) { - display = XOpenDisplay(NULL); - if (!display) { - std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n"; - exit(1); - } - screen = DefaultScreen(display); - } +void +init(void) { + display = XOpenDisplay(NULL); + if (!display) { + std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n"; + exit(1); } - ~GlxWindowSystem() { - XCloseDisplay(display); - } + screen = DefaultScreen(display); - Visual * - createVisual(bool doubleBuffer) { - int single_attribs[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DEPTH_SIZE, 1, - GLX_STENCIL_SIZE, 1, - None - }; - - int double_attribs[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - GLX_STENCIL_SIZE, 1, - None - }; - - XVisualInfo *visinfo; - - visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs); - - return new GlxVisual(visinfo); - } + int major = 0, minor = 0; + glXQueryVersion(display, &major, &minor); + glxVersion = (major << 8) | minor; - Drawable * - createDrawable(const Visual *visual, int width, int height) - { - return new GlxDrawable(visual, width, height); - } + extensions = glXQueryExtensionsString(display, screen); + has_GLX_ARB_create_context = checkExtension("GLX_ARB_create_context", extensions); +} - Context * - createContext(const Visual *visual, Context *shareContext) - { - XVisualInfo *visinfo = dynamic_cast(visual)->visinfo; - GLXContext share_context = NULL; - GLXContext context; +void +cleanup(void) { + if (display) { + XCloseDisplay(display); + display = NULL; + } +} - if (shareContext) { - share_context = dynamic_cast(shareContext)->context; +Visual * +createVisual(bool doubleBuffer) { + GlxVisual *visual = new GlxVisual; + + if (glxVersion >= 0x0103) { + Attributes attribs; + attribs.add(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT); + attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT); + attribs.add(GLX_RED_SIZE, 1); + attribs.add(GLX_GREEN_SIZE, 1); + attribs.add(GLX_BLUE_SIZE, 1); + attribs.add(GLX_ALPHA_SIZE, 1); + attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE); + attribs.add(GLX_DEPTH_SIZE, 1); + attribs.add(GLX_STENCIL_SIZE, 1); + attribs.end(); + + int num_configs = 0; + GLXFBConfig * fbconfigs; + fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_configs); + assert(num_configs && fbconfigs); + visual->fbconfig = fbconfigs[0]; + assert(visual->fbconfig); + visual->visinfo = glXGetVisualFromFBConfig(display, visual->fbconfig); + assert(visual->visinfo); + } else { + Attributes attribs; + attribs.add(GLX_RGBA); + attribs.add(GLX_RED_SIZE, 1); + attribs.add(GLX_GREEN_SIZE, 1); + attribs.add(GLX_BLUE_SIZE, 1); + attribs.add(GLX_ALPHA_SIZE, 1); + if (doubleBuffer) { + attribs.add(GLX_DOUBLEBUFFER); } + attribs.add(GLX_DEPTH_SIZE, 1); + attribs.add(GLX_STENCIL_SIZE, 1); + attribs.end(); - context = glXCreateContext(display, visinfo, - share_context, True); - return new GlxContext(visual, context); + visual->visinfo = glXChooseVisual(display, screen, attribs); } - bool - makeCurrent(Drawable *drawable, Context *context) - { - if (!drawable || !context) { - return glXMakeCurrent(display, None, NULL); - } else { - GlxDrawable *glxDrawable = dynamic_cast(drawable); - GlxContext *glxContext = dynamic_cast(context); + return visual; +} - return glXMakeCurrent(display, glxDrawable->window, glxContext->context); - } +Drawable * +createDrawable(const Visual *visual, int width, int height) +{ + return new GlxDrawable(visual, width, height); +} + +Context * +createContext(const Visual *_visual, Context *shareContext) +{ + const GlxVisual *visual = dynamic_cast(_visual); + GLXContext share_context = NULL; + GLXContext context; + + if (shareContext) { + share_context = dynamic_cast(shareContext)->context; } - bool - processEvents(void) { - XFlush(display); - while (XPending(display) > 0) { - XEvent event; - XNextEvent(display, &event); - describeEvent(event); + if (glxVersion >= 0x0104 && has_GLX_ARB_create_context) { + Attributes attribs; + attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE); + if (debug) { + attribs.add(GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB); } - return true; + attribs.end(); + + context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs); + } else + if (glxVersion >= 0x103) { + context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True); + } else { + context = glXCreateContext(display, visual->visinfo, share_context, True); } -}; + return new GlxContext(visual, context); +} -WindowSystem *createNativeWindowSystem(void) { - return new GlxWindowSystem(); +bool +makeCurrent(Drawable *drawable, Context *context) +{ + if (!drawable || !context) { + return glXMakeCurrent(display, None, NULL); + } else { + GlxDrawable *glxDrawable = dynamic_cast(drawable); + GlxContext *glxContext = dynamic_cast(context); + + return glXMakeCurrent(display, glxDrawable->window, glxContext->context); + } +} + +bool +processEvents(void) { + while (XPending(display) > 0) { + XEvent event; + XNextEvent(display, &event); + describeEvent(event); + } + return true; } -} /* namespace glretrace */ +} /* namespace glws */