]> git.cworth.org Git - apitrace/blob - glws_glx.cpp
Ignore unexpected end of file in gzread.
[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 "glws.hpp"
30
31 #include <X11/Xlib.h>
32 #include <GL/gl.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         glXWaitX();
142     }
143
144     ~GlxDrawable() {
145         XDestroyWindow(display, window);
146     }
147
148     void
149     resize(int w, int h) {
150         glXWaitGL();
151
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);
156
157         Drawable::resize(w, h);
158
159         XResizeWindow(display, window, w, h);
160
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);
168         XFree(size_hints);
169
170         waitForEvent(window, ConfigureNotify);
171
172         glXWaitX();
173     }
174
175     void show(void) {
176         if (!visible) {
177             XMapWindow(display, window);
178
179             waitForEvent(window, Expose);
180
181             Drawable::show();
182         }
183     }
184
185     void swapBuffers(void) {
186         glXSwapBuffers(display, window);
187     }
188 };
189
190
191 class GlxContext : public Context
192 {
193 public:
194     GLXContext context;
195
196     GlxContext(const Visual *vis, GLXContext ctx) :
197         Context(vis),
198         context(ctx)
199     {}
200
201     ~GlxContext() {
202         glXDestroyContext(display, context);
203     }
204 };
205
206
207 class GlxWindowSystem : public WindowSystem
208 {
209 public:
210     GlxWindowSystem() {
211         if (!display) {
212             display = XOpenDisplay(NULL);
213             if (!display) {
214                 std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
215                 exit(1);
216             }
217             screen = DefaultScreen(display);
218         }
219     }
220
221     ~GlxWindowSystem() {
222         XCloseDisplay(display);
223     }
224
225     Visual *
226     createVisual(bool doubleBuffer) {
227         int single_attribs[] = {
228             GLX_RGBA,
229             GLX_RED_SIZE, 1,
230             GLX_GREEN_SIZE, 1,
231             GLX_BLUE_SIZE, 1,
232             GLX_ALPHA_SIZE, 1,
233             GLX_DEPTH_SIZE, 1,
234             GLX_STENCIL_SIZE, 1,
235             None
236         };
237
238         int double_attribs[] = {
239             GLX_RGBA,
240             GLX_RED_SIZE, 1,
241             GLX_GREEN_SIZE, 1,
242             GLX_BLUE_SIZE, 1,
243             GLX_ALPHA_SIZE, 1,
244             GLX_DOUBLEBUFFER,
245             GLX_DEPTH_SIZE, 1,
246             GLX_STENCIL_SIZE, 1,
247             None
248         };
249
250         XVisualInfo *visinfo;
251
252         visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
253
254         return new GlxVisual(visinfo);
255     }
256
257     Drawable *
258     createDrawable(const Visual *visual, int width, int height)
259     {
260         return new GlxDrawable(visual, width, height);
261     }
262
263     Context *
264     createContext(const Visual *visual, Context *shareContext)
265     {
266         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
267         GLXContext share_context = NULL;
268         GLXContext context;
269
270         if (shareContext) {
271             share_context = dynamic_cast<GlxContext*>(shareContext)->context;
272         }
273
274         context = glXCreateContext(display, visinfo,
275                                    share_context, True);
276         return new GlxContext(visual, context);
277     }
278
279     bool
280     makeCurrent(Drawable *drawable, Context *context)
281     {
282         if (!drawable || !context) {
283             return glXMakeCurrent(display, None, NULL);
284         } else {
285             GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
286             GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
287
288             return glXMakeCurrent(display, glxDrawable->window, glxContext->context);
289         }
290     }
291
292     bool
293     processEvents(void) {
294         XFlush(display);
295         while (XPending(display) > 0) {
296             XEvent event;
297             XNextEvent(display, &event);
298             describeEvent(event);
299         }
300         return true;
301     }
302 };
303
304
305 WindowSystem *createNativeWindowSystem(void) {
306     return new GlxWindowSystem();
307 }
308
309
310 } /* namespace glretrace */