]> git.cworth.org Git - apitrace/blob - glws_glx.cpp
Use alpha visuals.
[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
33 namespace glws {
34
35
36 static Display *display = NULL;
37 static int screen = 0;
38
39
40 class GlxVisual : public Visual
41 {
42 public:
43     XVisualInfo *visinfo;
44
45     GlxVisual(XVisualInfo *vi) :
46         visinfo(vi)
47     {}
48
49     ~GlxVisual() {
50         XFree(visinfo);
51     }
52 };
53
54
55 static void describeEvent(const XEvent &event) {
56     if (0) {
57         switch (event.type) {
58         case ConfigureNotify:
59             std::cerr << "ConfigureNotify";
60             break;
61         case Expose:
62             std::cerr << "Expose";
63             break;
64         case KeyPress:
65             std::cerr << "KeyPress";
66             break;
67         case MapNotify:
68             std::cerr << "MapNotify";
69             break;
70         case ReparentNotify:
71             std::cerr << "ReparentNotify";
72             break;
73         default:
74             std::cerr << "Event " << event.type;
75         }
76         std::cerr << " " << event.xany.window << "\n";
77     }
78 }
79
80 static void waitForEvent(Window window, int type) {
81     XFlush(display);
82     XEvent event;
83     do {
84         XNextEvent(display, &event);
85         describeEvent(event);
86     } while (event.type != type ||
87              event.xany.window != window);
88 }
89
90
91 class GlxDrawable : public Drawable
92 {
93 public:
94     Window window;
95
96     GlxDrawable(const Visual *vis, int w, int h) :
97         Drawable(vis, w, h)
98     {
99         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
100
101         Window root = RootWindow(display, screen);
102
103         /* window attributes */
104         XSetWindowAttributes attr;
105         attr.background_pixel = 0;
106         attr.border_pixel = 0;
107         attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
108         attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
109
110         unsigned long mask;
111         mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
112
113         int x = 0, y = 0;
114
115         window = XCreateWindow(
116             display, root,
117             x, y, width, height,
118             0,
119             visinfo->depth,
120             InputOutput,
121             visinfo->visual,
122             mask,
123             &attr);
124
125         XSizeHints sizehints;
126         sizehints.x = x;
127         sizehints.y = y;
128         sizehints.width  = width;
129         sizehints.height = height;
130         sizehints.flags = USSize | USPosition;
131         XSetNormalHints(display, window, &sizehints);
132
133         const char *name = "glretrace";
134         XSetStandardProperties(
135             display, window, name, name,
136             None, (char **)NULL, 0, &sizehints);
137
138         XMapWindow(display, window);
139
140         waitForEvent(window, Expose);
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         waitForEvent(window, ConfigureNotify);
162
163         glXWaitX();
164     }
165
166     void swapBuffers(void) {
167         glXSwapBuffers(display, window);
168     }
169 };
170
171
172 class GlxContext : public Context
173 {
174 public:
175     GLXContext context;
176
177     GlxContext(const Visual *vis, GLXContext ctx) :
178         Context(vis),
179         context(ctx)
180     {}
181
182     ~GlxContext() {
183         glXDestroyContext(display, context);
184     }
185 };
186
187
188 class GlxWindowSystem : public WindowSystem
189 {
190 public:
191     GlxWindowSystem() {
192         if (!display) {
193             display = XOpenDisplay(NULL);
194             if (!display) {
195                 std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
196                 exit(1);
197             }
198             screen = DefaultScreen(display);
199         }
200     }
201
202     ~GlxWindowSystem() {
203         XCloseDisplay(display);
204     }
205
206     Visual *
207     createVisual(bool doubleBuffer) {
208         int single_attribs[] = {
209             GLX_RGBA,
210             GLX_RED_SIZE, 1,
211             GLX_GREEN_SIZE, 1,
212             GLX_BLUE_SIZE, 1,
213             GLX_ALPHA_SIZE, 1,
214             GLX_DEPTH_SIZE, 1,
215             GLX_STENCIL_SIZE, 1,
216             None
217         };
218
219         int double_attribs[] = {
220             GLX_RGBA,
221             GLX_RED_SIZE, 1,
222             GLX_GREEN_SIZE, 1,
223             GLX_BLUE_SIZE, 1,
224             GLX_ALPHA_SIZE, 1,
225             GLX_DOUBLEBUFFER,
226             GLX_DEPTH_SIZE, 1,
227             GLX_STENCIL_SIZE, 1,
228             None
229         };
230
231         XVisualInfo *visinfo;
232
233         visinfo = glXChooseVisual(display, screen, doubleBuffer ? double_attribs : single_attribs);
234
235         return new GlxVisual(visinfo);
236     }
237
238     Drawable *
239     createDrawable(const Visual *visual, int width, int height)
240     {
241         return new GlxDrawable(visual, width, height);
242     }
243
244     Context *
245     createContext(const Visual *visual, Context *shareContext)
246     {
247         XVisualInfo *visinfo = dynamic_cast<const GlxVisual *>(visual)->visinfo;
248         GLXContext share_context = NULL;
249         GLXContext context;
250
251         if (shareContext) {
252             share_context = dynamic_cast<GlxContext*>(shareContext)->context;
253         }
254
255         context = glXCreateContext(display, visinfo,
256                                    share_context, True);
257         return new GlxContext(visual, context);
258     }
259
260     bool
261     makeCurrent(Drawable *drawable, Context *context)
262     {
263         if (!drawable || !context) {
264             return glXMakeCurrent(display, None, NULL);
265         } else {
266             GlxDrawable *glxDrawable = dynamic_cast<GlxDrawable *>(drawable);
267             GlxContext *glxContext = dynamic_cast<GlxContext *>(context);
268
269             return glXMakeCurrent(display, glxDrawable->window, glxContext->context);
270         }
271     }
272
273     bool
274     processEvents(void) {
275         XFlush(display);
276         while (XPending(display) > 0) {
277             XEvent event;
278             XNextEvent(display, &event);
279             describeEvent(event);
280         }
281         return true;
282     }
283 };
284
285
286 WindowSystem *createNativeWindowSystem(void) {
287     return new GlxWindowSystem();
288 }
289
290
291 } /* namespace glretrace */