#include "android_renderer_frontend.hpp" #include #include #include #include #include #include #include #include #include #include #include "android_renderer_backend.hpp" #include "attach_env.hpp" namespace mbgl { namespace android { // Forwards RendererObserver signals to the given // Delegate RendererObserver on the given RunLoop class ForwardingRendererObserver : public RendererObserver { public: ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_) : mailbox(std::make_shared(mapRunLoop)), delegate(delegate_, mailbox) {} ~ForwardingRendererObserver() { mailbox->close(); } void onInvalidate() override { delegate.invoke(&RendererObserver::onInvalidate); } void onResourceError(std::exception_ptr err) override { delegate.invoke(&RendererObserver::onResourceError, err); } void onWillStartRenderingMap() override { delegate.invoke(&RendererObserver::onWillStartRenderingMap); } void onWillStartRenderingFrame() override { delegate.invoke(&RendererObserver::onWillStartRenderingFrame); } void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded, bool placementChanged, const gfx::RenderingStats& stats) override { void (RendererObserver::*f)( RenderMode, bool, bool, const gfx::RenderingStats&) = &RendererObserver::onDidFinishRenderingFrame; delegate.invoke(f, mode, repaintNeeded, placementChanged, stats); } void onDidFinishRenderingMap() override { delegate.invoke(&RendererObserver::onDidFinishRenderingMap); } void onStyleImageMissing(const std::string& id, const StyleImageMissingCallback& done) override { delegate.invoke(&RendererObserver::onStyleImageMissing, id, done); } void onRemoveUnusedStyleImages(const std::vector& ids) override { delegate.invoke(&RendererObserver::onRemoveUnusedStyleImages, ids); } void onPreCompileShader(mbgl::shaders::BuiltIn id, mbgl::gfx::Backend::Type type, const std::string& additionalDefines) override { delegate.invoke(&RendererObserver::onPreCompileShader, id, type, additionalDefines); } void onPostCompileShader(mbgl::shaders::BuiltIn id, mbgl::gfx::Backend::Type type, const std::string& additionalDefines) override { delegate.invoke(&RendererObserver::onPostCompileShader, id, type, additionalDefines); } void onShaderCompileFailed(mbgl::shaders::BuiltIn id, mbgl::gfx::Backend::Type type, const std::string& additionalDefines) override { delegate.invoke(&RendererObserver::onShaderCompileFailed, id, type, additionalDefines); } void onGlyphsLoaded(const mbgl::FontStack& stack, const mbgl::GlyphRange& range) override { delegate.invoke(&RendererObserver::onGlyphsLoaded, stack, range); } void onGlyphsError(const mbgl::FontStack& stack, const mbgl::GlyphRange& range, std::exception_ptr ex) override { delegate.invoke(&RendererObserver::onGlyphsError, stack, range, ex); } void onGlyphsRequested(const mbgl::FontStack& stack, const mbgl::GlyphRange& range) override { delegate.invoke(&RendererObserver::onGlyphsRequested, stack, range); } void onTileAction(TileOperation op, const OverscaledTileID& id, const std::string& sourceID) override { delegate.invoke(&RendererObserver::onTileAction, op, id, sourceID); } void onRenderError(std::exception_ptr err) override { delegate.invoke(&RendererObserver::onRenderError, err); } private: std::shared_ptr mailbox; ActorRef delegate; }; AndroidRendererFrontend::AndroidRendererFrontend(Private, jni::JNIEnv& env, const jni::Object& mapRendererObj) : mapRenderer(MapRenderer::getNativePeer(env, mapRendererObj)), mapRunLoop(util::RunLoop::Get()) {} std::shared_ptr AndroidRendererFrontend::create( jni::JNIEnv& env, const jni::Object& mapRendererObj) { auto ptr = std::make_shared(Private(), env, mapRendererObj); ptr->init(env, mapRendererObj); return ptr; } void AndroidRendererFrontend::init(jni::JNIEnv& env, const jni::Object& mapRendererObj) { auto weakMapRenderer = std::make_shared>>(env, mapRendererObj); updateAsyncTask = std::make_unique( [weakSelf = weak_from_this(), weakMapRenderer = std::move(weakMapRenderer)]() { if (auto self = weakSelf.lock()) { try { android::UniqueEnv _env = android::AttachEnv(); auto mapRendererRef = weakMapRenderer->get(*_env); if (mapRendererRef) { self->mapRenderer.update(std::move(self->updateParams)); self->mapRenderer.requestRender(*_env, mapRendererRef); } } catch (const std::exception& exception) { Log::Error(Event::Android, std::string("AndroidRendererFrontend::updateAsyncTask failed: ") + exception.what()); } } }); } AndroidRendererFrontend::~AndroidRendererFrontend() = default; void AndroidRendererFrontend::reset() { mapRenderer.reset(); } void AndroidRendererFrontend::setObserver(RendererObserver& observer) { assert(util::RunLoop::Get()); // Don't call the Renderer directly, but use MapRenderer#setObserver to make sure // the Renderer may be re-initialised without losing the RendererObserver reference. mapRenderer.setObserver(std::make_unique(*mapRunLoop, observer)); } void AndroidRendererFrontend::update(std::shared_ptr params) { MLN_TRACE_FUNC(); updateParams = std::move(params); updateAsyncTask->send(); } const TaggedScheduler& AndroidRendererFrontend::getThreadPool() const { return mapRenderer.getThreadPool(); } void AndroidRendererFrontend::setTileCacheEnabled(bool enabled) { mapRenderer.actor().invoke(&Renderer::setTileCacheEnabled, enabled); } bool AndroidRendererFrontend::getTileCacheEnabled() const { return mapRenderer.actor().ask(&Renderer::getTileCacheEnabled).get(); } void AndroidRendererFrontend::reduceMemoryUse() { mapRenderer.actor().invoke(&Renderer::reduceMemoryUse); } std::vector AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) const { // Waits for the result from the orchestration thread and returns return mapRenderer.actor().ask(&Renderer::querySourceFeatures, sourceID, options).get(); } void AndroidRendererFrontend::setFeatureState(const std::string& sourceID, const std::optional& sourceLayerID, const std::string& featureID, const FeatureState& state) const { mapRenderer.actor().invoke(&Renderer::setFeatureState, sourceID, sourceLayerID, featureID, state); } FeatureState AndroidRendererFrontend::getFeatureState(const std::string& sourceID, const std::optional& sourceLayerID, const std::string& featureID) const { auto getFeatureState = static_cast&, const std::string&) const>(&Renderer::getFeatureState); return mapRenderer.actor().ask(getFeatureState, sourceID, sourceLayerID, featureID).get(); } void AndroidRendererFrontend::removeFeatureState(const std::string& sourceID, const std::optional& sourceLayerID, const std::optional& featureID, const std::optional& stateKey) const { mapRenderer.actor().invoke(&Renderer::removeFeatureState, sourceID, sourceLayerID, featureID, stateKey); } std::vector AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box, const RenderedQueryOptions& options) const { // Select the right overloaded method std::vector (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures; // Waits for the result from the orchestration thread and returns return mapRenderer.actor().ask(fn, box, options).get(); } std::vector AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point, const RenderedQueryOptions& options) const { // Select the right overloaded method std::vector (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures; // Waits for the result from the orchestration thread and returns return mapRenderer.actor().ask(fn, point, options).get(); } AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box, const std::chrono::milliseconds& timeout) const { // Waits for the result from the orchestration thread and returns auto future = mapRenderer.actor().ask(&Renderer::queryPointAnnotations, box); if (future.wait_for(timeout) != std::future_status::ready) { return {}; } return future.get(); } AnnotationIDs AndroidRendererFrontend::queryShapeAnnotations(const ScreenBox& box, const std::chrono::milliseconds& timeout) const { // Waits for the result from the orchestration thread and returns auto future = mapRenderer.actor().ask(&Renderer::queryShapeAnnotations, box); if (future.wait_for(timeout) != std::future_status::ready) { return {}; } return future.get(); } FeatureExtensionValue AndroidRendererFrontend::queryFeatureExtensions( const std::string& sourceID, const Feature& feature, const std::string& extension, const std::string& extensionField, const std::optional>& args) const { return mapRenderer.actor() .ask(&Renderer::queryFeatureExtensions, sourceID, feature, extension, extensionField, args) .get(); } } // namespace android } // namespace mbgl