[PATCH] Android: glretracer for Android.

Juha-Pekka Heikkila juha-pekka.heikkila at linux.intel.com
Thu Jun 27 04:17:12 PDT 2013


I made the glretracer to work with Android using Waffle library.
There is still issue with multiple windows on Android, otherwise this
seems to work nicely. I am not so experienced with cmake thus if there
is something that look weird with the CMakeLists it probably is weird.

I limited glws_waffle.cpp strictly to Android only but it probably would
start to work quite easily also on desktop. Before Waffle port of glretrace
for desktop could work Waffle need waffle_window_resize API call to be
implemented for other plarforms than Android.

To build for Android Waffle need to be build first.
Waffle can be obtained from:
http://cgit.freedesktop.org/~chadversary/waffle/

Make sure these patches are in place for Waffle before compiling
(at time of writing they are still stuck on the list)
http://lists.freedesktop.org/archives/waffle/2013-June/000167.html
http://lists.freedesktop.org/archives/waffle/2013-June/000168.html

Known issues:
glretracer seems to launch multiple windows with some traces from
Android. These multiple windows sometime 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>
---
 CMakeLists.txt          |  26 +++++-
 dispatch/glproc_gl.cpp  |   8 ++
 retrace/CMakeLists.txt  | 120 +++++++++++++++++++------
 retrace/glws_waffle.cpp | 227 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 354 insertions(+), 27 deletions(-)
 create mode 100644 retrace/glws_waffle.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d819be2..1642b01 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,6 @@
 cmake_minimum_required (VERSION 2.8)
 
+include(CheckIncludeFiles)
 
 # Use clang on MacOSX. gcc doesn't support __thread key, and Apple has
 # abandoned it for clang.  This must be done before the project is defined.
@@ -61,7 +62,18 @@ else ()
 endif ()
 
 find_host_package (PythonInterp REQUIRED)
-find_package (Threads)
+if (NOT ANDROID)
+    find_package (Threads)
+endif ()
+
+if (ANDROID)
+#########
+# 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 )
+
+    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})
+endif ()
 
 if (ENABLE_GUI)
     if (NOT (ENABLE_GUI STREQUAL "AUTO"))
@@ -294,6 +306,12 @@ include_directories (
     ${CMAKE_CURRENT_SOURCE_DIR}/common
 )
 
+#if (ANDROID)
+#    include_directories ( BEFORE
+#        $ENV{ANDROID_BUILD_TOP}/external/ltp/tools/top-LTP
+#    )
+#endif ()
+
 if (WIN32)
     set (os os_win32.cpp)
     set (glws_os glws_wgl.cpp)
@@ -302,7 +320,11 @@ else ()
     if (APPLE)
         set (glws_os glws_cocoa.mm)
     else ()
-        set (glws_os glws_glx.cpp)
+        if (ANDROID)
+            set (glws_os glws_waffle.cpp)
+        else ()
+            set (glws_os glws_glx.cpp)
+        endif ()
     endif ()
 endif ()
 
diff --git a/dispatch/glproc_gl.cpp b/dispatch/glproc_gl.cpp
index 2516dab..f793d1c 100644
--- a/dispatch/glproc_gl.cpp
+++ b/dispatch/glproc_gl.cpp
@@ -26,6 +26,9 @@
 
 #include "glproc.hpp"
 
+#if defined(__ANDROID__)
+#include <waffle.h>
+#endif
 
 #if !defined(_WIN32)
 #include <unistd.h> // for symlink
@@ -272,7 +275,12 @@ _getPublicProcAddress(const char *procName)
 void *
 _getPrivateProcAddress(const char *procName)
 {
+#ifdef __ANDROID__
+    extern int waffle_gl_api;
+    return waffle_dl_sym(waffle_gl_api, procName);
+#else
     return (void *)_glXGetProcAddressARB((const GLubyte *)procName);
+#endif
 }
 
 
diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt
index 78cceae..c2de4fc 100644
--- a/retrace/CMakeLists.txt
+++ b/retrace/CMakeLists.txt
@@ -9,6 +9,12 @@ include_directories (
     ${CMAKE_SOURCE_DIR}/image
 )
 
+if (ANDROID)
+    include_directories ( BEFORE
+        $ENV{ANDROID_BUILD_TOP}/external/ltp/tools/top-LTP
+    )
+endif ()
+
 add_definitions (-DRETRACE)
 
 add_custom_command (
@@ -40,13 +46,55 @@ add_library (retrace_common STATIC
     retrace_swizzle.cpp
     json.cpp
 )
-target_link_libraries (retrace_common
-    image
-    common
-    ${ZLIB_LIBRARIES}
-    ${SNAPPY_LIBRARIES}
-    ${GETOPT_LIBRARIES}
-)
+
+if (ANDROID)
+
+#########
+# 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
+    )
+
+    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})
+
+    if (POLICY CMP0016)
+        cmake_policy (PUSH)
+        cmake_policy (SET CMP0016 OLD)
+    endif ()
+
+    target_link_libraries (retrace_common
+        image
+        common
+        ${ZLIB_LIBRARIES}
+        ${SNAPPY_LIBRARIES}
+        ${GETOPT_LIBRARIES}
+        ${Waffle}
+    )
+
+    if (POLICY CMP0016)
+        cmake_policy (POP)
+    endif ()
+
+
+else ()
+    target_link_libraries (retrace_common
+        image
+        common
+        ${ZLIB_LIBRARIES}
+        ${SNAPPY_LIBRARIES}
+        ${GETOPT_LIBRARIES}
+    )
+endif ()
 
 add_library (glretrace_common STATIC
     glretrace_gl.cpp
@@ -68,7 +116,7 @@ target_link_libraries (glretrace_common
 )
 
 
-if (WIN32 OR APPLE OR X11_FOUND)
+if (WIN32 OR APPLE OR X11_FOUND OR ANDROID)
     add_executable (glretrace
         ${glws_os}
     )
@@ -90,19 +138,31 @@ if (WIN32 OR APPLE OR X11_FOUND)
                 #"-framework OpenGL" # CGL*
             )
         else ()
-            target_link_libraries (glretrace ${X11_X11_LIB})
+            if (NOT ANDROID)
+                target_link_libraries (glretrace ${X11_X11_LIB})
+            endif()
         endif ()
 
-        target_link_libraries (glretrace
-            # gdb doesn't like when pthreads is loaded through dlopen (which happens
-            # when dlopen'ing libGL), so link pthreads to avoid this issue.  See also
-            # http://stackoverflow.com/questions/2702628/gdb-cannot-find-new-threads-generic-error
-            ${CMAKE_THREAD_LIBS_INIT}
-            dl
-        )
+
+        if (ANDROID)
+            target_link_libraries (glretrace
+                dl
+            )
+        else()
+            target_link_libraries (glretrace
+                # gdb doesn't like when pthreads is loaded through dlopen (which happens
+                # when dlopen'ing libGL), so link pthreads to avoid this issue.  See also
+                # http://stackoverflow.com/questions/2702628/gdb-cannot-find-new-threads-generic-error
+                ${CMAKE_THREAD_LIBS_INIT}
+                dl
+            )
+        endif ()
 
         if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
-            target_link_libraries (glretrace rt)
+            if (NOT ANDROID)
+                target_link_libraries (glretrace rt)
+            endif ()
+
             if (READPROC_H_FOUND)
                 target_link_libraries (glretrace ${proc_LIBRARY})
             endif ()
@@ -120,14 +180,24 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
 
     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
+            cutils
+            dl
+        )
+    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)
diff --git a/retrace/glws_waffle.cpp b/retrace/glws_waffle.cpp
new file mode 100644
index 0000000..d77cff0
--- /dev/null
+++ b/retrace/glws_waffle.cpp
@@ -0,0 +1,227 @@
+#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()
+    {
+    this->config = NULL;
+    }
+
+    ~WaffleVisual() {
+    waffle_config_destroy(this->config);
+    }
+};
+
+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,
+                  struct waffle_context *ctx) :
+        Context(vis, prof),
+        context(ctx)
+    {}
+
+    ~WaffleContext() {
+    }
+};
+
+/*
+ * 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)
+    {
+        printf("no display!!\n");
+    }
+}
+
+void
+cleanup(void) {
+    waffle_display_disconnect(dpy);
+}
+
+Visual *
+createVisual(bool doubleBuffer, Profile profile) {
+    WaffleVisual *visual = new WaffleVisual();
+
+    int config_attrib_list[64], i;
+
+    i = 0;
+    config_attrib_list[i++] = WAFFLE_CONTEXT_API;
+
+    switch (profile) {
+    case PROFILE_COMPAT:
+        if(!waffle_display_supports_context_api(dpy, WAFFLE_DL_OPENGL))
+            return NULL;
+        waffle_gl_api = config_attrib_list[i++] = WAFFLE_DL_OPENGL;
+        break;
+    case PROFILE_CORE:
+        assert(0);
+        return NULL;
+    case PROFILE_ES1:
+        if(!waffle_display_supports_context_api(dpy,
+                                                WAFFLE_CONTEXT_OPENGL_ES1))
+            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))
+            return NULL;
+
+        config_attrib_list[i++] = WAFFLE_CONTEXT_OPENGL_ES2;
+        waffle_gl_api = WAFFLE_DL_OPENGL_ES2;
+        break;
+    default:
+        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++] = true;
+    config_attrib_list[i++] = 0;
+
+    visual->config = waffle_config_choose(dpy, config_attrib_list);
+    if (!visual->config)
+    {
+        printf("Error in %s waffle_config_choose(dpy, config_attrib_list)\n",
+               __FILE__);
+        return NULL;
+    }
+
+    return visual;
+}
+
+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)
+{
+    struct waffle_context *ctx;
+    const WaffleVisual *waffleVisual =
+        static_cast<const WaffleVisual *>(visual);
+
+    ctx = waffle_context_create(waffleVisual->config, NULL);
+    if (!ctx)
+    {
+        printf("Error in %s waffle_context_create(config, NULL)\n",
+               __FILE__);
+        return NULL;
+    }
+    return new WaffleContext(visual, profile, ctx );
+}
+
+bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+
+    if (!drawable || !context) {
+        /*
+         * hm.
+         * 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