[PATCH] Android: Port eglretracer for Android

Juha-Pekka Heikkila juha-pekka.heikkila at linux.intel.com
Tue Jul 23 00:22:46 PDT 2013


Port eglretracer for Android using Waffle library. To build for
Android the Android source tree is needed for Waffle. Waffle
need to be build first, Waffle can be obtained from:
http://cgit.freedesktop.org/~chadversary/waffle/

If Android source tree is not available/only NDK is present
egltrace.so and related will only be build, eglretracer will
be skipped.

Known issues:
eglretracer seem to launch multiple windows with some traces from
Android. These multiple windows sometimes segfault on Android,
need to look into this yet. I remember SurfaceFlinger wasn't
maybe too happy with such behaviour.

Signed-off-by: Juha-Pekka Heikkila <juha-pekka.heikkila at linux.intel.com>
---
 dispatch/glproc_egl.cpp |   9 ++
 retrace/CMakeLists.txt  |  74 ++++++++++---
 retrace/glws_waffle.cpp | 274 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 344 insertions(+), 13 deletions(-)
 create mode 100644 retrace/glws_waffle.cpp

diff --git a/dispatch/glproc_egl.cpp b/dispatch/glproc_egl.cpp
index 5f93b14..f9e4ac1 100644
--- a/dispatch/glproc_egl.cpp
+++ b/dispatch/glproc_egl.cpp
@@ -26,6 +26,10 @@
 
 #include "glproc.hpp"
 
+#if defined __ANDROID__ && defined BUILDEGLRETRACER
+#include <waffle.h>
+#endif
+
 
 #if !defined(_WIN32)
 #ifndef _GNU_SOURCE
@@ -137,6 +141,10 @@ _getPublicProcAddress(const char *procName)
 void *
 _getPrivateProcAddress(const char *procName)
 {
+#if defined __ANDROID__ && defined BUILDEGLRETRACER
+    extern int waffle_gl_api;
+    return waffle_dl_sym(waffle_gl_api, procName);
+#else
     void *proc;
     proc = _getPublicProcAddress(procName);
     if (!proc &&
@@ -146,6 +154,7 @@ _getPrivateProcAddress(const char *procName)
     }
 
     return proc;
+#endif
 }
 
 #endif
diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt
index 913c23e..e77d549 100644
--- a/retrace/CMakeLists.txt
+++ b/retrace/CMakeLists.txt
@@ -39,6 +39,33 @@ add_library (retrace_common STATIC
     retrace_swizzle.cpp
     json.cpp
 )
+
+if (ANDROID)
+        message ("-- Looking for Waffle library")
+
+#########
+# In following the name waffle-1 should be fixed to found out properly.
+    find_path (Waffle_INCLUDE_DIRS
+        NAMES waffle.h
+        PATHS "$ENV{OUT}/obj/include/waffle-1"
+            "$ENV{OUT}/obj/lib" "$ENV{ANDROID_BUILD_TOP}/external/waffle"
+            NO_CMAKE_FIND_ROOT_PATH
+    )
+    if (Waffle_INCLUDE_DIRS)
+        message ("-- Looking for Waffle library - found")
+        find_library (Waffle
+            NAMES "waffle-1"
+            PATHS "$ENV{OUT}/obj/include/waffle-1" "$ENV{OUT}/obj/lib"
+                "$ENV{ANDROID_BUILD_TOP}/external/waffle"
+                REQUIRED NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
+        )
+        include_directories (${Waffle_INCLUDE_DIRS})
+    else ()
+        message ("-- Looking for Waffle library - not found,"
+                 " skipping eglretrace")
+    endif ()
+endif ()
+
 target_link_libraries (retrace_common
     image
     common
@@ -112,24 +139,45 @@ if (WIN32 OR APPLE OR X11_FOUND)
     install (TARGETS glretrace RUNTIME DESTINATION bin) 
 endif ()
 
-if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
-    add_executable (eglretrace
-        glws_egl_xlib.cpp
-    )
+
+if (ENABLE_EGL AND X11_FOUND OR (ANDROID AND Waffle_INCLUDE_DIRS)AND NOT WIN32
+    AND NOT APPLE)
+    if (ANDROID)
+        add_definitions(-DBUILDEGLRETRACER)
+        add_executable (eglretrace
+            glws_waffle.cpp
+        )
+    else ()
+        add_executable (eglretrace
+            glws_egl_xlib.cpp
+        )
+    endif ()
 
     add_dependencies (eglretrace glproc)
 
-    target_link_libraries (eglretrace
-        retrace_common
-        glretrace_common
-        glproc_egl
-        ${X11_X11_LIB}
-        ${CMAKE_THREAD_LIBS_INIT}
-        dl
-    )
+    if (ANDROID)
+        target_link_libraries (eglretrace
+            retrace_common
+            glretrace_common
+            glproc_egl
+            dl
+           ${Waffle}
+        )
+    else ()
+        target_link_libraries (eglretrace
+            retrace_common
+            glretrace_common
+            glproc_egl
+            ${X11_X11_LIB}
+            ${CMAKE_THREAD_LIBS_INIT}
+            dl
+        )
+    endif ()
 
     if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-        target_link_libraries (eglretrace rt)
+        if (NOT ANDROID)
+            target_link_libraries (eglretrace rt)
+        endif ()
         if (READPROC_H_FOUND)
             target_link_libraries (eglretrace ${proc_LIBRARY})
         endif ()
diff --git a/retrace/glws_waffle.cpp b/retrace/glws_waffle.cpp
new file mode 100644
index 0000000..f0c44ab
--- /dev/null
+++ b/retrace/glws_waffle.cpp
@@ -0,0 +1,274 @@
+#include "os.hpp"
+#include "waffle.h"
+#include "glws.hpp"
+
+extern "C" {
+int waffle_gl_api = 0;
+};
+
+namespace glws {
+
+struct waffle_display *dpy;
+
+class WaffleVisual : public Visual
+{
+public:
+    struct waffle_config *config;
+
+    WaffleVisual() :
+        config(NULL)
+    {}
+
+    static WaffleVisual* createWaffleVisual(bool doubleBuffer, Profile profile)
+    {
+        int config_attrib_list[64], i(0);
+        WaffleVisual *visual = new WaffleVisual();
+
+        config_attrib_list[i++] = WAFFLE_CONTEXT_API;
+
+        switch (profile) {
+        case PROFILE_COMPAT:
+            if(!waffle_display_supports_context_api(dpy, WAFFLE_DL_OPENGL))
+            {
+                os::log("%s: !waffle_display_supports_context_api\n",
+                    __FILE__);
+
+                delete visual;
+                assert(0);
+                return NULL;
+            }
+
+            waffle_gl_api = config_attrib_list[i++] = WAFFLE_DL_OPENGL;
+            break;
+        case PROFILE_CORE:
+            os::log("%s: PROFILE_CORE no support\n", __FILE__);
+            delete visual;
+            assert(0);
+            return NULL;
+        case PROFILE_ES1:
+            if(!waffle_display_supports_context_api(dpy,
+                                                    WAFFLE_CONTEXT_OPENGL_ES1))
+            {
+                os::log("%s: !waffle_display_supports_context_api\n",
+                    __FILE__);
+
+                delete visual;
+                assert(0);
+                return NULL;
+            }
+
+            config_attrib_list[i++] = WAFFLE_CONTEXT_OPENGL_ES1;
+            waffle_gl_api = WAFFLE_DL_OPENGL_ES1;
+            break;
+        case PROFILE_ES2:
+            if(!waffle_display_supports_context_api(dpy,
+                                                    WAFFLE_CONTEXT_OPENGL_ES2))
+            {
+                os::log("%s: !waffle_display_supports_context_api\n",
+                    __FILE__);
+
+                delete visual;
+                assert(0);
+                return NULL;
+            }
+
+            config_attrib_list[i++] = WAFFLE_CONTEXT_OPENGL_ES2;
+            waffle_gl_api = WAFFLE_DL_OPENGL_ES2;
+            break;
+        default:
+            os::log("%s: Unknown context profile\n", __FILE__);
+            delete visual;
+            assert(0);
+            return NULL;
+        }
+
+        config_attrib_list[i++] = WAFFLE_RED_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_GREEN_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_BLUE_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_DEPTH_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_ALPHA_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_STENCIL_SIZE;
+        config_attrib_list[i++] = 8;
+        config_attrib_list[i++] = WAFFLE_DOUBLE_BUFFERED;
+        config_attrib_list[i++] = doubleBuffer;
+        config_attrib_list[i++] = 0;
+
+        visual->config = waffle_config_choose(dpy, config_attrib_list);
+        if (!visual->config)
+        {
+            os::log("Error in %s waffle_config_choose(dpy, " \
+                "config_attrib_list)\n", __FILE__);
+            delete visual;
+            assert(0);
+            return NULL;
+        }
+        return visual;
+    }
+
+    ~WaffleVisual() {
+        if (this->config != NULL)
+        {
+            waffle_config_destroy(this->config);
+            this->config = NULL;
+        }
+    }
+};
+
+class WaffleDrawable : public Drawable
+{
+public:
+
+    struct waffle_window *window;
+
+    WaffleDrawable(const Visual *vis, int w, int h, bool pbuffer) :
+        Drawable(vis, w, h, pbuffer)
+    {
+        const WaffleVisual *waffleVisual =
+            static_cast<const WaffleVisual *>(vis);
+
+        window = waffle_window_create(waffleVisual->config, w, h);
+    }
+
+    void
+    resize(int w, int h) {
+        if (w == width && h == height) {
+            return;
+        }
+
+        waffle_window_resize(window, w, h);
+        Drawable::resize(w, h);
+    }
+
+    void show(void) {
+        if (visible) {
+            return;
+        }
+
+        waffle_window_show(window);
+        Drawable::show();
+    }
+
+    void swapBuffers(void) {
+        waffle_window_swap_buffers(window);
+    }
+};
+
+class WaffleContext : public Context
+{
+public:
+    struct waffle_context *context;
+
+    WaffleContext(const Visual *vis, Profile prof) :
+        Context(vis, prof),
+        context(NULL)
+    {}
+
+    static WaffleContext* createWaffleContext(const Visual *vis, Profile prof)
+    {
+        WaffleContext *ctx = new WaffleContext(vis, prof);
+        const WaffleVisual *waffleVisual =
+            static_cast<const WaffleVisual *>(vis);
+
+        ctx->context = waffle_context_create(waffleVisual->config, NULL);
+        if (!ctx->context)
+        {
+            os::log("Error in %s waffle_context_create(config, NULL)\n",
+                   __FILE__);
+
+            assert(0);
+            return NULL;
+        }
+        return ctx;
+    }
+
+    ~WaffleContext() {
+        if( context != NULL )
+        {
+            waffle_context_destroy(context);
+            context = NULL;
+        }
+    }
+};
+
+/*
+ With waffle there is not too many events to look for..
+ */
+bool
+processEvents(void) {
+    return true;
+}
+
+void
+init(void) {
+    int i;
+    int waffle_init_attrib_list[3];
+
+    i = 0;
+    waffle_init_attrib_list[i++] = WAFFLE_PLATFORM;
+    waffle_init_attrib_list[i++] = WAFFLE_PLATFORM_ANDROID;
+    waffle_init_attrib_list[i++] = WAFFLE_NONE;
+
+    waffle_init(waffle_init_attrib_list);
+
+    dpy = waffle_display_connect(NULL);
+    if (!dpy)
+    {
+        os::log("No display!!\n");
+        assert(0);
+    }
+}
+
+void
+cleanup(void) {
+    waffle_display_disconnect(dpy);
+}
+
+Visual *
+createVisual(bool doubleBuffer, Profile profile) {
+    return WaffleVisual::createWaffleVisual(doubleBuffer, profile);
+}
+
+Drawable *
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+{
+    return new WaffleDrawable(visual, width, height, pbuffer);
+}
+
+Context *
+createContext(const Visual *visual, Context *shareContext, Profile profile,
+              bool debug)
+{
+    return WaffleContext::createWaffleContext(visual, profile );
+}
+
+bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+    if (!drawable || !context) {
+        /*
+           Following cause inside waffle
+           eglMakeCurrent(dpy, NULL, NULL, NULL) which equal to
+           eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, \
+                            EGL_NO_CONTEXT)
+           Lets hope things stay that way...
+        */
+        return waffle_make_current(dpy, NULL, NULL);
+    }
+    else {
+        WaffleDrawable *waffleDrawable =
+            static_cast<WaffleDrawable *>(drawable);
+
+        WaffleContext *waffleContext =
+            static_cast<WaffleContext *>(context);
+
+        return waffle_make_current(dpy, waffleDrawable->window,
+                                   waffleContext->context);
+    }
+}
+
+} /* namespace glws */
-- 
1.8.1.2



More information about the apitrace mailing list