]> git.cworth.org Git - apitrace/blob - glws_glx.cpp
Determine drawable sizes on MacOSX.
[apitrace] / glws_glx.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #include <stdlib.h>
27 #include <iostream>
28
29 #include "glimports.hpp"
30 #include "glws.hpp"
31
32 #include <X11/Xlib.h>
33 #include <GL/glx.h>
34
35
36 namespace glws {
37
38
39 static Display *display = NULL;
40 static int screen = 0;
41
42
43 class GlxVisual : public Visual
44 {
45 public:
46     XVisualInfo *visinfo;
47
48     GlxVisual(XVisualInfo *vi) :
49         visinfo(vi)
50     {}
51
52     ~GlxVisual() {
53         XFree(visinfo);
54     }
55 };
56
57
58 static void describeEvent(const XEvent &event) {
59     if (0) {
60         switch (event.type) {
61         case ConfigureNotify:
62             std::cerr << "ConfigureNotify";
63             break;
64         case Expose:
65             std::cerr << "Expose";
66             break;
67         case KeyPress:
68             std::cerr << "KeyPress";
69             break;
70         case MapNotify:
71             std::cerr << "MapNotify";
72             break;
73         case ReparentNotify:
74             std::cerr << "ReparentNotify";
75             break;
76         default:
77             std::cerr << "Event " << event.type;
78         }
79         std::cerr << " " << event.xany.window << "\n";
80     }
81 }
82
83 static void waitForEvent(Window window, int type) {
84     XFlush(display);
85     XEvent event;
86     do {
87         XNextEvent(display, &event);
88         describeEvent(event);
89     } while (event.type != type ||
90              event.xany.window != window);
91 }
92
93
94 class GlxDrawable : public Drawable
95 {
96 public:
97     Window window;
98
99     GlxDrawable(const Visual *vis, int w, int h) :
100         Drawable(vis, w, h)
101     {
102         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
103
104         Window root = RootWindow(display, screen);
105
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;
112
113         unsigned long mask;
114         mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
115
116         int x = 0, y = 0;
117
118         window = XCreateWindow(
119             display, root,
120             x, y, width, height,
121             0,
122             visinfo->depth,
123             InputOutput,
124             visinfo->visual,
125             mask,
126             &attr);
127
128         XSizeHints sizehints;
129         sizehints.x = x;
130         sizehints.y = y;
131         sizehints.width  = width;
132         sizehints.height = height;
133         sizehints.flags = USSize | USPosition;
134         XSetNormalHints(display, window, &sizehints);
135
136         const char *name = "glretrace";
137         XSetStandardProperties(
138             display, window, name, name,
139             None, (char **)NULL, 0, &sizehints);
140
141         XMapWindow(display, window);
142
143         waitForEvent(window, Expose);
144         glXWaitX();
145     }
146
147     ~GlxDrawable() {
148         XDestroyWindow(display, window);
149     }
150
151     void
152     resize(int w, int h) {
153         glXWaitGL();
154
155         // We need to ensure that pending events are processed here, and XSync
156         // with discard = True guarantees that, but it appears the limited
157         // event processing we do so far is sufficient
158         //XSync(display, True);
159
160         Drawable::resize(w, h);
161
162         XResizeWindow(display, window, w, h);
163
164         waitForEvent(window, ConfigureNotify);
165
166         glXWaitX();
167     }
168
169     void swapBuffers(void) {
170         glXSwapBuffers(display, window);
171     }
172 };
173
174
175 class GlxContext : public Context
176 {
177 public:
178     GLXContext context;
179
180     GlxContext(const Visual *vis, GLXContext ctx) :
181         Context(vis),
182         context(ctx)
183     {}
184
185     ~GlxContext() {
186         glXDestroyContext(display, context);
187     }
188 };
189
190
191 class GlxWindowSystem : public WindowSystem
192 {
193 public:
194     GlxWindowSystem() {
195         if (!display) {
196             display = XOpenDisplay(NULL);
197             if (!display) {
198                 std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
199                 exit(1);
200             }
201             screen = DefaultScreen(display);
202         }
203     }
204
205     ~GlxWindowSystem() {
206         XCloseDisplay(display);
207     }
208
209     Visual *
210     createVisual(bool doubleBuffer) {
211         int single_attribs[] = {
212             GLX_RGBA,
213             GLX_RED_SIZE, 1,
214             GLX_GREEN_SIZE, 1,
215             GLX_BLUE_SIZE, 1,
216             GLX_ALPHA_SIZE, 1,
217             GLX_DEPTH_SIZE, 1,
218             GLX_STENCIL_SIZE, 1,
219             None
220         };
221
222         int double_attribs[] = {
223             GLX_RGBA,
224             GLX_RED_SIZE, 1,
225             GLX_GREEN_SIZE, 1,
226             GLX_BLUE_SIZE, 1,
227             GLX_ALPHA_SIZE, 1,
228             GLX_DOUBLEBUFFER,
229             GLX_DEPTH_SIZE, 1,
230             GLX_STENCIL_SIZE, 1,
231             None
232         };
233
234         XVisualInfo *visinfo;
235
236         visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
237
238         return new GlxVisual(visinfo);
239     }
240
241     Drawable *
242     createDrawable(const Visual *visual, int width, int height)
243     {
244         return new GlxDrawable(visual, width, height);
245     }
246
247     Context *
248     createContext(const Visual *visual, Context *shareContext)
249     {
250         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
251         GLXContext share_context = NULL;
252         GLXContext context;
253
254         if (shareContext) {
255             share_context = dynamic_cast<GlxContext*>(shareContext)->context;
256         }
257
258         context = glXCreateContext(display, visinfo,
259                                    share_context, True);
260         return new GlxContext(visual, context);
261     }
262
263     bool
264     makeCurrent(Drawable *drawable, Context *context)
265     {
266         if (!drawable || !context) {
267             return glXMakeCurrent(display, None, NULL);
268         } else {
269             GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
270             GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
271
272             return glXMakeCurrent(display, glxDrawable->window, glxContext->context);
273         }
274     }
275
276     bool
277     processEvents(void) {
278         XFlush(display);
279         while (XPending(display) > 0) {
280             XEvent event;
281             XNextEvent(display, &event);
282             describeEvent(event);
283         }
284         return true;
285     }
286 };
287
288
289 WindowSystem *createNativeWindowSystem(void) {
290     return new GlxWindowSystem();
291 }
292
293
294 } /* namespace glretrace */