[PATCH 3/6] glws: Add EGL/Xlib-based implementation

Chia-I Wu olvaffe at gmail.com
Tue Nov 8 15:48:40 PST 2011


This is based on glws_glx, with GLX replaced by EGL.  This is also the only
glws implementation that supports GLESv1 and GLESv2 profiles.
---
 glws_egl_xlib.cpp |  385 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 385 insertions(+), 0 deletions(-)
 create mode 100644 glws_egl_xlib.cpp

diff --git a/glws_egl_xlib.cpp b/glws_egl_xlib.cpp
new file mode 100644
index 0000000..da232bd
--- /dev/null
+++ b/glws_egl_xlib.cpp
@@ -0,0 +1,385 @@
+/**************************************************************************
+ *
+ * Copyright 2011 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Based on glws_glx.cpp, which has
+ *
+ *   Copyright 2011 Jose Fonseca
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <iostream>
+
+#include "glws.hpp"
+
+#include "glproc.hpp"
+
+
+namespace glws {
+
+
+static Display *display = NULL;
+static EGLDisplay eglDisplay = EGL_NO_DISPLAY;
+static int screen = 0;
+
+
+class EglVisual : public Visual
+{
+public:
+    EGLConfig config;
+    XVisualInfo *visinfo;
+
+    EglVisual() :
+        config(0),
+        visinfo(0)
+    {}
+
+    ~EglVisual() {
+        XFree(visinfo);
+    }
+};
+
+
+static void describeEvent(const XEvent &event) {
+    if (0) {
+        switch (event.type) {
+        case ConfigureNotify:
+            std::cerr << "ConfigureNotify";
+            break;
+        case Expose:
+            std::cerr << "Expose";
+            break;
+        case KeyPress:
+            std::cerr << "KeyPress";
+            break;
+        case MapNotify:
+            std::cerr << "MapNotify";
+            break;
+        case ReparentNotify:
+            std::cerr << "ReparentNotify";
+            break;
+        default:
+            std::cerr << "Event " << event.type;
+        }
+        std::cerr << " " << event.xany.window << "\n";
+    }
+}
+
+class EglDrawable : public Drawable
+{
+public:
+    Window window;
+    EGLSurface surface;
+    EGLint api;
+
+    EglDrawable(const Visual *vis, int w, int h) :
+        Drawable(vis, w, h), api(EGL_OPENGL_ES_API)
+    {
+        XVisualInfo *visinfo = dynamic_cast<const EglVisual *>(visual)->visinfo;
+
+        Window root = RootWindow(display, screen);
+
+        /* window attributes */
+        XSetWindowAttributes attr;
+        attr.background_pixel = 0;
+        attr.border_pixel = 0;
+        attr.colormap = XCreateColormap(display, root, visinfo->visual, AllocNone);
+        attr.event_mask = StructureNotifyMask;
+
+        unsigned long mask;
+        mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+        int x = 0, y = 0;
+
+        window = XCreateWindow(
+            display, root,
+            x, y, width, height,
+            0,
+            visinfo->depth,
+            InputOutput,
+            visinfo->visual,
+            mask,
+            &attr);
+
+        XSizeHints sizehints;
+        sizehints.x = x;
+        sizehints.y = y;
+        sizehints.width  = width;
+        sizehints.height = height;
+        sizehints.flags = USSize | USPosition;
+        XSetNormalHints(display, window, &sizehints);
+
+        const char *name = "glretrace";
+        XSetStandardProperties(
+            display, window, name, name,
+            None, (char **)NULL, 0, &sizehints);
+
+        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+
+        EGLConfig config = dynamic_cast<const EglVisual *>(visual)->config;
+        surface = eglCreateWindowSurface(eglDisplay, config, window, NULL);
+    }
+
+    void waitForEvent(int type) {
+        XEvent event;
+        do {
+            XWindowEvent(display, window, StructureNotifyMask, &event);
+            describeEvent(event);
+        } while (event.type != type);
+    }
+
+    ~EglDrawable() {
+        eglDestroySurface(eglDisplay, surface);
+        XDestroyWindow(display, window);
+    }
+
+    void
+    resize(int w, int h) {
+        if (w == width && h == height) {
+            return;
+        }
+
+        eglWaitClient();
+
+        // We need to ensure that pending events are processed here, and XSync
+        // with discard = True guarantees that, but it appears the limited
+        // event processing we do so far is sufficient
+        //XSync(display, True);
+
+        Drawable::resize(w, h);
+
+        XResizeWindow(display, window, w, h);
+
+        // Tell the window manager to respect the requested size
+        XSizeHints size_hints;
+        size_hints.max_width  = size_hints.min_width  = w;
+        size_hints.max_height = size_hints.min_height = h;
+        size_hints.flags = PMinSize | PMaxSize;
+        XSetWMNormalHints(display, window, &size_hints);
+
+        waitForEvent(ConfigureNotify);
+
+        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+    }
+
+    void show(void) {
+        if (visible) {
+            return;
+        }
+
+        eglWaitClient();
+
+        XMapWindow(display, window);
+
+        waitForEvent(MapNotify);
+
+        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+
+        Drawable::show();
+    }
+
+    void swapBuffers(void) {
+        eglBindAPI(api);
+        eglSwapBuffers(eglDisplay, surface);
+    }
+};
+
+
+class EglContext : public Context
+{
+public:
+    EGLContext context;
+
+    EglContext(const Visual *vis, EGLContext ctx) :
+        Context(vis),
+        context(ctx)
+    {}
+
+    ~EglContext() {
+        eglDestroyContext(eglDisplay, context);
+    }
+};
+
+void
+init(void) {
+    display = XOpenDisplay(NULL);
+    if (!display) {
+        std::cerr << "error: unable to open display " << XDisplayName(NULL) << "\n";
+        exit(1);
+    }
+
+    screen = DefaultScreen(display);
+
+    eglDisplay = eglGetDisplay(display);
+    if (eglDisplay == EGL_NO_DISPLAY) {
+        std::cerr << "error: unable to get EGL display\n";
+        XCloseDisplay(display);
+        exit(1);
+    }
+
+    EGLint major, minor;
+    if (!eglInitialize(eglDisplay, &major, &minor)) {
+        std::cerr << "error: unable to initialize EGL display\n";
+        XCloseDisplay(display);
+        exit(1);
+    }
+}
+
+void
+cleanup(void) {
+    if (display) {
+        eglTerminate(eglDisplay);
+        XCloseDisplay(display);
+        display = NULL;
+    }
+}
+
+Visual *
+createVisual(bool doubleBuffer) {
+    EglVisual *visual = new EglVisual();
+    // possible combinations
+    const EGLint api_bits[7] = {
+        EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
+        EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,
+        EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT,
+        EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT,
+        EGL_OPENGL_ES_BIT,
+        EGL_OPENGL_ES2_BIT,
+        EGL_OPENGL_BIT,
+    };
+
+    for (int i = 0; i < 7; i++) {
+        Attributes<EGLint> attribs;
+
+        attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+        attribs.add(EGL_RED_SIZE, 1);
+        attribs.add(EGL_GREEN_SIZE, 1);
+        attribs.add(EGL_BLUE_SIZE, 1);
+        attribs.add(EGL_ALPHA_SIZE, 1);
+        attribs.add(EGL_DEPTH_SIZE, 1);
+        attribs.add(EGL_STENCIL_SIZE, 1);
+        attribs.add(EGL_RENDERABLE_TYPE, api_bits[i]);
+        attribs.end(EGL_NONE);
+
+        EGLint num_configs, vid;
+        if (eglChooseConfig(eglDisplay, attribs, &visual->config, 1, &num_configs) &&
+            num_configs == 1 &&
+            eglGetConfigAttrib(eglDisplay, visual->config, EGL_NATIVE_VISUAL_ID, &vid)) {
+            XVisualInfo templ;
+            int num_visuals;
+
+            templ.visualid = vid;
+            visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals);
+            break;
+        }
+    }
+
+    assert(visual->visinfo);
+
+    return visual;
+}
+
+Drawable *
+createDrawable(const Visual *visual, int width, int height)
+{
+    return new EglDrawable(visual, width, height);
+}
+
+Context *
+createContext(const Visual *_visual, Context *shareContext, Profile profile)
+{
+    const EglVisual *visual = dynamic_cast<const EglVisual *>(_visual);
+    EGLContext share_context = EGL_NO_CONTEXT;
+    EGLContext context;
+    Attributes<EGLint> attribs;
+
+    if (shareContext) {
+        share_context = dynamic_cast<EglContext*>(shareContext)->context;
+    }
+
+    EGLint api = eglQueryAPI();
+
+    switch (profile) {
+    case PROFILE_COMPAT:
+        eglBindAPI(EGL_OPENGL_API);
+        break;
+    case PROFILE_ES1:
+        eglBindAPI(EGL_OPENGL_ES_API);
+        break;
+    case PROFILE_ES2:
+        eglBindAPI(EGL_OPENGL_ES_API);
+        attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2);
+        break;
+    }
+
+    attribs.end(EGL_NONE);
+
+    context = eglCreateContext(eglDisplay, visual->config, share_context, attribs);
+    if (!context)
+        return NULL;
+
+    eglBindAPI(api);
+
+    return new EglContext(visual, context);
+}
+
+bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+    if (!drawable || !context) {
+        return eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    } else {
+        EglDrawable *eglDrawable = dynamic_cast<EglDrawable *>(drawable);
+        EglContext *eglContext = dynamic_cast<EglContext *>(context);
+        EGLBoolean ok;
+
+        ok = eglMakeCurrent(eglDisplay, eglDrawable->surface,
+                            eglDrawable->surface, eglContext->context);
+
+        if (ok) {
+            EGLint api;
+
+            eglQueryContext(eglDisplay, eglContext->context,
+                            EGL_CONTEXT_CLIENT_TYPE, &api);
+
+            eglDrawable->api = api;
+        }
+
+        return ok;
+    }
+}
+
+bool
+processEvents(void) {
+    while (XPending(display) > 0) {
+        XEvent event;
+        XNextEvent(display, &event);
+        describeEvent(event);
+    }
+    return true;
+}
+
+
+} /* namespace glws */
-- 
1.7.6.3



More information about the apitrace mailing list