[PATCH] Android: glretracer for Android.

Juha-Pekka Heikkilä juha-pekka.heikkila at linux.intel.com
Fri Jun 28 01:16:30 PDT 2013


Hi,

thanks for looking at the patch and for the comments. I'm away to enjoy
the sun for a while thus the fixes will be delayed few weeks. :) Just
quick comments below.

The final target for me with this is to have the remote retracing from
qapitrace to work on Android over adb instead of ssh. I did Waffle port
for Android thus I was familiar to use it here also. As a side benefit by
using Waffle here one could also have retracing working on top of Wayland
with very little extra work.



On Thu, June 27, 2013 8:29 pm, Alexander Monakov wrote:
> On Thu, 27 Jun 2013, Juha-Pekka Heikkila wrote:
>> 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)
>
> Looks unused.
>

True, it is leftovers from experimenting with cmake.

>>
>>  # 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 ()
>
> I don't see why you need this change.


Things needed here are located in other libraries on Android thanks to
bionic. I was getting errors by having Threads package included thus left
it out.


>
>> +
>> +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
>
> I don't see why you're modifying glproc_gl.cpp; only glproc_egl should
> come
> into play on Android.


aha. This is where I seem to have been confused. Executable I run on
Android is glretracer, not eglretracer. I need to double check this
because it matters on where 'waffle_dl_sym' call is placed.


>
>>
>>  #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 ()
>> +
>
> Unrelated change?


True, this was related to the Threads package removal but it is in wrong
place here.


>
>>  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 ()
>
> Why do you need to suppress this cmake warning?
>


This possibly is due to my lack of experience with cmake. I was getting
error on the way I include Waffle here and did not see other way around.
This did cause the compilation to stop so I had to disable the warning.


>> +
>> +    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
>
> Hm.  Do you need both glretrace and eglretrace on Android?


As mention above, I seem to have had some mixup. I was running glretrace
on Android, not eglretrace.


>
>
>>          ${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;
>
> createVisual code should probably go here.
>


True


>> +    }
>> +
>> +    ~WaffleVisual() {
>> +    waffle_config_destroy(this->config);
>
> Watch indentation.
>
>> +    }
>> +};
>> +
>> +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");
>
> Can you use os::log instead?


yes, need to replace all the printfs to os::log. Here should probably also
do something like exit() or so.


>
>> +    }
>> +}
>> +
>> +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...
>> +         */
>
> I think this comment can be safely removed :)
>


I did initially put the comment here because this is undocumented
behaviour on Waffle. As I was looking at Waffle code for this I realized
the path was not 100% trivial inside Waffle.


>> +        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 */
>>
>



More information about the apitrace mailing list