1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
39 static Display *display = NULL;
40 static int screen = 0;
43 class GlxVisual : public Visual
48 GlxVisual(XVisualInfo *vi) :
58 static void describeEvent(const XEvent &event) {
62 std::cerr << "ConfigureNotify";
65 std::cerr << "Expose";
68 std::cerr << "KeyPress";
71 std::cerr << "MapNotify";
74 std::cerr << "ReparentNotify";
77 std::cerr << "Event " << event.type;
79 std::cerr << " " << event.xany.window << "\n";
83 static void waitForEvent(Window window, int type) {
87 XNextEvent(display, &event);
89 } while (event.type != type ||
90 event.xany.window != window);
94 class GlxDrawable : public Drawable
99 GlxDrawable(const Visual *vis, int w, int h) :
102 XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
104 Window root = RootWindow(display, screen);
106 /* window attributes */
107 XSetWindowAttributes attr;
108 attr.background_pixel = 0;
109 attr.border_pixel = 0;
110 attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
111 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
114 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
118 window = XCreateWindow(
128 XSizeHints sizehints;
131 sizehints.width = width;
132 sizehints.height = height;
133 sizehints.flags = USSize | USPosition;
134 XSetNormalHints(display, window, &sizehints);
136 const char *name = "glretrace";
137 XSetStandardProperties(
138 display, window, name, name,
139 None, (char **)NULL, 0, &sizehints);
145 XDestroyWindow(display, window);
149 resize(int w, int h) {
152 // We need to ensure that pending events are processed here, and XSync
153 // with discard = True guarantees that, but it appears the limited
154 // event processing we do so far is sufficient
155 //XSync(display, True);
157 Drawable::resize(w, h);
159 XResizeWindow(display, window, w, h);
161 // Tell the window manager to respect the requested size
162 XSizeHints *size_hints;
163 size_hints = XAllocSizeHints();
164 size_hints->max_width = size_hints->min_width = w;
165 size_hints->max_height = size_hints->min_height = h;
166 size_hints->flags = PMinSize | PMaxSize;
167 XSetWMNormalHints(display, window, size_hints);
170 waitForEvent(window, ConfigureNotify);
177 XMapWindow(display, window);
179 waitForEvent(window, Expose);
185 void swapBuffers(void) {
186 glXSwapBuffers(display, window);
191 class GlxContext : public Context
196 GlxContext(const Visual *vis, GLXContext ctx) :
202 glXDestroyContext(display, context);
207 class GlxWindowSystem : public WindowSystem
212 display = XOpenDisplay(NULL);
214 std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
217 screen = DefaultScreen(display);
222 XCloseDisplay(display);
226 createVisual(bool doubleBuffer) {
227 int single_attribs[] = {
238 int double_attribs[] = {
250 XVisualInfo *visinfo;
252 visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
254 return new GlxVisual(visinfo);
258 createDrawable(const Visual *visual, int width, int height)
260 return new GlxDrawable(visual, width, height);
264 createContext(const Visual *visual, Context *shareContext)
266 XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
267 GLXContext share_context = NULL;
271 share_context = dynamic_cast<GlxContext*>(shareContext)->context;
274 context = glXCreateContext(display, visinfo,
275 share_context, True);
276 return new GlxContext(visual, context);
280 makeCurrent(Drawable *drawable, Context *context)
282 if (!drawable || !context) {
283 return glXMakeCurrent(display, None, NULL);
285 GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
286 GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
288 return glXMakeCurrent(display, glxDrawable->window, glxContext->context);
293 processEvents(void) {
295 while (XPending(display) > 0) {
297 XNextEvent(display, &event);
298 describeEvent(event);
305 WindowSystem *createNativeWindowSystem(void) {
306 return new GlxWindowSystem();
310 } /* namespace glretrace */