[PATCH] Android: Port eglretracer for Android

Juha-Pekka Heikkila juha-pekka.heikkila at linux.intel.com
Mon Sep 2 06:12:01 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>
---
 cmake/FindWaffle.cmake  |  38 +++++++++
 retrace/CMakeLists.txt  |  26 ++++++
 retrace/glws_waffle.cpp | 220 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 284 insertions(+)
 create mode 100644 cmake/FindWaffle.cmake
 create mode 100644 retrace/glws_waffle.cpp

diff --git a/cmake/FindWaffle.cmake b/cmake/FindWaffle.cmake
new file mode 100644
index 0000000..e2f6a84
--- /dev/null
+++ b/cmake/FindWaffle.cmake
@@ -0,0 +1,38 @@
+# - try to find Waffle include dirs and library
+
+if (ANDROID)
+    set (Android_root_path "$ENV{OUT}")
+	if (Android_root_path)
+		set (Waffle_INC_SEARCH_PATH "$ENV{OUT}/obj/include/waffle-1"
+			"$ENV{OUT}/obj/lib"
+			"$ENV{ANDROID_BUILD_TOP}/external/waffle"
+		)
+
+		set (Waffle_LIB_SEARCH_PATH "$ENV{OUT}/obj/lib")
+	endif ()
+
+	find_path (Waffle_INCLUDE_DIR waffle.h
+		PATHS ${Waffle_INC_SEARCH_PATH}
+		DOC "The directory where waffle.h resides"
+		NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
+		)
+
+	find_library (Waffle_LIBRARY waffle-1
+		PATHS ${Waffle_LIB_SEARCH_PATH}
+		DOC "The directory where libwaffle-1 resides"
+		NO_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
+		)
+
+	if (Waffle_INCLUDE_DIR AND Waffle_LIBRARY)
+		set (Waffle_FOUND 1)
+	endif (Waffle_INCLUDE_DIR AND Waffle_LIBRARY)
+
+	mark_as_advanced (
+		Waffle_INCLUDE_DIR
+		Waffle_LIBRARY
+	)
+endif ()
+
+mark_as_advanced (
+	Waffle_FOUND
+)
diff --git a/retrace/CMakeLists.txt b/retrace/CMakeLists.txt
index 913c23e..8217f68 100644
--- a/retrace/CMakeLists.txt
+++ b/retrace/CMakeLists.txt
@@ -39,6 +39,13 @@ add_library (retrace_common STATIC
     retrace_swizzle.cpp
     json.cpp
 )
+
+if (ANDROID)
+##
+# if waffle is found eglretracer will be build for Android.
+    find_package (Waffle)
+endif ()
+
 target_link_libraries (retrace_common
     image
     common
@@ -138,6 +145,25 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
     install (TARGETS eglretrace RUNTIME DESTINATION bin) 
 endif ()
 
+if (ENABLE_EGL AND ANDROID AND Waffle_FOUND)
+    add_executable (eglretrace
+        glws_waffle.cpp
+    )
+
+    add_dependencies (eglretrace glproc)
+    include_directories (${Waffle_INCLUDE_DIR})
+
+    target_link_libraries (eglretrace
+        retrace_common
+        glretrace_common
+        glproc_egl
+        dl
+        ${Waffle_LIBRARY}
+    )
+    target_link_libraries (eglretrace ${proc_LIBRARY})
+    install (TARGETS eglretrace RUNTIME DESTINATION bin)
+endif ()
+
 if (WIN32)
     if (DirectX_D3D8_INCLUDE_DIR) 
         include_directories (BEFORE SYSTEM ${DirectX_D3D8_INCLUDE_DIR})
diff --git a/retrace/glws_waffle.cpp b/retrace/glws_waffle.cpp
new file mode 100644
index 0000000..c10c01e
--- /dev/null
+++ b/retrace/glws_waffle.cpp
@@ -0,0 +1,220 @@
+#include "os.hpp"
+#include "waffle.h"
+#include "glws.hpp"
+
+namespace glws {
+
+struct waffle_display *dpy;
+
+class WaffleVisual : public Visual
+{
+public:
+    struct waffle_config *config;
+
+    WaffleVisual(waffle_config *cfg) :
+        config (cfg)
+    {}
+
+    ~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,
+        struct waffle_window *win) :
+        Drawable (vis, w, h, pbuffer),
+        window (win)
+    {}
+
+    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() {
+        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("%s: waffle_display_connect(NULL) == NULL\n", __FILE__);
+        os::abort();
+    }
+}
+
+void
+cleanup(void) {
+    waffle_display_disconnect(dpy);
+}
+
+Visual *
+createVisual(bool doubleBuffer, Profile profile) {
+    struct waffle_config *cfg;
+    int config_attrib_list[64], i(0), waffle_profile;
+
+    switch (profile) {
+    case PROFILE_ES1:
+        waffle_profile = WAFFLE_CONTEXT_OPENGL_ES1;
+        break;
+    case PROFILE_ES2:
+        waffle_profile = WAFFLE_CONTEXT_OPENGL_ES2;
+        break;
+    default:
+        os::log("%s: Unsupported context profile\n", __FILE__);
+        os::abort();
+        return NULL;
+    }
+
+    if(!waffle_display_supports_context_api(dpy, waffle_profile)) {
+        os::log("%s: !waffle_display_supports_context_api\n",
+            __FILE__);
+
+        os::abort();
+        return NULL;
+    }
+
+    config_attrib_list[i++] = WAFFLE_CONTEXT_API;
+    config_attrib_list[i++] = waffle_profile;
+    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;
+
+    cfg = waffle_config_choose(dpy, config_attrib_list);
+    if (!cfg)
+    {
+        os::log("Error in %s waffle_config_choose(dpy, " \
+            "config_attrib_list)\n", __FILE__);
+        os::abort();
+        return NULL;
+    }
+    return new WaffleVisual(cfg);
+}
+
+Drawable *
+createDrawable(const Visual *visual, int width, int height, bool pbuffer)
+{
+    struct waffle_window *window;
+    const WaffleVisual *waffleVisual =
+        static_cast<const WaffleVisual *>(visual);
+
+    window = waffle_window_create(waffleVisual->config, width, height);
+    return new WaffleDrawable(visual, width, height, pbuffer, window);
+}
+
+Context *
+createContext(const Visual *visual, Context *shareContext, Profile profile,
+              bool debug)
+{
+    struct waffle_context *context;
+    const WaffleVisual *waffleVisual =
+        static_cast<const WaffleVisual *>(visual);
+
+    if (shareContext != NULL) {
+        os::log("Error in %s createContext, shareContext != NULL\n", __FILE__);
+        os::abort();
+        return NULL;
+    }
+
+    context = waffle_context_create(waffleVisual->config, NULL);
+    if (!context) {
+        os::log("Error in %s waffle_context_create(config, NULL)\n",
+               __FILE__);
+
+        os::abort();
+        return NULL;
+    }
+    return new WaffleContext(visual, profile, context);
+}
+
+bool
+makeCurrent(Drawable *drawable, Context *context)
+{
+    if (!drawable || !context) {
+        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