From 3832f8d0d8194b81ea34a045e19b0d5bc7a89e25 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Tue, 13 Jun 2017 10:50:16 +0300 Subject: [core] renderer interface --- bin/render.cpp | 7 +- cmake/core-files.cmake | 8 +- cmake/render.cmake | 2 + cmake/test-files.cmake | 2 + include/mbgl/map/backend.hpp | 9 +- include/mbgl/map/map.hpp | 25 +- include/mbgl/map/query.hpp | 43 --- include/mbgl/renderer/query.hpp | 43 +++ include/mbgl/renderer/renderer.hpp | 54 ++++ include/mbgl/renderer/renderer_frontend.hpp | 31 ++ platform/android/config.cmake | 2 + platform/default/mbgl/gl/headless_backend.cpp | 6 +- platform/default/mbgl/gl/headless_backend.hpp | 2 - .../mbgl/renderer/async_renderer_frontend.cpp | 38 +++ .../mbgl/renderer/async_renderer_frontend.hpp | 35 +++ platform/node/src/node_map.cpp | 1 - src/mbgl/annotation/annotation_manager.cpp | 1 - src/mbgl/geometry/feature_index.cpp | 2 +- src/mbgl/map/map.cpp | 349 ++++++--------------- src/mbgl/renderer/painter.cpp | 2 - src/mbgl/renderer/painter.hpp | 6 +- src/mbgl/renderer/render_style.cpp | 2 +- src/mbgl/renderer/renderer.cpp | 78 +++++ src/mbgl/renderer/renderer_impl.cpp | 151 +++++++++ src/mbgl/renderer/renderer_impl.hpp | 65 ++++ src/mbgl/renderer/renderer_observer.hpp | 35 +++ src/mbgl/renderer/tile_pyramid.cpp | 2 +- src/mbgl/renderer/update_parameters.hpp | 21 +- src/mbgl/tile/geojson_tile.cpp | 2 +- src/mbgl/tile/geometry_tile.cpp | 2 +- src/mbgl/tile/tile.cpp | 2 +- test/api/annotations.test.cpp | 17 +- test/api/api_misuse.test.cpp | 11 +- test/api/custom_layer.test.cpp | 9 +- test/api/query.test.cpp | 40 ++- test/api/render_missing.test.cpp | 10 +- test/api/repeated_render.test.cpp | 21 +- test/map/map.test.cpp | 344 ++++++++++---------- test/map/prefetch.test.cpp | 6 +- test/src/mbgl/test/stub_renderer_frontend.cpp | 52 +++ test/src/mbgl/test/stub_renderer_frontend.hpp | 44 +++ test/src/mbgl/test/util.cpp | 2 +- test/tile/annotation_tile.test.cpp | 3 +- test/tile/vector_tile.test.cpp | 2 +- test/util/memory.test.cpp | 48 ++- 45 files changed, 1056 insertions(+), 581 deletions(-) delete mode 100644 include/mbgl/map/query.hpp create mode 100644 include/mbgl/renderer/query.hpp create mode 100644 include/mbgl/renderer/renderer.hpp create mode 100644 include/mbgl/renderer/renderer_frontend.hpp create mode 100644 platform/default/mbgl/renderer/async_renderer_frontend.cpp create mode 100644 platform/default/mbgl/renderer/async_renderer_frontend.hpp create mode 100644 src/mbgl/renderer/renderer.cpp create mode 100644 src/mbgl/renderer/renderer_impl.cpp create mode 100644 src/mbgl/renderer/renderer_impl.hpp create mode 100644 src/mbgl/renderer/renderer_observer.hpp create mode 100644 test/src/mbgl/test/stub_renderer_frontend.cpp create mode 100644 test/src/mbgl/test/stub_renderer_frontend.hpp diff --git a/bin/render.cpp b/bin/render.cpp index 74fd6fdcc4..fedd8bbda6 100644 --- a/bin/render.cpp +++ b/bin/render.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" @@ -88,7 +90,8 @@ int main(int argc, char *argv[]) { OffscreenView view(backend.getContext(), { static_cast(width * pixelRatio), static_cast(height * pixelRatio) }); ThreadPool threadPool(4); - Map map(backend, MapObserver::nullObserver(), mbgl::Size { width, height }, pixelRatio, fileSource, threadPool, MapMode::Still); + AsyncRendererFrontend rendererFrontend(std::make_unique(backend, pixelRatio, fileSource, threadPool), view); + Map map(rendererFrontend, MapObserver::nullObserver(), mbgl::Size { width, height }, pixelRatio, fileSource, threadPool, MapMode::Still); if (style_path.find("://") == std::string::npos) { style_path = std::string("file://") + style_path; @@ -103,7 +106,7 @@ int main(int argc, char *argv[]) { map.setDebug(debug ? mbgl::MapDebugOptions::TileBorders | mbgl::MapDebugOptions::ParseStatus : mbgl::MapDebugOptions::NoDebug); } - map.renderStill(view, [&](std::exception_ptr error) { + map.renderStill([&](std::exception_ptr error) { try { if (error) { std::rethrow_exception(error); diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 28dd25376b..d22aa58fef 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -108,7 +108,6 @@ set(MBGL_CORE_FILES include/mbgl/map/map.hpp include/mbgl/map/map_observer.hpp include/mbgl/map/mode.hpp - include/mbgl/map/query.hpp include/mbgl/map/view.hpp src/mbgl/map/backend.cpp src/mbgl/map/backend_scope.cpp @@ -160,6 +159,9 @@ set(MBGL_CORE_FILES src/mbgl/programs/uniforms.hpp # renderer + include/mbgl/renderer/query.hpp + include/mbgl/renderer/renderer.hpp + include/mbgl/renderer/renderer_frontend.hpp src/mbgl/renderer/bucket.hpp src/mbgl/renderer/bucket_parameters.cpp src/mbgl/renderer/bucket_parameters.hpp @@ -196,6 +198,10 @@ set(MBGL_CORE_FILES src/mbgl/renderer/render_style_observer.hpp src/mbgl/renderer/render_tile.cpp src/mbgl/renderer/render_tile.hpp + src/mbgl/renderer/renderer.cpp + src/mbgl/renderer/renderer_impl.cpp + src/mbgl/renderer/renderer_impl.hpp + src/mbgl/renderer/renderer_observer.hpp src/mbgl/renderer/style_diff.cpp src/mbgl/renderer/style_diff.hpp src/mbgl/renderer/tile_parameters.hpp diff --git a/cmake/render.cmake b/cmake/render.cmake index 407e1ca8ef..350350dc76 100644 --- a/cmake/render.cmake +++ b/cmake/render.cmake @@ -1,4 +1,6 @@ add_executable(mbgl-render + platform/default/mbgl/renderer/async_renderer_frontend.cpp + platform/default/mbgl/renderer/async_renderer_frontend.hpp bin/render.cpp ) diff --git a/cmake/test-files.cmake b/cmake/test-files.cmake index cdca1db280..ca7182581b 100644 --- a/cmake/test-files.cmake +++ b/cmake/test-files.cmake @@ -60,6 +60,8 @@ set(MBGL_TEST_FILES test/src/mbgl/test/stub_geometry_tile_feature.hpp test/src/mbgl/test/stub_layer_observer.hpp test/src/mbgl/test/stub_render_source_observer.hpp + test/src/mbgl/test/stub_renderer_frontend.cpp + test/src/mbgl/test/stub_renderer_frontend.hpp test/src/mbgl/test/stub_style_observer.hpp test/src/mbgl/test/stub_tile_observer.hpp test/src/mbgl/test/test.cpp diff --git a/include/mbgl/map/backend.hpp b/include/mbgl/map/backend.hpp index 434f68779c..3347086571 100644 --- a/include/mbgl/map/backend.hpp +++ b/include/mbgl/map/backend.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -15,8 +16,6 @@ using ProcAddress = void (*)(); using FramebufferID = uint32_t; } // namespace gl -class BackendScope; - class Backend { public: Backend(); @@ -28,9 +27,9 @@ public: // Called prior to rendering to update the internally assumed OpenGL state. virtual void updateAssumedState() = 0; - // Called when the map needs to be rendered; the backend should call Map::render() at some point - // in the near future. (Not called for Map::renderStill() mode.) - virtual void invalidate() = 0; + inline virtual BackendScope::ScopeType getScopeType() const { + return BackendScope::ScopeType::Explicit; + }; protected: // Called with the name of an OpenGL extension that should be loaded. Backend implementations diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 22ac100c40..14f42d7fd5 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -4,13 +4,10 @@ #include #include #include -#include -#include #include #include #include #include -#include #include #include @@ -24,6 +21,7 @@ class Backend; class View; class FileSource; class Scheduler; +class RendererFrontend; namespace style { class Image; @@ -32,30 +30,25 @@ class Style; class Map : private util::noncopyable { public: - explicit Map(Backend&, + explicit Map(RendererFrontend&, MapObserver&, Size size, float pixelRatio, FileSource&, Scheduler&, MapMode mapMode = MapMode::Continuous, - GLContextMode contextMode = GLContextMode::Unique, ConstrainMode constrainMode = ConstrainMode::HeightOnly, - ViewportMode viewportMode = ViewportMode::Default, - optional programCacheDir = optional()); + ViewportMode viewportMode = ViewportMode::Default); ~Map(); // Register a callback that will get called (on the render thread) when all resources have // been loaded and a complete render occurs. using StillImageCallback = std::function; - void renderStill(View&, StillImageCallback callback); + void renderStill(StillImageCallback callback); // Triggers a repaint. void triggerRepaint(); - // Main render function. - void render(View&); - style::Style& getStyle(); const style::Style& getStyle() const; @@ -150,13 +143,6 @@ public: void updateAnnotation(AnnotationID, const Annotation&); void removeAnnotation(AnnotationID); - // Feature queries - std::vector queryRenderedFeatures(const ScreenCoordinate&, const RenderedQueryOptions& options = {}); - std::vector queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions& options = {}); - std::vector querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options = {}); - - AnnotationIDs queryPointAnnotations(const ScreenBox&); - // Tile prefetching // // When loading a map, if `PrefetchZoomDelta` is set to any number greater than 0, the map will @@ -166,9 +152,6 @@ public: void setPrefetchZoomDelta(uint8_t delta); uint8_t getPrefetchZoomDelta() const; - // Memory - void onLowMemory(); - // Debug void setDebug(MapDebugOptions); void cycleDebugOptions(); diff --git a/include/mbgl/map/query.hpp b/include/mbgl/map/query.hpp deleted file mode 100644 index b9d5f21a44..0000000000 --- a/include/mbgl/map/query.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -namespace mbgl { - -/** - * Options for query rendered features. - */ -class RenderedQueryOptions { -public: - RenderedQueryOptions(optional> layerIDs_ = optional>(), - optional filter_ = optional()) - : layerIDs(std::move(layerIDs_)), - filter(std::move(filter_)) {} - - /** layerIDs to include in the query */ - optional> layerIDs; - - optional filter; -}; - -/** - * Options for query source features - */ -class SourceQueryOptions { -public: - SourceQueryOptions(optional> sourceLayers_ = optional> (), - optional filter_ = optional()) - : sourceLayers(std::move(sourceLayers_)), - filter(std::move(filter_)) {} - - // Required for VectorSource, ignored for GeoJSONSource - optional> sourceLayers; - - optional filter; -}; - -} // namespace mbgl diff --git a/include/mbgl/renderer/query.hpp b/include/mbgl/renderer/query.hpp new file mode 100644 index 0000000000..b9d5f21a44 --- /dev/null +++ b/include/mbgl/renderer/query.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include +#include + +namespace mbgl { + +/** + * Options for query rendered features. + */ +class RenderedQueryOptions { +public: + RenderedQueryOptions(optional> layerIDs_ = optional>(), + optional filter_ = optional()) + : layerIDs(std::move(layerIDs_)), + filter(std::move(filter_)) {} + + /** layerIDs to include in the query */ + optional> layerIDs; + + optional filter; +}; + +/** + * Options for query source features + */ +class SourceQueryOptions { +public: + SourceQueryOptions(optional> sourceLayers_ = optional> (), + optional filter_ = optional()) + : sourceLayers(std::move(sourceLayers_)), + filter(std::move(filter_)) {} + + // Required for VectorSource, ignored for GeoJSONSource + optional> sourceLayers; + + optional filter; +}; + +} // namespace mbgl diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp new file mode 100644 index 0000000000..6626f74d3d --- /dev/null +++ b/include/mbgl/renderer/renderer.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace mbgl { + +class Backend; +class FileSource; +class RendererObserver; +class RenderedQueryOptions; +class Scheduler; +class SourceQueryOptions; +class UpdateParameters; +class View; + +class Renderer { +public: + Renderer(Backend&, float pixelRatio_, FileSource&, Scheduler&, + GLContextMode = GLContextMode::Unique, + const optional programCacheDir = optional()); + ~Renderer(); + + void setObserver(RendererObserver*); + + void render(View& view, const UpdateParameters&); + + // Feature queries + std::vector queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions& options = {}) const; + std::vector queryRenderedFeatures(const ScreenCoordinate& point, const RenderedQueryOptions& options = {}) const; + std::vector queryRenderedFeatures(const ScreenBox& box, const RenderedQueryOptions& options = {}) const; + std::vector querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options = {}) const; + AnnotationIDs queryPointAnnotations(const ScreenBox& box) const; + + // Debug + void dumpDebugLogs(); + + // Memory + void onLowMemory(); + +private: + class Impl; + std::unique_ptr impl; +}; + +} // namespace mbgl diff --git a/include/mbgl/renderer/renderer_frontend.hpp b/include/mbgl/renderer/renderer_frontend.hpp new file mode 100644 index 0000000000..f72b0ccdde --- /dev/null +++ b/include/mbgl/renderer/renderer_frontend.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace mbgl { + +class RendererObserver; +class UpdateParameters; + +// The RenderFrontend is the bridge between the Map and +// platform used to update and observer the Renderer +// +// It hides any threading specifics and always replies on +// the original thread. +class RendererFrontend { +public: + + virtual ~RendererFrontend() = default; + + // Must synchronously clean up the Renderer if set + virtual void reset() = 0; + + // Implementer must bind the renderer observer to the renderer in a + // appropriate manner so that the callbacks occur on the main thread + virtual void setObserver(RendererObserver&) = 0; + + // Coalescing updates is up to the implementer + virtual void update(std::shared_ptr) = 0; +}; + +} // namespace mbgl diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 5a6950a23f..9fdbfa1b45 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -57,6 +57,8 @@ macro(mbgl_platform_core) PRIVATE platform/default/bidi.cpp PRIVATE platform/default/thread_local.cpp PRIVATE platform/default/utf.cpp + PRIVATE platform/default/mbgl/renderer/default_render_bridge.cpp + PRIVATE platform/default/mbgl/renderer/default_render_bridge.hpp # Image handling PRIVATE platform/default/png_writer.cpp diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp index df3a517823..82cf7b38fd 100644 --- a/platform/default/mbgl/gl/headless_backend.cpp +++ b/platform/default/mbgl/gl/headless_backend.cpp @@ -16,7 +16,7 @@ HeadlessBackend::HeadlessBackend(std::shared_ptr display_) } HeadlessBackend::~HeadlessBackend() { - BackendScope scope(*this); + BackendScope guard { *this, getScopeType() }; context.reset(); } @@ -44,8 +44,4 @@ void HeadlessBackend::updateAssumedState() { // no-op } -void HeadlessBackend::invalidate() { - assert(false); -} - } // namespace mbgl diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp index 26033acf82..7b9f7f5ad3 100644 --- a/platform/default/mbgl/gl/headless_backend.hpp +++ b/platform/default/mbgl/gl/headless_backend.hpp @@ -17,8 +17,6 @@ public: void updateAssumedState() override; - void invalidate() override; - struct Impl { virtual ~Impl() = default; virtual void activateContext() = 0; diff --git a/platform/default/mbgl/renderer/async_renderer_frontend.cpp b/platform/default/mbgl/renderer/async_renderer_frontend.cpp new file mode 100644 index 0000000000..37b4e60cf6 --- /dev/null +++ b/platform/default/mbgl/renderer/async_renderer_frontend.cpp @@ -0,0 +1,38 @@ +#include "async_renderer_frontend.hpp" +#include + +namespace mbgl { + +AsyncRendererFrontend::AsyncRendererFrontend(std::unique_ptr renderer_, View& view_) + : renderer(std::move(renderer_)) + , view(view_) + , asyncInvalidate([this] { + if (renderer && updateParameters) { + renderer->render(view, *updateParameters); + } + }) { +} + +AsyncRendererFrontend::~AsyncRendererFrontend() = default; + +void AsyncRendererFrontend::reset() { + assert(renderer); + renderer.reset(); +} + +void AsyncRendererFrontend::update(std::shared_ptr updateParameters_) { + updateParameters = updateParameters_; + asyncInvalidate.send(); +} + +void AsyncRendererFrontend::setObserver(RendererObserver& observer_) { + assert(renderer); + renderer->setObserver(&observer_); +} + +Renderer* AsyncRendererFrontend::getRenderer() { + assert(renderer); + return renderer.get(); +} + +} // namespace mbgl diff --git a/platform/default/mbgl/renderer/async_renderer_frontend.hpp b/platform/default/mbgl/renderer/async_renderer_frontend.hpp new file mode 100644 index 0000000000..00cf3a480c --- /dev/null +++ b/platform/default/mbgl/renderer/async_renderer_frontend.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace mbgl { + +class Renderer; + +// Default implementation for RendererFrontend +class AsyncRendererFrontend : public mbgl::RendererFrontend { +public: + AsyncRendererFrontend(std::unique_ptr, View&); + ~AsyncRendererFrontend() override; + + void reset() override; + + void update(std::shared_ptr updateParameters_) override; + + void setObserver(RendererObserver& observer_) override; + + Renderer* getRenderer(); + +private: + std::unique_ptr renderer; + View& view; + std::shared_ptr updateParameters; + util::AsyncTask asyncInvalidate; +}; + +} // namespace mbgl diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 78e98e2a28..2599996f7c 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index ec5a360a90..dbf8387ae0 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -215,7 +215,6 @@ void AnnotationManager::addImage(std::unique_ptr image) { images.erase(id); auto inserted = images.emplace(id, style::Image(id, image->getImage().clone(), image->getPixelRatio(), image->isSdf())); - style.get().impl->addImage(std::make_unique(inserted.first->second)); } diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index b1594388c4..4c4e985369 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -1,12 +1,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include #include diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 172b2bf851..7d57f6863e 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -1,23 +1,19 @@ #include #include -#include -#include -#include #include #include #include #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include #include #include -#include #include #include #include @@ -29,69 +25,58 @@ namespace mbgl { using namespace style; -enum class RenderState : uint8_t { - Never, - Partial, - Fully, -}; - struct StillImageRequest { - StillImageRequest(View& view_, Map::StillImageCallback&& callback_) - : view(view_), callback(std::move(callback_)) { + StillImageRequest(Map::StillImageCallback&& callback_) + : callback(std::move(callback_)) { } - View& view; Map::StillImageCallback callback; }; class Map::Impl : public style::Observer, - public RenderStyleObserver { + public RendererObserver { public: Impl(Map&, - Backend&, + RendererFrontend&, MapObserver&, float pixelRatio, FileSource&, Scheduler&, MapMode, - GLContextMode, ConstrainMode, - ViewportMode, - optional programCacheDir); + ViewportMode); + + ~Impl(); + // StyleObserver void onSourceChanged(style::Source&) override; void onUpdate(Update) override; - void onInvalidate() override; void onStyleLoading() override; void onStyleLoaded() override; void onStyleError(std::exception_ptr) override; - void onResourceError(std::exception_ptr) override; - void render(View&); - void renderStill(); + // RendererObserver + void onInvalidate() override; + void onResourceError(std::exception_ptr) override; + void onWillStartRenderingFrame() override; + void onDidFinishRenderingFrame(RenderMode, bool) override; + void onWillStartRenderingMap() override; + void onDidFinishRenderingMap() override; Map& map; MapObserver& observer; - Backend& backend; + RendererFrontend& rendererFrontend; FileSource& fileSource; Scheduler& scheduler; - RenderState renderState = RenderState::Never; Transform transform; const MapMode mode; - const GLContextMode contextMode; const float pixelRatio; - const optional programCacheDir; MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; - Update updateFlags = Update::Nothing; - - std::unique_ptr painter; std::unique_ptr