1 /**************************************************************************
3 * Copyright 2011 LunarG, Inc.
6 * Based on glws_glx.cpp, which has
8 * Copyright 2011 Jose Fonseca
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 **************************************************************************/
43 static Display *display = NULL;
44 static EGLDisplay eglDisplay = EGL_NO_DISPLAY;
45 static int screen = 0;
48 class EglVisual : public Visual
65 static void describeEvent(const XEvent &event) {
69 std::cerr << "ConfigureNotify";
72 std::cerr << "Expose";
75 std::cerr << "KeyPress";
78 std::cerr << "MapNotify";
81 std::cerr << "ReparentNotify";
84 std::cerr << "Event " << event.type;
86 std::cerr << " " << event.xany.window << "\n";
90 class EglDrawable : public Drawable
97 EglDrawable(const Visual *vis, int w, int h) :
98 Drawable(vis, w, h), api(EGL_OPENGL_ES_API)
100 XVisualInfo *visinfo = dynamic_cast<const EglVisual *>(visual)->visinfo;
102 Window root = RootWindow(display, screen);
104 /* window attributes */
105 XSetWindowAttributes attr;
106 attr.background_pixel = 0;
107 attr.border_pixel = 0;
108 attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
109 attr.event_mask = StructureNotifyMask;
112 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
116 window = XCreateWindow(
126 XSizeHints sizehints;
129 sizehints.width = width;
130 sizehints.height = height;
131 sizehints.flags = USSize | USPosition;
132 XSetNormalHints(display, window, &sizehints);
134 const char *name = "glretrace";
135 XSetStandardProperties(
136 display, window, name, name,
137 None, (char **)NULL, 0, &sizehints);
139 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
141 EGLConfig config = dynamic_cast<const EglVisual *>(visual)->config;
142 surface = eglCreateWindowSurface(eglDisplay, config, window, NULL);
145 void waitForEvent(int type) {
148 XWindowEvent(display, window, StructureNotifyMask, &event);
149 describeEvent(event);
150 } while (event.type != type);
154 eglDestroySurface(eglDisplay, surface);
155 XDestroyWindow(display, window);
159 resize(int w, int h) {
160 if (w == width && h == height) {
166 // We need to ensure that pending events are processed here, and XSync
167 // with discard = True guarantees that, but it appears the limited
168 // event processing we do so far is sufficient
169 //XSync(display, True);
171 Drawable::resize(w, h);
173 XResizeWindow(display, window, w, h);
175 // Tell the window manager to respect the requested size
176 XSizeHints size_hints;
177 size_hints.max_width = size_hints.min_width = w;
178 size_hints.max_height = size_hints.min_height = h;
179 size_hints.flags = PMinSize | PMaxSize;
180 XSetWMNormalHints(display, window, &size_hints);
182 waitForEvent(ConfigureNotify);
184 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
194 XMapWindow(display, window);
196 waitForEvent(MapNotify);
198 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
203 void swapBuffers(void) {
205 eglSwapBuffers(eglDisplay, surface);
210 class EglContext : public Context
215 EglContext(const Visual *vis, EGLContext ctx) :
221 eglDestroyContext(eglDisplay, context);
227 display = XOpenDisplay(NULL);
229 std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
233 screen = DefaultScreen(display);
235 eglDisplay = eglGetDisplay(display);
236 if (eglDisplay == EGL_NO_DISPLAY) {
237 std::cerr << "error: unable to get EGL display\n";
238 XCloseDisplay(display);
243 if (!eglInitialize(eglDisplay, &major, &minor)) {
244 std::cerr << "error: unable to initialize EGL display\n";
245 XCloseDisplay(display);
253 eglTerminate(eglDisplay);
254 XCloseDisplay(display);
260 createVisual(bool doubleBuffer) {
261 EglVisual *visual = new EglVisual();
262 // possible combinations
263 const EGLint api_bits[7] = {
264 EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
265 EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
266 EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT,
267 EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT,
273 for (int i = 0; i < 7; i++) {
274 Attributes<EGLint> attribs;
276 attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
277 attribs.add(EGL_RED_SIZE, 1);
278 attribs.add(EGL_GREEN_SIZE, 1);
279 attribs.add(EGL_BLUE_SIZE, 1);
280 attribs.add(EGL_ALPHA_SIZE, 1);
281 attribs.add(EGL_DEPTH_SIZE, 1);
282 attribs.add(EGL_STENCIL_SIZE, 1);
283 attribs.add(EGL_RENDERABLE_TYPE, api_bits[i]);
284 attribs.end(EGL_NONE);
286 EGLint num_configs, vid;
287 if (eglChooseConfig(eglDisplay, attribs, &visual->config, 1, &num_configs) &&
289 eglGetConfigAttrib(eglDisplay, visual->config, EGL_NATIVE_VISUAL_ID, &vid)) {
293 templ.visualid = vid;
294 visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals);
299 assert(visual->visinfo);
305 createDrawable(const Visual *visual, int width, int height)
307 return new EglDrawable(visual, width, height);
311 createContext(const Visual *_visual, Context *shareContext, Profile profile)
313 const EglVisual *visual = dynamic_cast<const EglVisual *>(_visual);
314 EGLContext share_context = EGL_NO_CONTEXT;
316 Attributes<EGLint> attribs;
319 share_context = dynamic_cast<EglContext*>(shareContext)->context;
322 EGLint api = eglQueryAPI();
326 eglBindAPI(EGL_OPENGL_API);
329 eglBindAPI(EGL_OPENGL_ES_API);
332 eglBindAPI(EGL_OPENGL_ES_API);
333 attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2);
337 attribs.end(EGL_NONE);
339 context = eglCreateContext(eglDisplay, visual->config, share_context, attribs);
345 return new EglContext(visual, context);
349 makeCurrent(Drawable *drawable, Context *context)
351 if (!drawable || !context) {
352 return eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
354 EglDrawable *eglDrawable = dynamic_cast<EglDrawable *>(drawable);
355 EglContext *eglContext = dynamic_cast<EglContext *>(context);
358 ok = eglMakeCurrent(eglDisplay, eglDrawable->surface,
359 eglDrawable->surface, eglContext->context);
364 eglQueryContext(eglDisplay, eglContext->context,
365 EGL_CONTEXT_CLIENT_TYPE, &api);
367 eglDrawable->api = api;
375 processEvents(void) {
376 while (XPending(display) > 0) {
378 XNextEvent(display, &event);
379 describeEvent(event);
385 } /* namespace glws */