Update libtangram and fix crashes 67/136067/2
authorMatt Blair <blair1618@gmail.com>
Wed, 28 Jun 2017 02:15:36 +0000 (22:15 -0400)
committerMatt Blair <blair1618@gmail.com>
Thu, 29 Jun 2017 03:30:32 +0000 (23:30 -0400)
 - Update libtangram to Tangram ES 0.7.0 release, built from Tangram ES commit 4dcdca26b625da545d65a795775351c64d83a2ba
 - fix: do not assign null to std::string
 - fix: use thread_safe_call_sync instead of async
 - prevent maps_service_instance_count go below zero
 - use unique_ptr<Map>, shutdown Map before GL context
 - poll for renderRequests from non-ui threads to avoid deadlocks

Change-Id: Idd2818754ed65ce2013e4da50578455204af67fb

lib/aarch64/libtangram.so
lib/arm/libtangram.so
lib/i586/libtangram.so
lib/x86_64/libtangram.so
src/mapzen/tangram_view.cpp
src/mapzen/tangram_view.hpp
src/mapzen_plugin.c

index 0a0559c..6065adc 100755 (executable)
Binary files a/lib/aarch64/libtangram.so and b/lib/aarch64/libtangram.so differ
index c81a33f..3d8e693 100755 (executable)
Binary files a/lib/arm/libtangram.so and b/lib/arm/libtangram.so differ
index 128dd35..40aa675 100755 (executable)
Binary files a/lib/i586/libtangram.so and b/lib/i586/libtangram.so differ
index 93efedb..fe04ed2 100755 (executable)
Binary files a/lib/x86_64/libtangram.so and b/lib/x86_64/libtangram.so differ
index e7e5e90..45b8db5 100644 (file)
@@ -30,6 +30,8 @@ extern "C" {
 #include <string>
 #include <cstdio>
 
+#include <sys/syscall.h> // SYS_gettid
+
 #define NORMAL_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/bubble-wrap/bubble-wrap.yaml"
 #define TERRAIN_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/walkabout-style/walkabout-style.yaml"
 
@@ -106,19 +108,40 @@ mapzen_error_e TangramView::create(maps_view_h view, maps_plugin_map_view_ready_
        Tangram::UrlClient::Options urlOptions;
        char* proxyAddress = NULL;
        get_proxy_address(&proxyAddress);
-       urlOptions.proxyAddress = proxyAddress;
-       if (proxyAddress)
+       if (proxyAddress) {
+               urlOptions.proxyAddress = proxyAddress;
                free(proxyAddress);
+       }
+
+       m_platform = std::make_shared<Tangram::TizenPlatform>(urlOptions);
+
+       m_uiThreadId = syscall(SYS_gettid);
 
-       auto platform = std::shared_ptr<Tangram::TizenPlatform>(new Tangram::TizenPlatform(urlOptions));
-       //auto platform = std::make_shared<Tangram::TizenPlatform>();
+       m_platform->setRenderCallbackFunction([&]() {
 
-       platform->setRenderCallbackFunction([=](){
-               ecore_main_loop_thread_safe_call_async(&renderingCb, m_image);
+               if (m_uiThreadId == syscall(SYS_gettid)) {
+                       m_dirty = false;
+                       evas_object_image_pixels_dirty_set(m_image, EINA_TRUE);
+               } else {
+                       m_dirty = true;
+               }
        });
 
+       // NB: Since there is no safe way to use ecore_main_loop_thread_safe_call_async in a
+       // module that could be unloaded at runtime we use polling to check on the mainloop
+       // whether a render request came in.
+       // TODO only run timer when async tasks (Tile- and Scene-Loading) are in progress.
+       m_renderRequestTimer = ecore_timer_add(0.05, [](void *data){
+               auto tv = static_cast<TangramView*>(data);
+               if (tv->m_dirty) {
+                       tv->m_dirty = false;
+                       evas_object_image_pixels_dirty_set((Evas_Object*)tv->m_image, EINA_TRUE);
+               }
+               return EINA_TRUE;
+       }, this);
+
        // Set up the tangram map.
-       m_map = new Tangram::Map(platform);
+       m_map.reset(new Tangram::Map(m_platform));
 
        float scaleFactor = elm_config_scale_get();
        MAPS_LOGD("evas_gl_context_create() set PixelScale %f", scaleFactor);
@@ -198,6 +221,11 @@ mapzen_error_e TangramView::destroy(maps_view_h view)
        m_isInitialized = false;
        m_sceneLoaded = false;
 
+       if (m_renderRequestTimer) {
+               ecore_timer_del(m_renderRequestTimer);
+               m_renderRequestTimer = nullptr;
+       }
+
        if (m_image) {
                evas_object_image_pixels_get_callback_set(m_image, nullptr, nullptr);
        }
@@ -206,6 +234,16 @@ mapzen_error_e TangramView::destroy(maps_view_h view)
                if (m_surface && m_context) {
                        evas_gl_make_current(m_gl, m_surface, m_context);
                }
+       }
+
+       if (m_map) {
+               removeAllObjects();
+
+               m_map.reset();
+               m_platform.reset();
+       }
+
+       if (m_gl) {
                if (m_surface) {
                        evas_object_image_native_surface_set(m_image, nullptr);
                        evas_gl_surface_destroy(m_gl, m_surface);
@@ -221,14 +259,6 @@ mapzen_error_e TangramView::destroy(maps_view_h view)
                evas_gl_config_free(m_config);
        }
 
-       if (m_map) {
-               static_cast<Tangram::TizenPlatform*>(m_map->getPlatform().get())->setRenderCallbackFunction(nullptr);
-               removeAllObjects();
-               delete m_map;
-               m_map = nullptr;
-       }
-
-
        return MAPZEN_ERROR_NONE;
 }
 
@@ -959,7 +989,13 @@ void TangramView::pixelGetCb(void *data, Evas_Object *obj)
 {
        TangramView *tv = nullptr;
        int maps_error = maps_view_get_maps_plugin_view_handle(data, (void**)&tv);
-       if (maps_error != MAPS_ERROR_NONE || !tv || !tv->m_gl || !tv->m_surface || !tv->m_context) {
+       if (maps_error != MAPS_ERROR_NONE || !tv) {
+               return;
+       }
+
+       tv->m_dirty = false;
+
+       if (!tv->m_gl || !tv->m_surface || !tv->m_context) {
                return;
        }
 
@@ -973,10 +1009,3 @@ void TangramView::pixelGetCb(void *data, Evas_Object *obj)
                MAPS_LOGD("tv->m_map is null, in pixelGelCb");
        }
 }
-
-void TangramView::renderingCb(void *data) {
-       if (!data) {
-               return;
-       }
-       evas_object_image_pixels_dirty_set((Evas_Object*)data, EINA_TRUE);
-}
index fe7b9c4..0a1c4f2 100644 (file)
 #include <Ecore_Evas.h>
 #include <Evas_GL.h>
 #include <map>
+#include <memory>
 #include <mutex>
 
 #include "mapzen_types.h"
 #include "tangram/util/types.h"
 
+#include <sys/types.h> // pid_t, gettid()
+
 namespace Tangram {
        class Map;
+       class TizenPlatform;
 }
 
 typedef std::map<maps_view_object_h, Tangram::MarkerID> MapViewObjects;
@@ -79,18 +83,22 @@ private:
 
        static void sceneLoadedCb(void *data);
        static void readyMapCb(void *view);
-       static void renderingCb(void *data);
        static void pixelGetCb(void *data, Evas_Object *obj);
        // Emplaces the lng/lat from `coordinate` to `user_data` (Tangram::Coordinates)
        static bool emplaceCoord(int index, maps_coordinates_h coordinate, void *user_data);
 
-       Tangram::Map *m_map = nullptr;
+       std::unique_ptr<Tangram::Map> m_map;
+       std::shared_ptr<Tangram::TizenPlatform> m_platform;
+
+       pid_t m_uiThreadId = 0;
+
        Evas_Object *m_image = nullptr;
        Evas_GL_Context *m_context = nullptr;
        Evas_GL_Surface *m_surface = nullptr;
        Evas_GL_Config *m_config = nullptr;
        Evas_GL *m_gl = nullptr;
        Evas_GL_API *m_api = nullptr;
+       Ecore_Timer *m_renderRequestTimer = nullptr;
 
        bool m_isInitialized = false;
        bool m_publicTransitEnabled = false;
@@ -99,6 +107,7 @@ private:
        std::string m_language = "en";
        std::string m_providerKey = "";
        bool m_isProviderKeySet = false;
+       bool m_dirty = false;
 
        int m_x = 0;
        int m_y = 0;
index 24f0698..702d75a 100644 (file)
@@ -173,6 +173,10 @@ EXPORT_API int maps_plugin_shutdown(maps_plugin_h plugin)
        if (!plugin)
                return MAPS_ERROR_INVALID_PARAMETER;
 
+       if (__maps_service_instance_count == 0) {
+               return MAPS_ERROR_INVALID_PARAMETER;
+       }
+
        __maps_service_instance_count--;
 
        int ret = MAPS_ERROR_NONE;