Add extra observer hooks for interesting internal processes (#2694)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
### ✨ New features
|
||||
|
||||
- *...Add new stuff here...*
|
||||
- [core] Added new map observer events: onPreCompileShader, onPostCompileShader, onShaderCompileFailed, onGlyphsLoaded, onGlyphsError, onGlyphsRequested, onTileAction, onSpriteLoaded, onSpriteError, onSpriteRequested ([#2694](https://github.com/maplibre/maplibre-native/pull/2694)).
|
||||
- [core] Add WebP image decoding support to default platform (Linux, Windows)
|
||||
- [core] All CMake properties are now prefixed `MLN_*` [1054](https://github.com/maplibre/maplibre-native/pull/1054).
|
||||
- [windows] Added windows build support for core applications and node [#707](https://github.com/maplibre/maplibre-native/pull/707)
|
||||
|
||||
@@ -369,12 +369,16 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/raster_dem_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/raster_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/sources/vector_source.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/sprite.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/style.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/style_property.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/types.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/undefined.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/text/glyph.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/text/glyph_range.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/tile/tile_id.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/tile/tile_operation.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/tile/tile_necessity.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/async_request.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/async_task.hpp
|
||||
@@ -396,6 +400,7 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/geo.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/geojson.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/geometry.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/hash.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/identity.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/ignore.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/image.hpp
|
||||
@@ -410,6 +415,7 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/premultiply.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/projection.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/range.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/rect.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/run_loop.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/scoped.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/util/size.hpp
|
||||
@@ -757,7 +763,6 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/expression/within.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/filter.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/image.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/sprite.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/sprite.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/image_impl.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/image_impl.hpp
|
||||
@@ -863,7 +868,6 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_atlas.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_atlas.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager.cpp
|
||||
@@ -871,7 +875,6 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_pbf.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_pbf.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_range.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/language_tag.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/language_tag.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/local_glyph_rasterizer.hpp
|
||||
@@ -910,6 +913,7 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_id_io.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_loader.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_loader_impl.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_loader_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/tile_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/tile/vector_tile.hpp
|
||||
@@ -932,7 +936,6 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/geometry_util.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/grid_index.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/grid_index.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/hash.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/http_header.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/http_header.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/http_timeout.cpp
|
||||
@@ -961,7 +964,6 @@ list(APPEND SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/quaternion.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/rapidjson.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/rapidjson.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/rect.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/std.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/stopwatch.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/util/stopwatch.hpp
|
||||
|
||||
@@ -441,7 +441,6 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/style/expression/value.cpp",
|
||||
"src/mbgl/style/expression/within.cpp",
|
||||
"src/mbgl/style/filter.cpp",
|
||||
"src/mbgl/style/sprite.hpp",
|
||||
"src/mbgl/style/sprite.cpp",
|
||||
"src/mbgl/style/image.cpp",
|
||||
"src/mbgl/style/image_impl.cpp",
|
||||
@@ -521,7 +520,6 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/text/get_anchors.cpp",
|
||||
"src/mbgl/text/get_anchors.hpp",
|
||||
"src/mbgl/text/glyph.cpp",
|
||||
"src/mbgl/text/glyph.hpp",
|
||||
"src/mbgl/text/glyph_atlas.cpp",
|
||||
"src/mbgl/text/glyph_atlas.hpp",
|
||||
"src/mbgl/text/glyph_manager.cpp",
|
||||
@@ -529,7 +527,6 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/text/glyph_manager_observer.hpp",
|
||||
"src/mbgl/text/glyph_pbf.cpp",
|
||||
"src/mbgl/text/glyph_pbf.hpp",
|
||||
"src/mbgl/text/glyph_range.hpp",
|
||||
"src/mbgl/text/language_tag.cpp",
|
||||
"src/mbgl/text/language_tag.hpp",
|
||||
"src/mbgl/text/local_glyph_rasterizer.hpp",
|
||||
@@ -568,6 +565,7 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/tile/tile_id_io.cpp",
|
||||
"src/mbgl/tile/tile_loader.hpp",
|
||||
"src/mbgl/tile/tile_loader_impl.hpp",
|
||||
"src/mbgl/tile/tile_loader_observer.hpp",
|
||||
"src/mbgl/tile/tile_observer.hpp",
|
||||
"src/mbgl/tile/vector_tile.cpp",
|
||||
"src/mbgl/tile/vector_tile.hpp",
|
||||
@@ -591,7 +589,6 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/util/geometry_util.hpp",
|
||||
"src/mbgl/util/grid_index.cpp",
|
||||
"src/mbgl/util/grid_index.hpp",
|
||||
"src/mbgl/util/hash.hpp",
|
||||
"src/mbgl/util/http_header.cpp",
|
||||
"src/mbgl/util/http_header.hpp",
|
||||
"src/mbgl/util/http_timeout.cpp",
|
||||
@@ -621,7 +618,6 @@ MLN_CORE_SOURCE = [
|
||||
"src/mbgl/util/quaternion.hpp",
|
||||
"src/mbgl/util/rapidjson.cpp",
|
||||
"src/mbgl/util/rapidjson.hpp",
|
||||
"src/mbgl/util/rect.hpp",
|
||||
"src/mbgl/util/std.hpp",
|
||||
"src/mbgl/util/stopwatch.cpp",
|
||||
"src/mbgl/util/stopwatch.hpp",
|
||||
@@ -652,6 +648,7 @@ MLN_CORE_SOURCE = [
|
||||
|
||||
MLN_CORE_HEADERS = [
|
||||
"include/mbgl/gfx/context.hpp",
|
||||
"include/mbgl/gfx/context_observer.hpp",
|
||||
"include/mbgl/actor/actor.hpp",
|
||||
"include/mbgl/actor/actor_ref.hpp",
|
||||
"include/mbgl/actor/aspiring_actor.hpp",
|
||||
@@ -794,12 +791,16 @@ MLN_CORE_HEADERS = [
|
||||
"include/mbgl/style/sources/raster_dem_source.hpp",
|
||||
"include/mbgl/style/sources/raster_source.hpp",
|
||||
"include/mbgl/style/sources/vector_source.hpp",
|
||||
"include/mbgl/style/sprite.hpp",
|
||||
"include/mbgl/style/style.hpp",
|
||||
"include/mbgl/style/style_property.hpp",
|
||||
"include/mbgl/style/transition_options.hpp",
|
||||
"include/mbgl/style/types.hpp",
|
||||
"include/mbgl/style/undefined.hpp",
|
||||
"include/mbgl/text/glyph.hpp",
|
||||
"include/mbgl/text/glyph_range.hpp",
|
||||
"include/mbgl/tile/tile_id.hpp",
|
||||
"include/mbgl/tile/tile_operation.hpp",
|
||||
"include/mbgl/tile/tile_necessity.hpp",
|
||||
"include/mbgl/util/async_request.hpp",
|
||||
"include/mbgl/util/async_task.hpp",
|
||||
@@ -822,6 +823,7 @@ MLN_CORE_HEADERS = [
|
||||
"include/mbgl/util/geo.hpp",
|
||||
"include/mbgl/util/geojson.hpp",
|
||||
"include/mbgl/util/geometry.hpp",
|
||||
"include/mbgl/util/hash.hpp",
|
||||
"include/mbgl/util/identity.hpp",
|
||||
"include/mbgl/util/ignore.hpp",
|
||||
"include/mbgl/util/image.hpp",
|
||||
@@ -837,6 +839,7 @@ MLN_CORE_HEADERS = [
|
||||
"include/mbgl/util/premultiply.hpp",
|
||||
"include/mbgl/util/projection.hpp",
|
||||
"include/mbgl/util/range.hpp",
|
||||
"include/mbgl/util/rect.hpp",
|
||||
"include/mbgl/util/run_loop.hpp",
|
||||
"include/mbgl/util/scoped.hpp",
|
||||
"include/mbgl/util/size.hpp",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/gfx/backend.hpp>
|
||||
#include <mbgl/gfx/command_encoder.hpp>
|
||||
#include <mbgl/gfx/context_observer.hpp>
|
||||
#include <mbgl/gfx/draw_scope.hpp>
|
||||
#include <mbgl/gfx/program.hpp>
|
||||
#include <mbgl/gfx/renderbuffer.hpp>
|
||||
@@ -51,10 +52,15 @@ using UniqueDrawableBuilder = std::unique_ptr<DrawableBuilder>;
|
||||
using VertexAttributeArrayPtr = std::shared_ptr<VertexAttributeArray>;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
ContextObserver nullObserver;
|
||||
}
|
||||
|
||||
class Context {
|
||||
protected:
|
||||
Context(uint32_t maximumVertexBindingCount_)
|
||||
: maximumVertexBindingCount(maximumVertexBindingCount_) {}
|
||||
: maximumVertexBindingCount(maximumVertexBindingCount_),
|
||||
observer(&nullObserver) {}
|
||||
|
||||
public:
|
||||
static constexpr const uint32_t minimumRequiredVertexBindingCount = 8;
|
||||
@@ -66,6 +72,8 @@ public:
|
||||
Context& operator=(const Context& other) = delete;
|
||||
virtual ~Context() = default;
|
||||
|
||||
virtual void setObserver(ContextObserver* observer_) { observer = observer_ ? observer_ : &nullObserver; }
|
||||
|
||||
virtual void beginFrame() = 0;
|
||||
virtual void endFrame() = 0;
|
||||
|
||||
@@ -173,6 +181,7 @@ protected:
|
||||
virtual std::unique_ptr<DrawScopeResource> createDrawScopeResource() = 0;
|
||||
|
||||
gfx::RenderingStats stats;
|
||||
ContextObserver* observer;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
19
include/mbgl/gfx/context_observer.hpp
Normal file
19
include/mbgl/gfx/context_observer.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/backend.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
class ContextObserver {
|
||||
public:
|
||||
virtual void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
@@ -1,7 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/style/source.hpp>
|
||||
#include <mbgl/style/image.hpp>
|
||||
#include <mbgl/style/sprite.hpp>
|
||||
#include <mbgl/text/glyph.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@@ -65,7 +70,25 @@ public:
|
||||
virtual bool onCanRemoveUnusedStyleImage(const std::string&) { return true; }
|
||||
// Observe this event to easily mutate or observe shaders as soon
|
||||
// as the registry becomes available.
|
||||
virtual void onRegisterShaders(gfx::ShaderRegistry&) {};
|
||||
virtual void onRegisterShaders(gfx::ShaderRegistry&) {}
|
||||
|
||||
// Shaders compilation
|
||||
virtual void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
|
||||
// Glyph requests
|
||||
virtual void onGlyphsLoaded(const FontStack&, const GlyphRange&) {}
|
||||
virtual void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) {}
|
||||
virtual void onGlyphsRequested(const FontStack&, const GlyphRange&) {}
|
||||
|
||||
// Tile requests
|
||||
virtual void onTileAction(TileOperation, const OverscaledTileID&, const std::string&) {}
|
||||
|
||||
// Sprite requests
|
||||
virtual void onSpriteLoaded(const std::optional<style::Sprite>&) {}
|
||||
virtual void onSpriteError(const std::optional<style::Sprite>&, std::exception_ptr) {}
|
||||
virtual void onSpriteRequested(const std::optional<style::Sprite>&) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -66,7 +66,8 @@ public:
|
||||
BufferResource createBuffer(
|
||||
const void* data, std::size_t size, gfx::BufferUsageType usage, bool isIndexBuffer, bool persistent) const;
|
||||
|
||||
UniqueShaderProgram createProgram(std::string name,
|
||||
UniqueShaderProgram createProgram(shaders::BuiltIn shaderID,
|
||||
std::string name,
|
||||
std::string_view source,
|
||||
std::string_view vertexName,
|
||||
std::string_view fragmentName,
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/util/font_stack.hpp>
|
||||
#include <mbgl/text/glyph_range.hpp>
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <mbgl/gfx/backend.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
@@ -54,6 +61,17 @@ public:
|
||||
|
||||
// Entry point for custom shader registration
|
||||
virtual void onRegisterShaders(gfx::ShaderRegistry&) {};
|
||||
virtual void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
|
||||
// Glyph loading
|
||||
virtual void onGlyphsLoaded(const FontStack&, const GlyphRange&) {}
|
||||
virtual void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) {}
|
||||
virtual void onGlyphsRequested(const FontStack&, const GlyphRange&) {}
|
||||
|
||||
// Tile loading
|
||||
virtual void onTileAction(TileOperation, const OverscaledTileID&, const std::string&) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -14,7 +14,7 @@ class ShaderGroupGL final : public gfx::ShaderGroup {
|
||||
public:
|
||||
ShaderGroupGL(const ProgramParameters& programParameters_)
|
||||
: gfx::ShaderGroup(),
|
||||
programParameters(programParameters_) {}
|
||||
programParameters(programParameters_.withProgramType(ShaderID)) {}
|
||||
~ShaderGroupGL() noexcept override = default;
|
||||
|
||||
gfx::ShaderPtr getOrCreateShader(gfx::Context& context,
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
auto& context = static_cast<Context&>(gfxContext);
|
||||
const auto shaderSource = std::string(shaders::prelude) + source;
|
||||
shader = context.createProgram(
|
||||
shaderName, shaderSource, vertMain, fragMain, programParameters, additionalDefines);
|
||||
ShaderID, shaderName, shaderSource, vertMain, fragMain, programParameters, additionalDefines);
|
||||
assert(shader);
|
||||
if (!shader || !registerShader(shader, shaderName)) {
|
||||
assert(false);
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
addAdditionalDefines(propertiesAsUniforms, additionalDefines);
|
||||
|
||||
auto& context = static_cast<Context&>(gfxContext);
|
||||
shader = context.createProgram(shaderName, vert, frag, programParameters, additionalDefines);
|
||||
shader = context.createProgram(ShaderID, shaderName, vert, frag, programParameters, additionalDefines);
|
||||
assert(shader);
|
||||
if (!shader || !registerShader(shader, shaderName)) {
|
||||
assert(false);
|
||||
|
||||
@@ -51,12 +51,14 @@ using UniqueShaderProgram = std::unique_ptr<ShaderProgram>;
|
||||
|
||||
class ShaderProgram final : public gfx::ShaderProgramBase {
|
||||
public:
|
||||
ShaderProgram(const std::string& name,
|
||||
ShaderProgram(shaders::BuiltIn shaderID,
|
||||
const std::string& name,
|
||||
const std::string_view& vertex,
|
||||
const std::string_view& fragment,
|
||||
const ProgramParameters& programParameters,
|
||||
const mbgl::unordered_map<std::string, std::string>& additionalDefines,
|
||||
RendererBackend& backend);
|
||||
RendererBackend& backend,
|
||||
gfx::ContextObserver& observer);
|
||||
~ShaderProgram() noexcept override;
|
||||
|
||||
static constexpr std::string_view Name{"GenericVulkanShader"};
|
||||
|
||||
16
include/mbgl/tile/tile_operation.hpp
Normal file
16
include/mbgl/tile/tile_operation.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace mbgl {
|
||||
enum class TileOperation : uint8_t {
|
||||
RequestedFromCache, ///< A read request from the cache
|
||||
RequestedFromNetwork, ///< A read request from the online source
|
||||
LoadFromNetwork, ///< Tile data from the network has been retrieved
|
||||
LoadFromCache, ///< Tile data from the cache has been retrieved
|
||||
StartParse, ///< Background processing of tile data has been initiated
|
||||
EndParse, ///< Background processing of tile data has been completed
|
||||
Error, ///< An error occurred while loading the tile
|
||||
Cancelled, ///< Loading of a tile was cancelled
|
||||
NullOp, ///< No operation has taken place
|
||||
};
|
||||
} // namespace mbgl
|
||||
@@ -60,7 +60,8 @@ public:
|
||||
|
||||
BufferResource createBuffer(const void* data, std::size_t size, std::uint32_t usage, bool persistent) const;
|
||||
|
||||
UniqueShaderProgram createProgram(std::string name,
|
||||
UniqueShaderProgram createProgram(shaders::BuiltIn shaderID,
|
||||
std::string name,
|
||||
const std::string_view vertex,
|
||||
const std::string_view fragment,
|
||||
const ProgramParameters& programParameters,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
### ✨ Features and improvements
|
||||
|
||||
- Added new map observer events: onPreCompileShader, onPostCompileShader, onShaderCompileFailed, onGlyphsLoaded, onGlyphsError, onGlyphsRequested, onTileAction, onSpriteLoaded, onSpriteError, onSpriteRequested ([#2694](https://github.com/maplibre/maplibre-native/pull/2694)).
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
## 11.2.0
|
||||
|
||||
@@ -189,7 +189,8 @@ add_library(maplibre SHARED
|
||||
${PROJECT_SOURCE_DIR}/style/transition_options.hpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.cpp
|
||||
${PROJECT_SOURCE_DIR}/style/value.hpp
|
||||
${PROJECT_SOURCE_DIR}/util/default_style.cpp
|
||||
${PROJECT_SOURCE_DIR}/tile/tile_operation.cpp
|
||||
${PROJECT_SOURCE_DIR}/util/default_style.cpp
|
||||
${PROJECT_SOURCE_DIR}/util/tile_server_options.cpp
|
||||
${PROJECT_SOURCE_DIR}/util/default_style.hpp
|
||||
${PROJECT_SOURCE_DIR}/util/tile_server_options.hpp)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "android_renderer_frontend.hpp"
|
||||
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/renderer/renderer_observer.hpp>
|
||||
@@ -52,6 +53,40 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Mailbox> mailbox;
|
||||
ActorRef<RendererObserver> delegate;
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "i18n/number_format_jni.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "text/local_glyph_rasterizer_jni.hpp"
|
||||
#include "tile/tile_operation.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
@@ -158,6 +159,9 @@ void registerNatives(JavaVM* vm) {
|
||||
StringUtils::registerNative(env);
|
||||
NumberFormat::registerNative(env);
|
||||
|
||||
// Tile
|
||||
TileOperation::registerNative(env);
|
||||
|
||||
// Logger
|
||||
Logger::registerNative(env);
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "map_renderer.hpp"
|
||||
#include "run_loop_impl.hpp"
|
||||
#include "style/light.hpp"
|
||||
#include "tile/tile_operation.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
@@ -1341,5 +1342,199 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
|
||||
METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"));
|
||||
}
|
||||
|
||||
void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {};
|
||||
|
||||
// Shader compilation
|
||||
void NativeMapView::onPreCompileShader(shaders::BuiltIn id,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onPreCompileShader = javaClass.GetMethod<void(jni::jint, jni::jint, jni::String)>(*_env,
|
||||
"onPreCompileShader");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env,
|
||||
onPreCompileShader,
|
||||
static_cast<jni::jint>(id),
|
||||
static_cast<jni::jint>(type),
|
||||
jni::Make<jni::String>(*_env, additionalDefines));
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onPostCompileShader(shaders::BuiltIn id,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onPostCompileShader = javaClass.GetMethod<void(jni::jint, jni::jint, jni::String)>(
|
||||
*_env, "onPostCompileShader");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env,
|
||||
onPostCompileShader,
|
||||
static_cast<jni::jint>(id),
|
||||
static_cast<jni::jint>(type),
|
||||
jni::Make<jni::String>(*_env, additionalDefines));
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onShaderCompileFailed(shaders::BuiltIn id,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onShaderCompileFailed = javaClass.GetMethod<void(jni::jint, jni::jint, jni::String)>(
|
||||
*_env, "onShaderCompileFailed");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env,
|
||||
onShaderCompileFailed,
|
||||
static_cast<jni::jint>(id),
|
||||
static_cast<jni::jint>(type),
|
||||
jni::Make<jni::String>(*_env, additionalDefines));
|
||||
}
|
||||
}
|
||||
|
||||
// Glyph requests
|
||||
void NativeMapView::onGlyphsLoaded(const FontStack& stack, const GlyphRange& range) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onGlyphsLoaded = javaClass.GetMethod<void(jni::Array<jni::String>, jni::jint, jni::jint)>(
|
||||
*_env, "onGlyphsLoaded");
|
||||
|
||||
auto fontStack = jni::Array<jni::String>::New(*_env, stack.size());
|
||||
for (std::size_t i = 0; i < stack.size(); i++) {
|
||||
fontStack.Set(*_env, i, jni::Make<jni::String>(*_env, stack.at(i)));
|
||||
}
|
||||
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, onGlyphsLoaded, fontStack, range.first, range.second);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onGlyphsError(const FontStack& stack, const GlyphRange& range, std::exception_ptr) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onGlyphsError = javaClass.GetMethod<void(jni::Array<jni::String>, jni::jint, jni::jint)>(
|
||||
*_env, "onGlyphsError");
|
||||
|
||||
auto fontStack = jni::Array<jni::String>::New(*_env, stack.size());
|
||||
for (std::size_t i = 0; i < stack.size(); i++) {
|
||||
fontStack.Set(*_env, i, jni::Make<jni::String>(*_env, stack.at(i)));
|
||||
}
|
||||
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, onGlyphsError, fontStack, range.first, range.second);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onGlyphsRequested(const FontStack& stack, const GlyphRange& range) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onGlyphsRequested = javaClass.GetMethod<void(jni::Array<jni::String>, jni::jint, jni::jint)>(
|
||||
*_env, "onGlyphsRequested");
|
||||
|
||||
auto fontStack = jni::Array<jni::String>::New(*_env, stack.size());
|
||||
for (std::size_t i = 0; i < stack.size(); i++) {
|
||||
fontStack.Set(*_env, i, jni::Make<jni::String>(*_env, stack.at(i)));
|
||||
}
|
||||
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env, onGlyphsRequested, fontStack, range.first, range.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Tile requests
|
||||
void NativeMapView::onTileAction(mbgl::TileOperation op, const OverscaledTileID& id, const std::string& sourceID) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onTileAction = javaClass.GetMethod<void(
|
||||
jni::Object<mbgl::android::TileOperation>, jni::jint, jni::jint, jni::jint, jni::jint, jni::jint, jni::String)>(
|
||||
*_env, "onTileAction");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference) {
|
||||
weakReference.Call(*_env,
|
||||
onTileAction,
|
||||
mbgl::android::TileOperation::Create(*_env, op),
|
||||
static_cast<jni::jint>(id.canonical.x),
|
||||
static_cast<jni::jint>(id.canonical.y),
|
||||
static_cast<jni::jint>(id.canonical.z),
|
||||
static_cast<jni::jint>(id.wrap),
|
||||
static_cast<jni::jint>(id.overscaledZ),
|
||||
jni::Make<jni::String>(*_env, sourceID));
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite requests
|
||||
void NativeMapView::onSpriteLoaded(const std::optional<style::Sprite>& sprite) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onSpriteLoaded = javaClass.GetMethod<void(jni::String, jni::String)>(*_env, "onSpriteLoaded");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference && sprite) {
|
||||
weakReference.Call(*_env,
|
||||
onSpriteLoaded,
|
||||
jni::Make<jni::String>(*_env, sprite->id),
|
||||
jni::Make<jni::String>(*_env, sprite->spriteURL));
|
||||
} else {
|
||||
weakReference.Call(*_env, onSpriteLoaded, jni::Make<jni::String>(*_env, ""), jni::Make<jni::String>(*_env, ""));
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onSpriteError(const std::optional<style::Sprite>& sprite, std::exception_ptr ex) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onSpriteError = javaClass.GetMethod<void(jni::String, jni::String)>(*_env, "onSpriteError");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference && sprite) {
|
||||
weakReference.Call(*_env,
|
||||
onSpriteError,
|
||||
jni::Make<jni::String>(*_env, sprite->id),
|
||||
jni::Make<jni::String>(*_env, sprite->spriteURL));
|
||||
} else {
|
||||
weakReference.Call(*_env, onSpriteError, jni::Make<jni::String>(*_env, ""), jni::Make<jni::String>(*_env, ""));
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::onSpriteRequested(const std::optional<style::Sprite>& sprite) {
|
||||
assert(vm != nullptr);
|
||||
|
||||
android::UniqueEnv _env = android::AttachEnv();
|
||||
static auto& javaClass = jni::Class<NativeMapView>::Singleton(*_env);
|
||||
static auto onSpriteRequested = javaClass.GetMethod<void(jni::String, jni::String)>(*_env, "onSpriteRequested");
|
||||
auto weakReference = javaPeer.get(*_env);
|
||||
if (weakReference && sprite) {
|
||||
weakReference.Call(*_env,
|
||||
onSpriteRequested,
|
||||
jni::Make<jni::String>(*_env, sprite->id),
|
||||
jni::Make<jni::String>(*_env, sprite->spriteURL));
|
||||
} else {
|
||||
weakReference.Call(
|
||||
*_env, onSpriteRequested, jni::Make<jni::String>(*_env, ""), jni::Make<jni::String>(*_env, ""));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
|
||||
#include "annotation/marker.hpp"
|
||||
@@ -298,6 +299,25 @@ public:
|
||||
|
||||
void triggerRepaint(JNIEnv&);
|
||||
|
||||
// Shader compilation
|
||||
void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override;
|
||||
void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
|
||||
void onPostCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
|
||||
void onShaderCompileFailed(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
|
||||
|
||||
// Glyph requests
|
||||
void onGlyphsLoaded(const mbgl::FontStack&, const mbgl::GlyphRange&) override;
|
||||
void onGlyphsError(const mbgl::FontStack&, const mbgl::GlyphRange&, std::exception_ptr) override;
|
||||
void onGlyphsRequested(const mbgl::FontStack&, const mbgl::GlyphRange&) override;
|
||||
|
||||
// Tile requests
|
||||
void onTileAction(mbgl::TileOperation, const mbgl::OverscaledTileID&, const std::string&) override;
|
||||
|
||||
// Sprite requests
|
||||
void onSpriteLoaded(const std::optional<mbgl::style::Sprite>&) override;
|
||||
void onSpriteError(const std::optional<mbgl::style::Sprite>&, std::exception_ptr) override;
|
||||
void onSpriteRequested(const std::optional<mbgl::style::Sprite>&) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<AndroidRendererFrontend> rendererFrontend;
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "tile_operation.hpp"
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
jni::Local<jni::Object<TileOperation>> TileOperation::Create(jni::JNIEnv& env, mbgl::TileOperation op) {
|
||||
static auto& _class = jni::Class<mbgl::android::TileOperation>::Singleton(env);
|
||||
switch (op) {
|
||||
case mbgl::TileOperation::RequestedFromNetwork:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "RequestedFromNetwork"));
|
||||
case mbgl::TileOperation::RequestedFromCache:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "RequestedFromCache"));
|
||||
case mbgl::TileOperation::LoadFromCache:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "LoadFromCache"));
|
||||
case mbgl::TileOperation::LoadFromNetwork:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "LoadFromNetwork"));
|
||||
case mbgl::TileOperation::StartParse:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "StartParse"));
|
||||
case mbgl::TileOperation::EndParse:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "EndParse"));
|
||||
case mbgl::TileOperation::Error:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "Error"));
|
||||
case mbgl::TileOperation::Cancelled:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "Cancelled"));
|
||||
case mbgl::TileOperation::NullOp:
|
||||
return _class.Get(env, _class.GetStaticField<jni::Object<TileOperation>>(env, "NullOp"));
|
||||
}
|
||||
}
|
||||
|
||||
void TileOperation::registerNative(jni::JNIEnv& env) {
|
||||
jni::Class<TileOperation>::Singleton(env);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
|
||||
#include <jni/jni.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class TileOperation {
|
||||
public:
|
||||
static constexpr auto Name() { return "org/maplibre/android/tile/TileOperation"; };
|
||||
|
||||
static jni::Local<jni::Object<TileOperation>> Create(jni::JNIEnv&, mbgl::TileOperation);
|
||||
|
||||
static void registerNative(jni::JNIEnv& env);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.maplibre.android.maps;
|
||||
|
||||
import org.maplibre.android.log.Logger;
|
||||
import org.maplibre.android.tile.TileOperation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@@ -35,6 +36,26 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnCanRemoveUnusedStyleImageListener> onCanRemoveUnusedStyleImageListenerList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnPreCompileShaderListener> onPreCompileShaderList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnPostCompileShaderListener> onPostCompileShaderList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnShaderCompileFailedListener> onShaderCompileFailedList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnGlyphsLoadedListener> onGlyphsLoadedList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnGlyphsErrorListener> onGlyphsErrorList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnGlyphsRequestedListener> onGlyphsRequestedList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnTileActionListener> onTileActionList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnSpriteLoadedListener> onSpriteLoadedList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnSpriteErrorListener> onSpriteErrorList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
private final List<MapView.OnSpriteRequestedListener> onSpriteRequestedList
|
||||
= new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onCameraWillChange(boolean animated) {
|
||||
@@ -255,6 +276,146 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreCompileShader(int id, int type, String additionalDefines) {
|
||||
try {
|
||||
if (!onPreCompileShaderList.isEmpty()) {
|
||||
for (MapView.OnPreCompileShaderListener listener : onPreCompileShaderList) {
|
||||
listener.onPreCompileShader(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onPreCompileShader", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostCompileShader(int id, int type, String additionalDefines) {
|
||||
try {
|
||||
if (!onPostCompileShaderList.isEmpty()) {
|
||||
for (MapView.OnPostCompileShaderListener listener : onPostCompileShaderList) {
|
||||
listener.onPostCompileShader(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onPostCompileShader", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShaderCompileFailed(int id, int type, String additionalDefines) {
|
||||
try {
|
||||
if (!onShaderCompileFailedList.isEmpty()) {
|
||||
for (MapView.OnShaderCompileFailedListener listener : onShaderCompileFailedList) {
|
||||
listener.onShaderCompileFailed(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onShaderCompileFailed", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlyphsLoaded(String[] stack, int rangeStart, int rangeEnd) {
|
||||
try {
|
||||
if (!onGlyphsLoadedList.isEmpty()) {
|
||||
for (MapView.OnGlyphsLoadedListener listener : onGlyphsLoadedList) {
|
||||
listener.onGlyphsLoaded(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onGlyphsLoaded", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlyphsError(String[] stack, int rangeStart, int rangeEnd) {
|
||||
try {
|
||||
if (!onGlyphsErrorList.isEmpty()) {
|
||||
for (MapView.OnGlyphsErrorListener listener : onGlyphsErrorList) {
|
||||
listener.onGlyphsError(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onGlyphsError", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlyphsRequested(String[] stack, int rangeStart, int rangeEnd) {
|
||||
try {
|
||||
if (!onGlyphsRequestedList.isEmpty()) {
|
||||
for (MapView.OnGlyphsRequestedListener listener : onGlyphsRequestedList) {
|
||||
listener.onGlyphsRequested(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onGlyphsRequested", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTileAction(TileOperation op, int x, int y, int z, int wrap, int overscaledZ, String sourceID) {
|
||||
try {
|
||||
if (!onTileActionList.isEmpty()) {
|
||||
for (MapView.OnTileActionListener listener : onTileActionList) {
|
||||
listener.onTileAction(op, x, y, z, wrap, overscaledZ, sourceID);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onTileAction", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpriteLoaded(String id, String url) {
|
||||
try {
|
||||
if (!onSpriteLoadedList.isEmpty()) {
|
||||
for (MapView.OnSpriteLoadedListener listener : onSpriteLoadedList) {
|
||||
listener.onSpriteLoaded(id, url);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onSpriteLoaded", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpriteError(String id, String url) {
|
||||
try {
|
||||
if (!onSpriteErrorList.isEmpty()) {
|
||||
for (MapView.OnSpriteErrorListener listener : onSpriteErrorList) {
|
||||
listener.onSpriteError(id, url);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onSpriteError", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSpriteRequested(String id, String url) {
|
||||
try {
|
||||
if (!onSpriteRequestedList.isEmpty()) {
|
||||
for (MapView.OnSpriteRequestedListener listener : onSpriteRequestedList) {
|
||||
listener.onSpriteRequested(id, url);
|
||||
}
|
||||
}
|
||||
} catch (Throwable err) {
|
||||
Logger.e(TAG, "Exception in onSpriteRequested", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
void addOnCameraWillChangeListener(MapView.OnCameraWillChangeListener listener) {
|
||||
onCameraWillChangeListenerList.add(listener);
|
||||
}
|
||||
@@ -375,6 +536,86 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
|
||||
onCanRemoveUnusedStyleImageListenerList.remove(listener);
|
||||
}
|
||||
|
||||
public void addOnPreCompileShaderListener(MapView.OnPreCompileShaderListener callback) {
|
||||
onPreCompileShaderList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnPostCompileShaderListener(MapView.OnPostCompileShaderListener callback) {
|
||||
onPostCompileShaderList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnShaderCompileFailedListener(MapView.OnShaderCompileFailedListener callback) {
|
||||
onShaderCompileFailedList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnGlyphsLoadedListener(MapView.OnGlyphsLoadedListener callback) {
|
||||
onGlyphsLoadedList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnGlyphsErrorListener(MapView.OnGlyphsErrorListener callback) {
|
||||
onGlyphsErrorList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnGlyphsRequestedListener(MapView.OnGlyphsRequestedListener callback) {
|
||||
onGlyphsRequestedList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnTileActionListener(MapView.OnTileActionListener callback) {
|
||||
onTileActionList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnSpriteLoadedListener(MapView.OnSpriteLoadedListener callback) {
|
||||
onSpriteLoadedList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnSpriteErrorListener(MapView.OnSpriteErrorListener callback) {
|
||||
onSpriteErrorList.add(callback);
|
||||
}
|
||||
|
||||
public void addOnSpriteRequestedListener(MapView.OnSpriteRequestedListener callback) {
|
||||
onSpriteRequestedList.add(callback);
|
||||
}
|
||||
|
||||
public void removeOnPreCompileShaderListener(MapView.OnPreCompileShaderListener callback) {
|
||||
onPreCompileShaderList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnPostCompileShaderListener(MapView.OnPostCompileShaderListener callback) {
|
||||
onPostCompileShaderList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnShaderCompileFailedListener(MapView.OnShaderCompileFailedListener callback) {
|
||||
onShaderCompileFailedList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnGlyphsLoadedListener(MapView.OnGlyphsLoadedListener callback) {
|
||||
onGlyphsLoadedList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnGlyphsErrorListener(MapView.OnGlyphsErrorListener callback) {
|
||||
onGlyphsErrorList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnGlyphsRequestedListener(MapView.OnGlyphsRequestedListener callback) {
|
||||
onGlyphsRequestedList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnTileActionListener(MapView.OnTileActionListener callback) {
|
||||
onTileActionList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnSpriteLoadedListener(MapView.OnSpriteLoadedListener callback) {
|
||||
onSpriteLoadedList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnSpriteErrorListener(MapView.OnSpriteErrorListener callback) {
|
||||
onSpriteErrorList.remove(callback);
|
||||
}
|
||||
|
||||
public void removeOnSpriteRequestedListener(MapView.OnSpriteRequestedListener callback) {
|
||||
onSpriteRequestedList.remove(callback);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
onCameraWillChangeListenerList.clear();
|
||||
onCameraIsChangingListenerList.clear();
|
||||
@@ -391,5 +632,15 @@ class MapChangeReceiver implements NativeMapView.StateCallback {
|
||||
onSourceChangedListenerList.clear();
|
||||
onStyleImageMissingListenerList.clear();
|
||||
onCanRemoveUnusedStyleImageListenerList.clear();
|
||||
onPreCompileShaderList.clear();
|
||||
onPostCompileShaderList.clear();
|
||||
onShaderCompileFailedList.clear();
|
||||
onGlyphsLoadedList.clear();
|
||||
onGlyphsErrorList.clear();
|
||||
onGlyphsRequestedList.clear();
|
||||
onTileActionList.clear();
|
||||
onSpriteLoadedList.clear();
|
||||
onSpriteErrorList.clear();
|
||||
onSpriteRequestedList.clear();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.maplibre.android.maps.widgets.CompassView;
|
||||
import org.maplibre.android.net.ConnectivityReceiver;
|
||||
import org.maplibre.android.storage.FileSource;
|
||||
import org.maplibre.android.utils.BitmapUtils;
|
||||
import org.maplibre.android.tile.TileOperation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -906,6 +907,186 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
|
||||
mapChangeReceiver.removeOnCanRemoveUnusedStyleImageListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked before a shader is compiled.
|
||||
*
|
||||
* @param listener The callback that's invoked before a shader is compiled
|
||||
*/
|
||||
public void addOnPreCompileShaderListener(MapView.OnPreCompileShaderListener callback) {
|
||||
mapChangeReceiver.addOnPreCompileShaderListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked before a shader is compiled.
|
||||
*
|
||||
* @param listener The callback that's invoked before a shader is compiled
|
||||
*/
|
||||
public void removeOnPreCompileShaderListener(MapView.OnPreCompileShaderListener callback) {
|
||||
mapChangeReceiver.removeOnPreCompileShaderListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a shader is compiled.
|
||||
*
|
||||
* @param listener The callback that's invoked after a shader is compiled
|
||||
*/
|
||||
public void addOnPostCompileShaderListener(MapView.OnPostCompileShaderListener callback) {
|
||||
mapChangeReceiver.addOnPostCompileShaderListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a shader is compiled.
|
||||
*
|
||||
* @param listener The callback that's invoked after a shader is compiled
|
||||
*/
|
||||
public void removeOnPostCompileShaderListener(MapView.OnPostCompileShaderListener callback) {
|
||||
mapChangeReceiver.removeOnPostCompileShaderListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a shader failed to compile.
|
||||
*
|
||||
* @param listener The callback that's invoked after a shader failes to compile
|
||||
*/
|
||||
public void addOnShaderCompileFailedListener(MapView.OnShaderCompileFailedListener callback) {
|
||||
mapChangeReceiver.addOnShaderCompileFailedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a shader failed to compile.
|
||||
*
|
||||
* @param listener The callback that's invoked after a shader failes to compile
|
||||
*/
|
||||
public void removeOnShaderCompileFailedListener(MapView.OnShaderCompileFailedListener callback) {
|
||||
mapChangeReceiver.removeOnShaderCompileFailedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a range of glyphs are loaded.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs are loaded
|
||||
*/
|
||||
public void addOnGlyphsLoadedListener(MapView.OnGlyphsLoadedListener callback) {
|
||||
mapChangeReceiver.addOnGlyphsLoadedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a range of glyphs are loaded.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs are loaded
|
||||
*/
|
||||
public void removeOnGlyphsLoadedListener(MapView.OnGlyphsLoadedListener callback) {
|
||||
mapChangeReceiver.removeOnGlyphsLoadedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a range of glyphs fail to load.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs fail to load
|
||||
*/
|
||||
public void addOnGlyphsErrorListener(MapView.OnGlyphsErrorListener callback) {
|
||||
mapChangeReceiver.addOnGlyphsErrorListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a range of glyphs fail to load.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs fail to load
|
||||
*/
|
||||
public void removeOnGlyphsErrorListener(MapView.OnGlyphsErrorListener callback) {
|
||||
mapChangeReceiver.removeOnGlyphsErrorListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a range of glyphs are requested.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs are requested
|
||||
*/
|
||||
public void addOnGlyphsRequestedListener(MapView.OnGlyphsRequestedListener callback) {
|
||||
mapChangeReceiver.addOnGlyphsRequestedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a range of glyphs are requested.
|
||||
*
|
||||
* @param listener The callback that's invoked after a range of glyphs are requested
|
||||
*/
|
||||
public void removeOnGlyphsRequestedListener(MapView.OnGlyphsRequestedListener callback) {
|
||||
mapChangeReceiver.removeOnGlyphsRequestedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a tile action occurs.
|
||||
*
|
||||
* @param listener The callback that's invoked after a tile action occurs
|
||||
*/
|
||||
public void addOnTileActionListener(MapView.OnTileActionListener callback) {
|
||||
mapChangeReceiver.addOnTileActionListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove's a callback that's invoked after a tile action occurs.
|
||||
*
|
||||
* @param listener The callback that's invoked after a tile action occurs
|
||||
*/
|
||||
public void removeOnTileActionListener(MapView.OnTileActionListener callback) {
|
||||
mapChangeReceiver.removeOnTileActionListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a sprite is loaded.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite is loaded
|
||||
*/
|
||||
public void addOnSpriteLoadedListener(MapView.OnSpriteLoadedListener callback) {
|
||||
mapChangeReceiver.addOnSpriteLoadedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a sprite is loaded.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite is loaded
|
||||
*/
|
||||
public void removeOnSpriteLoadedListener(MapView.OnSpriteLoadedListener callback) {
|
||||
mapChangeReceiver.removeOnSpriteLoadedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a sprite fails to laod.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite fails to load
|
||||
*/
|
||||
public void addOnSpriteErrorListener(MapView.OnSpriteErrorListener callback) {
|
||||
mapChangeReceiver.addOnSpriteErrorListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a sprite fails to laod.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite fails to load
|
||||
*/
|
||||
public void removeOnSpriteErrorListener(MapView.OnSpriteErrorListener callback) {
|
||||
mapChangeReceiver.removeOnSpriteErrorListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback that's invoked after a sprite is requested.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite is requested
|
||||
*/
|
||||
public void addOnSpriteRequestedListener(MapView.OnSpriteRequestedListener callback) {
|
||||
mapChangeReceiver.addOnSpriteRequestedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a callback that's invoked after a sprite is requested.
|
||||
*
|
||||
* @param listener The callback that's invoked after a sprite is requested
|
||||
*/
|
||||
public void removeOnSpriteRequestedListener(MapView.OnSpriteRequestedListener callback) {
|
||||
mapChangeReceiver.removeOnSpriteRequestedListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the camera will change.
|
||||
* <p>
|
||||
@@ -1123,6 +1304,183 @@ public class MapView extends FrameLayout implements NativeMapView.ViewCallback {
|
||||
boolean onCanRemoveUnusedStyleImage(@NonNull String id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked before a shader is compiled.
|
||||
* <p>
|
||||
* {@link MapView#addOnPreCompileShaderListener(OnPreCompileShaderListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnPreCompileShaderListener {
|
||||
/**
|
||||
* Called before a shader is compiled.
|
||||
*
|
||||
* @param id of a shader type enumeration. See `mbgl::shaders::BuiltIn` for a list
|
||||
* of possible values.
|
||||
* @param type of graphics backend the shader is being compiled for. See
|
||||
* `mbgl::gfx::Backend::Type` for a list of possible values.
|
||||
* @param additionalDefines that specify the permutaion of the shader.
|
||||
*/
|
||||
void onPreCompileShader(int id, int type, String additionalDefines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a shader is compiled.
|
||||
* <p>
|
||||
* {@link MapView#addOnPostCompileShaderListener(OnPostCompileShaderListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnPostCompileShaderListener {
|
||||
/**
|
||||
* Called after a shader is compiled.
|
||||
*
|
||||
* @param id of a shader type enumeration. See `mbgl::shaders::BuiltIn` for a list
|
||||
* of possible values.
|
||||
* @param type of graphics backend the shader is being compiled for. See
|
||||
* `mbgl::gfx::Backend::Type` for a list of possible values.
|
||||
* @param additionalDefines that specify the permutation of the shader.
|
||||
*/
|
||||
void onPostCompileShader(int id, int type, String additionalDefines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a shader failed to compile.
|
||||
* <p>
|
||||
* {@link MapView#addOnShaderCompileFailedListener(OnShaderCompileFailedListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnShaderCompileFailedListener {
|
||||
/**
|
||||
* Called when a shader fails to compile.
|
||||
*
|
||||
* @param id of a shader type enumeration. See `mbgl::shaders::BuiltIn` for a list
|
||||
* of possible values.
|
||||
* @param type of graphics backend the shader is being compiled for. See
|
||||
* `mbgl::gfx::Backend::Type` for a list of possible values.
|
||||
* @param additionalDefines that specify the permutation of the shader.
|
||||
*/
|
||||
void onShaderCompileFailed(int id, int type, String additionalDefines);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a range of glyphs are loaded.
|
||||
* <p>
|
||||
* {@link MapView#addOnGlyphsLoadedListener(OnGlyphsLoadedListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnGlyphsLoadedListener {
|
||||
/**
|
||||
* Called when a range of glyphs for a font stack are loaded.
|
||||
*
|
||||
* @param stack of font names.
|
||||
* @param rangeStart of glyph indices being loaded.
|
||||
* @param rangeEnd of glyph indices being loaded.
|
||||
*/
|
||||
void onGlyphsLoaded(@NonNull String[] stack, int rangeStart, int rangeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a range of glyphs fail to load.
|
||||
* <p>
|
||||
* {@link MapView#addOnGlyphsErrorListener(OnGlyphsErrorListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnGlyphsErrorListener {
|
||||
/**
|
||||
* Called when a range of glyphs for a font stack failed to load.
|
||||
*
|
||||
* @param stack of font names.
|
||||
* @param rangeStart of glyph indices that failed to load.
|
||||
* @param rangeEnd of glyph indices that failed to load.
|
||||
*/
|
||||
void onGlyphsError(@NonNull String[] stack, int rangeStart, int rangeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a range of glyphs are requested.
|
||||
* <p>
|
||||
* {@link MapView#addOnGlyphsRequestedListener(OnGlyphsRequestedListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnGlyphsRequestedListener {
|
||||
/**
|
||||
* Called when a range of glyphs for a font stack are requested.
|
||||
*
|
||||
* @param stack of font names.
|
||||
* @param rangeStart of glyph indices that are being requested.
|
||||
* @param rangeEnd of glyph indices that are being requested.
|
||||
*/
|
||||
void onGlyphsRequested(@NonNull String[] stack, int rangeStart, int rangeEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a tile action occurs.
|
||||
* <p>
|
||||
* {@link MapView#addOnTileActionListener(OnTileActionListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnTileActionListener {
|
||||
/**
|
||||
* Called when a tile action occurs.
|
||||
*
|
||||
* @param op identifying the tile action that occurred.
|
||||
* @param x coordinate of the tile.
|
||||
* @param y coordinate of the tile.
|
||||
* @param z coordinate of the tile.
|
||||
* @param wrap coordinate of the tile.
|
||||
* @param overscaledZ coordinate of the tile.
|
||||
* @param sourceID of the tile.
|
||||
*/
|
||||
void onTileAction(TileOperation op, int x, int y, int z, int wrap, int overscaledZ, String sourceID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a sprite is requested.
|
||||
* <p>
|
||||
* {@link MapView#addOnSpriteLoadedListener(OnSpriteLoadedListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnSpriteLoadedListener {
|
||||
/**
|
||||
* Called when a sprite is loaded.
|
||||
*
|
||||
* @param id of the sprite.
|
||||
* @param url of the sprite.
|
||||
*/
|
||||
void onSpriteLoaded(@NonNull String id, @NonNull String url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a sprite fails to load.
|
||||
* <p>
|
||||
* {@link MapView#addOnSpriteErrorListener(OnSpriteErrorListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnSpriteErrorListener {
|
||||
/**
|
||||
* Called when a sprite fails to load.
|
||||
*
|
||||
* @param id of the sprite.
|
||||
* @param url of the sprite.
|
||||
*/
|
||||
void onSpriteError(@NonNull String id, @NonNull String url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked after a sprite is requested.
|
||||
* <p>
|
||||
* {@link MapView#addOnSpriteRequestedListener(OnSpriteRequestedListener)}
|
||||
* </p>
|
||||
*/
|
||||
public interface OnSpriteRequestedListener {
|
||||
/**
|
||||
* Called when a sprite is requested.
|
||||
*
|
||||
* @param id of the sprite.
|
||||
* @param url of the sprite.
|
||||
*/
|
||||
void onSpriteRequested(@NonNull String id, @NonNull String url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback object which will be triggered when the {@link MapLibreMap} instance is ready to be used.
|
||||
*
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.maplibre.android.style.light.Light;
|
||||
import org.maplibre.android.style.sources.CannotAddSourceException;
|
||||
import org.maplibre.android.style.sources.Source;
|
||||
import org.maplibre.android.utils.BitmapUtils;
|
||||
import org.maplibre.android.tile.TileOperation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -1194,6 +1195,76 @@ final class NativeMapView implements NativeMap {
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onPreCompileShader(int id, int type, String additionalDefines) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onPreCompileShader(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onPostCompileShader(int id, int type, String additionalDefines) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onPostCompileShader(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onShaderCompileFailed(int id, int type, String additionalDefines) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onShaderCompileFailed(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onGlyphsLoaded(String[] stack, int rangeStart, int rangeEnd) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onGlyphsLoaded(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onGlyphsError(String[] stack, int rangeStart, int rangeEnd) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onGlyphsError(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onGlyphsRequested(String[] stack, int rangeStart, int rangeEnd) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onGlyphsRequested(stack, rangeStart, rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onTileAction(TileOperation op, int x, int y, int z, int wrap, int overscaledZ, String sourceID) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onTileAction(op, x, y, z, wrap, overscaledZ, sourceID);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onSpriteLoaded(String id, String url) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onSpriteLoaded(id, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onSpriteError(String id, String url) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onSpriteError(id, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
private void onSpriteRequested(String id, String url) {
|
||||
if (stateCallback != null) {
|
||||
stateCallback.onSpriteRequested(id, url);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// JNI methods
|
||||
//
|
||||
@@ -1621,5 +1692,25 @@ final class NativeMapView implements NativeMap {
|
||||
void onStyleImageMissing(String imageId);
|
||||
|
||||
boolean onCanRemoveUnusedStyleImage(String imageId);
|
||||
|
||||
void onPreCompileShader(int id, int type, String additionalDefines);
|
||||
|
||||
void onPostCompileShader(int id, int type, String additionalDefines);
|
||||
|
||||
void onShaderCompileFailed(int id, int type, String additionalDefines);
|
||||
|
||||
void onGlyphsLoaded(String[] stack, int rangeStart, int rangeEnd);
|
||||
|
||||
void onGlyphsError(String[] stack, int rangeStart, int rangeEnd);
|
||||
|
||||
void onGlyphsRequested(String[] stack, int rangeStart, int rangeEnd);
|
||||
|
||||
void onTileAction(TileOperation op, int x, int y, int z, int wrap, int overscaledZ, String sourceID);
|
||||
|
||||
void onSpriteLoaded(String id, String url);
|
||||
|
||||
void onSpriteError(String id, String url);
|
||||
|
||||
void onSpriteRequested(String id, String url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.maplibre.android.tile;
|
||||
|
||||
public enum TileOperation {
|
||||
RequestedFromCache,
|
||||
RequestedFromNetwork,
|
||||
LoadFromNetwork,
|
||||
LoadFromCache,
|
||||
StartParse,
|
||||
EndParse,
|
||||
Error,
|
||||
Cancelled,
|
||||
NullOp,
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
# GMS
|
||||
-dontnote com.google.android.gms.**
|
||||
|
||||
-keep class com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer { *; }
|
||||
-keep class org.maplibre.android.testapp.model.customlayer.ExampleCustomLayer { *; }
|
||||
|
||||
# okhttp
|
||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||
|
||||
@@ -874,6 +874,18 @@
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity" />
|
||||
</activity> <!-- Events -->
|
||||
<activity
|
||||
android:name="org.maplibre.android.testapp.activity.events.ObserverActivity"
|
||||
android:description="@string/description_observer_activity"
|
||||
android:exported="true"
|
||||
android:label="@string/activity_observer_activity" >
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_events" />
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity" />
|
||||
</activity> <!-- TextureView -->
|
||||
<activity
|
||||
android:name=".activity.textureview.TextureViewDebugModeActivity"
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.maplibre.android.testapp.activity.events
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.maplibre.android.MapLibre
|
||||
import org.maplibre.android.maps.MapView
|
||||
import org.maplibre.android.maps.Style
|
||||
import org.maplibre.android.tile.TileOperation
|
||||
import org.maplibre.android.testapp.R
|
||||
import org.maplibre.android.testapp.styles.TestStyles
|
||||
import timber.log.Timber
|
||||
import java.util.*
|
||||
import kotlin.time.TimeMark
|
||||
import kotlin.time.TimeSource
|
||||
import kotlin.time.TimeSource.Monotonic
|
||||
import org.maplibre.android.log.Logger
|
||||
import org.maplibre.android.log.Logger.INFO
|
||||
|
||||
/**
|
||||
* Test activity showcasing logging observer actions from the core
|
||||
*/
|
||||
class ObserverActivity : AppCompatActivity(),
|
||||
MapView.OnPreCompileShaderListener,
|
||||
MapView.OnPostCompileShaderListener,
|
||||
MapView.OnTileActionListener,
|
||||
MapView.OnGlyphsLoadedListener,
|
||||
MapView.OnGlyphsRequestedListener,
|
||||
MapView.OnSpriteLoadedListener,
|
||||
MapView.OnSpriteRequestedListener {
|
||||
private lateinit var mapView: MapView
|
||||
|
||||
companion object {
|
||||
const val TAG = "ObserverActivity"
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_map_simple)
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.addOnPreCompileShaderListener(this)
|
||||
mapView.addOnPostCompileShaderListener(this)
|
||||
mapView.addOnTileActionListener(this)
|
||||
mapView.addOnGlyphsLoadedListener(this)
|
||||
mapView.addOnGlyphsRequestedListener(this)
|
||||
mapView.addOnSpriteLoadedListener(this)
|
||||
mapView.addOnSpriteRequestedListener(this)
|
||||
mapView.getMapAsync {
|
||||
it.setStyle(
|
||||
Style.Builder().fromUri(TestStyles.getPredefinedStyleWithFallback("Streets"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val shaderTimes: HashMap<String, TimeMark> = HashMap()
|
||||
|
||||
public override fun onPreCompileShader(id: Int, type: Int, defines: String) {
|
||||
shaderTimes["${id}-${type}-${defines}"] = TimeSource.Monotonic.markNow()
|
||||
Logger.i(TAG, "A new shader is being compiled, shaderID:${id}, backend type:${type}, program configuration:${defines}")
|
||||
}
|
||||
|
||||
public override fun onPostCompileShader(id: Int, type: Int, defines: String) {
|
||||
val startTime = shaderTimes.get("${id}-${type}-${defines}")
|
||||
if (startTime != null) {
|
||||
Logger.i(TAG, "A shader has been compiled in ${startTime.elapsedNow()}, shaderID:${id}, backend type:${type}, program configuration:${defines}")
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onGlyphsRequested(fontStack: Array<String>, rangeStart: Int, rangeEnd: Int) {
|
||||
Logger.i(TAG, "Glyphs are being requested for the font stack $fontStack, ranging from $rangeStart to $rangeEnd")
|
||||
}
|
||||
|
||||
public override fun onGlyphsLoaded(fontStack: Array<String>, rangeStart: Int, rangeEnd: Int) {
|
||||
Logger.i(TAG, "Glyphs have been loaded for the font stack $fontStack, ranging from $rangeStart to $rangeEnd")
|
||||
}
|
||||
|
||||
public override fun onSpriteRequested(id: String, url: String) {
|
||||
Logger.i(TAG, "The sprite $id has been requested from $url")
|
||||
}
|
||||
|
||||
public override fun onSpriteLoaded(id: String, url: String) {
|
||||
Logger.i(TAG, "The sprite $id has been loaded from $url")
|
||||
}
|
||||
|
||||
public override fun onTileAction(op: TileOperation, x: Int, y: Int, z: Int, wrap: Int, overscaledZ: Int, sourceID: String) {
|
||||
val tile = "X:${x}, Y:${y}, Z:${z}, Wrap:${wrap}, OverscaledZ:${overscaledZ}, SourceID:${sourceID}"
|
||||
when (op) {
|
||||
TileOperation.RequestedFromCache -> Logger.i(TAG, "Requesting tile ${tile} from the cache")
|
||||
TileOperation.RequestedFromNetwork -> Logger.i(TAG, "Requesting tile ${tile} from the network")
|
||||
TileOperation.LoadFromCache -> Logger.i(TAG, "Loading tile ${tile}, requested from the cache")
|
||||
TileOperation.LoadFromNetwork -> Logger.i(TAG, "Loading tile ${tile}, requested from the network")
|
||||
TileOperation.StartParse -> Logger.i(TAG, "Parsing tile ${tile}")
|
||||
TileOperation.EndParse -> Logger.i(TAG, "Completed parsing tile ${tile}")
|
||||
TileOperation.Error -> Logger.e(TAG, "An error occured during proccessing for tile ${tile}")
|
||||
TileOperation.Cancelled -> Logger.i(TAG, "Pending work on tile ${tile} was cancelled")
|
||||
TileOperation.NullOp -> Logger.e(TAG, "An unknown tile operation was emitted for tile ${tile}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
<string name="category_style">Styling</string>
|
||||
<string name="category_features">Features</string>
|
||||
<string name="category_storage">Storage</string>
|
||||
<string name="category_events">Events</string>
|
||||
<string name="category_textureview">Texture View</string>
|
||||
<string name="category_location">Location</string>
|
||||
<string name="category_integration">_Integration</string>
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
<string name="description_map_snapshotter_local_style">Show how to load a local style with a Snapshot</string>
|
||||
<string name="description_camera_animator">Use Android SDK Animators to animate camera position changes</string>
|
||||
<string name="description_symbol_generator">Use Android SDK Views as symbols</string>
|
||||
<string name="description_observer_activity">Use map observers to log map event information</string>
|
||||
<string name="description_textureview_debug">Use TextureView to render the map</string>
|
||||
<string name="description_textureview_resize">Resize a map rendered on a TextureView</string>
|
||||
<string name="description_textureview_animate">Animate a map rendered on a TextureView</string>
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
<string name="activity_map_snapshotter_local_style">Map Snapshot with local style</string>
|
||||
<string name="activity_camera_animator">Animator animation</string>
|
||||
<string name="activity_symbol_generator">SymbolGenerator</string>
|
||||
<string name="activity_observer_activity">Log map observer events</string>
|
||||
<string name="activity_textureview_debug">TextureView debug</string>
|
||||
<string name="activity_textureview_resize">TextureView resize</string>
|
||||
<string name="activity_textureview_animate">TextureView animation</string>
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
AnnotationTile::AnnotationTile(const OverscaledTileID& overscaledTileID, const TileParameters& parameters)
|
||||
: GeometryTile(overscaledTileID, AnnotationManager::SourceID, parameters),
|
||||
AnnotationTile::AnnotationTile(const OverscaledTileID& overscaledTileID,
|
||||
const TileParameters& parameters,
|
||||
TileObserver* observer_)
|
||||
: GeometryTile(overscaledTileID, AnnotationManager::SourceID, parameters, observer_),
|
||||
annotationManager(parameters.annotationManager) {
|
||||
auto guard = annotationManager.lock();
|
||||
if (annotationManager) {
|
||||
|
||||
@@ -11,7 +11,7 @@ class TileParameters;
|
||||
|
||||
class AnnotationTile : public GeometryTile {
|
||||
public:
|
||||
AnnotationTile(const OverscaledTileID&, const TileParameters&);
|
||||
AnnotationTile(const OverscaledTileID&, const TileParameters&, TileObserver*);
|
||||
~AnnotationTile() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -32,18 +32,19 @@ void RenderAnnotationSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
|
||||
enabled = needsRendering;
|
||||
|
||||
tilePyramid.update(
|
||||
layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
util::tileSize_I,
|
||||
// Zoom level 16 is typically sufficient for annotations.
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/10197
|
||||
{0, 16},
|
||||
std::nullopt,
|
||||
[&](const OverscaledTileID& tileID) { return std::make_unique<AnnotationTile>(tileID, parameters); });
|
||||
tilePyramid.update(layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
util::tileSize_I,
|
||||
// Zoom level 16 is typically sufficient for annotations.
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/10197
|
||||
{0, 16},
|
||||
std::nullopt,
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<AnnotationTile>(tileID, parameters, observer_);
|
||||
});
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<Feature>> RenderAnnotationSource::queryRenderedFeatures(
|
||||
|
||||
@@ -47,6 +47,8 @@ public:
|
||||
|
||||
std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;
|
||||
|
||||
gfx::ContextObserver& getObserver() const { return *observer; }
|
||||
|
||||
void beginFrame() override;
|
||||
void endFrame() override;
|
||||
|
||||
|
||||
@@ -147,6 +147,18 @@ void Map::Impl::onStyleError(std::exception_ptr error) {
|
||||
observer.onDidFailLoadingMap(type, description);
|
||||
}
|
||||
|
||||
void Map::Impl::onSpriteLoaded(const std::optional<style::Sprite>& sprite) {
|
||||
observer.onSpriteLoaded(sprite);
|
||||
}
|
||||
|
||||
void Map::Impl::onSpriteError(const std::optional<style::Sprite>& sprite, std::exception_ptr ex) {
|
||||
observer.onSpriteError(sprite, ex);
|
||||
}
|
||||
|
||||
void Map::Impl::onSpriteRequested(const std::optional<style::Sprite>& sprite) {
|
||||
observer.onSpriteRequested(sprite);
|
||||
}
|
||||
|
||||
// MARK: - Map::Impl RendererObserver
|
||||
|
||||
void Map::Impl::onInvalidate() {
|
||||
@@ -232,4 +244,38 @@ void Map::Impl::onRegisterShaders(gfx::ShaderRegistry& registry) {
|
||||
observer.onRegisterShaders(registry);
|
||||
}
|
||||
|
||||
void Map::Impl::onPreCompileShader(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer.onPreCompileShader(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Map::Impl::onPostCompileShader(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer.onPostCompileShader(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Map::Impl::onShaderCompileFailed(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer.onShaderCompileFailed(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Map::Impl::onGlyphsLoaded(const FontStack& fontStack, const GlyphRange& ranges) {
|
||||
observer.onGlyphsLoaded(fontStack, ranges);
|
||||
}
|
||||
|
||||
void Map::Impl::onGlyphsError(const FontStack& fontStack, const GlyphRange& ranges, std::exception_ptr ex) {
|
||||
observer.onGlyphsError(fontStack, ranges, ex);
|
||||
}
|
||||
|
||||
void Map::Impl::onGlyphsRequested(const FontStack& fontStack, const GlyphRange& ranges) {
|
||||
observer.onGlyphsRequested(fontStack, ranges);
|
||||
}
|
||||
|
||||
void Map::Impl::onTileAction(TileOperation op, const OverscaledTileID& id, const std::string& sourceID) {
|
||||
observer.onTileAction(op, id, sourceID);
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <mbgl/style/source.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/util/size.hpp>
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -40,6 +41,9 @@ public:
|
||||
void onStyleLoading() final;
|
||||
void onStyleLoaded() final;
|
||||
void onStyleError(std::exception_ptr) final;
|
||||
void onSpriteLoaded(const std::optional<style::Sprite>&) final;
|
||||
void onSpriteError(const std::optional<style::Sprite>&, std::exception_ptr) final;
|
||||
void onSpriteRequested(const std::optional<style::Sprite>&) final;
|
||||
|
||||
// RendererObserver
|
||||
void onInvalidate() final;
|
||||
@@ -52,6 +56,14 @@ public:
|
||||
void onRemoveUnusedStyleImages(const std::vector<std::string>&) final;
|
||||
void onRegisterShaders(gfx::ShaderRegistry&) final;
|
||||
|
||||
void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) final;
|
||||
void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) final;
|
||||
void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) final;
|
||||
void onGlyphsLoaded(const FontStack&, const GlyphRange&) final;
|
||||
void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) final;
|
||||
void onGlyphsRequested(const FontStack&, const GlyphRange&) final;
|
||||
void onTileAction(TileOperation op, const OverscaledTileID&, const std::string&) final;
|
||||
|
||||
// Map
|
||||
void jumpTo(const CameraOptions&);
|
||||
|
||||
|
||||
@@ -87,7 +87,8 @@ BufferResource Context::createBuffer(
|
||||
// `NS::Object::sendMessage`, and the alignment rules are different. We assume that, because
|
||||
// `NS::Object` does not use virtual methods and only serves as a way for C++ code to store
|
||||
// and pass ObjC `id`s to `objc_msgSend`, this won't cause any real problems.
|
||||
UniqueShaderProgram Context::createProgram(std::string name,
|
||||
UniqueShaderProgram Context::createProgram(shaders::BuiltIn shaderID,
|
||||
std::string name,
|
||||
const std::string_view source,
|
||||
const std::string_view vertexName,
|
||||
const std::string_view fragmentName,
|
||||
@@ -99,17 +100,21 @@ UniqueShaderProgram Context::createProgram(std::string name,
|
||||
const auto& programDefines = programParameters.getDefines();
|
||||
const auto numDefines = programDefines.size() + additionalDefines.size();
|
||||
|
||||
std::string defineStr;
|
||||
std::vector<const NS::Object*> rawDefines;
|
||||
rawDefines.reserve(2 * numDefines);
|
||||
const auto addDefine = [&rawDefines](const auto& pair) {
|
||||
const auto addDefine = [&rawDefines, &defineStr](const auto& pair) {
|
||||
const auto* nsKey = NS::String::string(pair.first.data(), NS::UTF8StringEncoding);
|
||||
const auto* nsVal = NS::String::string(pair.second.data(), NS::UTF8StringEncoding);
|
||||
rawDefines.insert(std::next(rawDefines.begin(), rawDefines.size() / 2), nsKey);
|
||||
rawDefines.insert(rawDefines.end(), nsVal);
|
||||
defineStr += "#define " + pair.first + " " + pair.second + "\n";
|
||||
};
|
||||
std::for_each(programDefines.begin(), programDefines.end(), addDefine);
|
||||
std::for_each(additionalDefines.begin(), additionalDefines.end(), addDefine);
|
||||
|
||||
observer->onPreCompileShader(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
|
||||
const auto nsDefines = NS::Dictionary::dictionary(
|
||||
&rawDefines[numDefines], rawDefines.data(), static_cast<NS::UInteger>(numDefines));
|
||||
rawDefines.clear();
|
||||
@@ -142,6 +147,7 @@ UniqueShaderProgram Context::createProgram(std::string name,
|
||||
const auto errPtr = error ? error->localizedDescription()->utf8String() : nullptr;
|
||||
const auto errStr = (errPtr && errPtr[0]) ? ": " + std::string(errPtr) : std::string();
|
||||
Log::Error(Event::Shader, name + " compile failed" + errStr);
|
||||
observer->onShaderCompileFailed(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -150,6 +156,7 @@ UniqueShaderProgram Context::createProgram(std::string name,
|
||||
MTLFunctionPtr vertexFunction = NS::TransferPtr(library->newFunction(nsVertName));
|
||||
if (!vertexFunction) {
|
||||
Log::Error(Event::Shader, name + " missing vertex function " + vertexName.data());
|
||||
observer->onShaderCompileFailed(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -161,13 +168,17 @@ UniqueShaderProgram Context::createProgram(std::string name,
|
||||
fragmentFunction = NS::TransferPtr(library->newFunction(nsFragName));
|
||||
if (!fragmentFunction) {
|
||||
Log::Error(Event::Shader, name + " missing fragment function " + fragmentName.data());
|
||||
observer->onShaderCompileFailed(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<ShaderProgram>(
|
||||
auto shader = std::make_unique<ShaderProgram>(
|
||||
std::move(name), backend, std::move(vertexFunction), std::move(fragmentFunction));
|
||||
observer->onPostCompileShader(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
MTLTexturePtr Context::createMetalTexture(MTLTextureDescriptorPtr textureDescriptor) const {
|
||||
|
||||
@@ -34,6 +34,12 @@ ProgramParameters ProgramParameters::withDefaultSource(const ProgramSource& sour
|
||||
return params;
|
||||
}
|
||||
|
||||
ProgramParameters ProgramParameters::withProgramType(shaders::BuiltIn type) const noexcept {
|
||||
ProgramParameters params = *this;
|
||||
params.programType = type;
|
||||
return params;
|
||||
}
|
||||
|
||||
const std::string& ProgramParameters::getDefinesString() const {
|
||||
if (definesStr.empty() && !defines.empty()) {
|
||||
definesStr.assign(defines.size() * 32, '\0');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/backend.hpp>
|
||||
#include <mbgl/shaders/shader_source.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
@@ -42,6 +43,13 @@ public:
|
||||
/// @return Mutated ProgramParameters
|
||||
ProgramParameters withDefaultSource(const ProgramSource& source) const noexcept;
|
||||
|
||||
/// @brief Provide a `BuiltIn` value used to indicate the program type
|
||||
/// @param source ProgramSource
|
||||
/// @return Mutated ProgramParameters
|
||||
ProgramParameters withProgramType(shaders::BuiltIn type) const noexcept;
|
||||
|
||||
shaders::BuiltIn getProgramType() const noexcept { return programType; }
|
||||
|
||||
/// @brief Get a list of built-in shader preprocessor defines
|
||||
/// @return Shader source string
|
||||
/// @todo With the addition of future backends, defines should also be backend-aware
|
||||
@@ -67,6 +75,7 @@ public:
|
||||
private:
|
||||
std::unordered_map<std::string, std::string> defines;
|
||||
std::uint64_t definesHash;
|
||||
shaders::BuiltIn programType = shaders::BuiltIn::None;
|
||||
|
||||
// cached value of `defines` converted to string format
|
||||
mutable std::string definesStr;
|
||||
|
||||
@@ -1033,6 +1033,10 @@ void RenderOrchestrator::updateDebugLayerGroups(const RenderTree& renderTree, Pa
|
||||
|
||||
#endif // MLN_DRAWABLE_RENDERER
|
||||
|
||||
void RenderOrchestrator::onGlyphsLoaded(const FontStack& fontStack, const GlyphRange& range) {
|
||||
observer->onGlyphsLoaded(fontStack, range);
|
||||
}
|
||||
|
||||
void RenderOrchestrator::onGlyphsError(const FontStack& fontStack,
|
||||
const GlyphRange& glyphRange,
|
||||
std::exception_ptr error) {
|
||||
@@ -1045,6 +1049,10 @@ void RenderOrchestrator::onGlyphsError(const FontStack& fontStack,
|
||||
observer->onResourceError(error);
|
||||
}
|
||||
|
||||
void RenderOrchestrator::onGlyphsRequested(const FontStack& fontStack, const GlyphRange& range) {
|
||||
observer->onGlyphsRequested(fontStack, range);
|
||||
}
|
||||
|
||||
void RenderOrchestrator::onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
@@ -1060,6 +1068,13 @@ void RenderOrchestrator::onTileChanged(RenderSource&, const OverscaledTileID&) {
|
||||
observer->onInvalidate();
|
||||
}
|
||||
|
||||
void RenderOrchestrator::onTileAction(RenderSource&,
|
||||
TileOperation op,
|
||||
const OverscaledTileID& id,
|
||||
const std::string& sourceID) {
|
||||
observer->onTileAction(op, id, sourceID);
|
||||
}
|
||||
|
||||
void RenderOrchestrator::onStyleImageMissing(const std::string& id, const std::function<void()>& done) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
|
||||
@@ -169,11 +169,13 @@ private:
|
||||
const std::unordered_map<std::string, const RenderLayer*>&) const;
|
||||
|
||||
// GlyphManagerObserver implementation.
|
||||
void onGlyphsLoaded(const FontStack&, const GlyphRange&) override;
|
||||
void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) override;
|
||||
|
||||
void onGlyphsRequested(const FontStack&, const GlyphRange&) override;
|
||||
// RenderSourceObserver implementation.
|
||||
void onTileChanged(RenderSource&, const OverscaledTileID&) override;
|
||||
void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;
|
||||
void onTileAction(RenderSource&, TileOperation, const OverscaledTileID&, const std::string&) override;
|
||||
|
||||
// ImageManagerObserver implementation
|
||||
void onStyleImageMissing(const std::string&, const std::function<void()>&) override;
|
||||
|
||||
@@ -78,6 +78,10 @@ void RenderSource::onTileError(Tile& tile, std::exception_ptr error) {
|
||||
observer->onTileError(*this, tile.id, error);
|
||||
}
|
||||
|
||||
void RenderSource::onTileAction(OverscaledTileID id, std::string sourceID, TileOperation op) {
|
||||
observer->onTileAction(*this, op, id, sourceID);
|
||||
}
|
||||
|
||||
bool RenderSource::isEnabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ protected:
|
||||
|
||||
void onTileChanged(Tile&) override;
|
||||
void onTileError(Tile&, std::exception_ptr) final;
|
||||
void onTileAction(OverscaledTileID, std::string, TileOperation) override;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -13,6 +15,7 @@ public:
|
||||
|
||||
virtual void onTileChanged(RenderSource&, const OverscaledTileID&) {}
|
||||
virtual void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) {}
|
||||
virtual void onTileAction(RenderSource&, TileOperation, const OverscaledTileID&, const std::string&) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -68,6 +68,24 @@ Renderer::Impl::~Impl() {
|
||||
assert(gfx::BackendScope::exists());
|
||||
};
|
||||
|
||||
void Renderer::Impl::onPreCompileShader(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer->onPreCompileShader(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Renderer::Impl::onPostCompileShader(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer->onPostCompileShader(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Renderer::Impl::onShaderCompileFailed(shaders::BuiltIn shaderID,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) {
|
||||
observer->onShaderCompileFailed(shaderID, type, additionalDefines);
|
||||
}
|
||||
|
||||
void Renderer::Impl::setObserver(RendererObserver* observer_) {
|
||||
observer = observer_ ? observer_ : &nullObserver();
|
||||
}
|
||||
@@ -76,6 +94,8 @@ void Renderer::Impl::render(const RenderTree& renderTree,
|
||||
[[maybe_unused]] const std::shared_ptr<UpdateParameters>& updateParameters) {
|
||||
MLN_TRACE_FUNC();
|
||||
auto& context = backend.getContext();
|
||||
context.setObserver(this);
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
if constexpr (EnableMetalCapture) {
|
||||
const auto& mtlBackend = static_cast<mtl::RendererBackend&>(backend);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/render_orchestrator.hpp>
|
||||
#include <mbgl/gfx/context_observer.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#include <mbgl/mtl/mtl_fwd.hpp>
|
||||
@@ -21,10 +22,15 @@ class RendererBackend;
|
||||
class ShadeRegistry;
|
||||
} // namespace gfx
|
||||
|
||||
class Renderer::Impl {
|
||||
class Renderer::Impl : public gfx::ContextObserver {
|
||||
public:
|
||||
Impl(gfx::RendererBackend&, float pixelRatio_, const std::optional<std::string>& localFontFamily_);
|
||||
~Impl();
|
||||
virtual ~Impl();
|
||||
|
||||
// ContextObserver
|
||||
void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) override;
|
||||
void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) override;
|
||||
void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) override;
|
||||
|
||||
private:
|
||||
friend class Renderer;
|
||||
|
||||
@@ -49,9 +49,9 @@ void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_
|
||||
impl().getTileOptions()->tileSize,
|
||||
impl().getZoomRange(),
|
||||
{},
|
||||
[&](const OverscaledTileID& tileID) {
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<CustomGeometryTile>(
|
||||
tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader);
|
||||
tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader, observer_);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
|
||||
util::tileSize_I,
|
||||
impl().getZoomRange(),
|
||||
std::optional<LatLngBounds>{},
|
||||
[&, data_](const OverscaledTileID& tileID) {
|
||||
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data_);
|
||||
[&, data_](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data_, observer_);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,17 @@ void RenderRasterDEMSource::updateInternal(const Tileset& tileset,
|
||||
const bool needsRendering,
|
||||
const bool needsRelayout,
|
||||
const TileParameters& parameters) {
|
||||
tilePyramid.update(
|
||||
layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
impl().getTileSize(),
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterDEMTile>(tileID, parameters, tileset); });
|
||||
tilePyramid.update(layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
impl().getTileSize(),
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<RasterDEMTile>(tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
});
|
||||
algorithm::updateTileMasks(tilePyramid.getRenderedTiles());
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,17 @@ void RenderRasterSource::updateInternal(const Tileset& tileset,
|
||||
const bool needsRendering,
|
||||
const bool needsRelayout,
|
||||
const TileParameters& parameters) {
|
||||
tilePyramid.update(
|
||||
layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
impl().getTileSize(),
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterTile>(tileID, parameters, tileset); });
|
||||
tilePyramid.update(layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
impl().getTileSize(),
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<RasterTile>(tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
});
|
||||
algorithm::updateTileMasks(tilePyramid.getRenderedTiles());
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ void RenderVectorSource::updateInternal(const Tileset& tileset,
|
||||
util::tileSize_I,
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID) {
|
||||
return std::make_unique<VectorTile>(tileID, baseImpl->id, parameters, tileset);
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<VectorTile>(tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ void TilePyramid::update(const std::vector<Immutable<style::LayerProperties>>& l
|
||||
const uint16_t tileSize,
|
||||
const Range<uint8_t> zoomRange,
|
||||
std::optional<LatLngBounds> bounds,
|
||||
std::function<std::unique_ptr<Tile>(const OverscaledTileID&)> createTile) {
|
||||
std::function<std::unique_ptr<Tile>(const OverscaledTileID&, TileObserver*)> createTile) {
|
||||
// If we need a relayout, abandon any cached tiles; they're now stale.
|
||||
if (needsRelayout) {
|
||||
cache.clear();
|
||||
@@ -172,9 +172,8 @@ void TilePyramid::update(const std::vector<Immutable<style::LayerProperties>>& l
|
||||
}
|
||||
std::unique_ptr<Tile> tile = cache.pop(tileID);
|
||||
if (!tile) {
|
||||
tile = createTile(tileID);
|
||||
tile = createTile(tileID, observer);
|
||||
if (!tile) return nullptr;
|
||||
tile->setObserver(observer);
|
||||
tile->setLayers(layers);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
uint16_t tileSize,
|
||||
Range<uint8_t> zoomRange,
|
||||
std::optional<LatLngBounds> bounds,
|
||||
std::function<std::unique_ptr<Tile>(const OverscaledTileID&)> createTile);
|
||||
std::function<std::unique_ptr<Tile>(const OverscaledTileID&, TileObserver*)> createTile);
|
||||
|
||||
const std::map<UnwrappedTileID, std::reference_wrapper<Tile>>& getRenderedTiles() const { return renderedTiles; }
|
||||
Tile* getTile(const OverscaledTileID&);
|
||||
|
||||
@@ -118,65 +118,77 @@ std::shared_ptr<ShaderProgramGL> ShaderProgramGL::create(
|
||||
const std::string& vertexSource,
|
||||
const std::string& fragmentSource,
|
||||
const std::string& additionalDefines) noexcept(false) {
|
||||
// throws on compile error
|
||||
auto vertProg = context.createShader(
|
||||
ShaderType::Vertex,
|
||||
std::initializer_list<const char*>{
|
||||
"#version 300 es\n",
|
||||
programParameters.getDefinesString().c_str(),
|
||||
additionalDefines.c_str(),
|
||||
shaders::ShaderSource<shaders::BuiltIn::Prelude, gfx::Backend::Type::OpenGL>::vertex,
|
||||
vertexSource.c_str()});
|
||||
auto fragProg = context.createShader(
|
||||
ShaderType::Fragment,
|
||||
{"#version 300 es\n",
|
||||
programParameters.getDefinesString().c_str(),
|
||||
additionalDefines.c_str(),
|
||||
shaders::ShaderSource<shaders::BuiltIn::Prelude, gfx::Backend::Type::OpenGL>::fragment,
|
||||
fragmentSource.c_str()});
|
||||
auto program = context.createProgram(vertProg, fragProg, firstAttribName.data());
|
||||
try {
|
||||
context.getObserver().onPreCompileShader(
|
||||
programParameters.getProgramType(), gfx::Backend::Type::OpenGL, additionalDefines);
|
||||
|
||||
UniformBlockArrayGL uniformBlocks;
|
||||
for (const auto& blockInfo : uniformBlocksInfo) {
|
||||
GLint index = MBGL_CHECK_ERROR(glGetUniformBlockIndex(program, blockInfo.name.data()));
|
||||
GLint size = 0;
|
||||
MBGL_CHECK_ERROR(glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size));
|
||||
assert(size > 0);
|
||||
GLint binding = static_cast<GLint>(blockInfo.binding);
|
||||
MBGL_CHECK_ERROR(glUniformBlockBinding(program, index, binding));
|
||||
uniformBlocks.set(blockInfo.id, binding, size);
|
||||
}
|
||||
// throws on compile error
|
||||
auto vertProg = context.createShader(
|
||||
ShaderType::Vertex,
|
||||
std::initializer_list<const char*>{
|
||||
"#version 300 es\n",
|
||||
programParameters.getDefinesString().c_str(),
|
||||
additionalDefines.c_str(),
|
||||
shaders::ShaderSource<shaders::BuiltIn::Prelude, gfx::Backend::Type::OpenGL>::vertex,
|
||||
vertexSource.c_str()});
|
||||
auto fragProg = context.createShader(
|
||||
ShaderType::Fragment,
|
||||
{"#version 300 es\n",
|
||||
programParameters.getDefinesString().c_str(),
|
||||
additionalDefines.c_str(),
|
||||
shaders::ShaderSource<shaders::BuiltIn::Prelude, gfx::Backend::Type::OpenGL>::fragment,
|
||||
fragmentSource.c_str()});
|
||||
auto program = context.createProgram(vertProg, fragProg, firstAttribName.data());
|
||||
|
||||
SamplerLocationArray samplerLocations;
|
||||
for (const auto& textureInfo : texturesInfo) {
|
||||
GLint location = MBGL_CHECK_ERROR(glGetUniformLocation(program, textureInfo.name.data()));
|
||||
assert(location != -1);
|
||||
if (location != -1) {
|
||||
samplerLocations[textureInfo.id] = location;
|
||||
context.getObserver().onPostCompileShader(
|
||||
programParameters.getProgramType(), gfx::Backend::Type::OpenGL, additionalDefines);
|
||||
|
||||
UniformBlockArrayGL uniformBlocks;
|
||||
for (const auto& blockInfo : uniformBlocksInfo) {
|
||||
GLint index = MBGL_CHECK_ERROR(glGetUniformBlockIndex(program, blockInfo.name.data()));
|
||||
GLint size = 0;
|
||||
MBGL_CHECK_ERROR(glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size));
|
||||
assert(size > 0);
|
||||
GLint binding = static_cast<GLint>(blockInfo.binding);
|
||||
MBGL_CHECK_ERROR(glUniformBlockBinding(program, index, binding));
|
||||
uniformBlocks.set(blockInfo.id, binding, size);
|
||||
}
|
||||
}
|
||||
|
||||
VertexAttributeArrayGL attrs;
|
||||
GLint count = 0;
|
||||
GLint maxLength = 0;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &count));
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength));
|
||||
auto name = std::vector<GLchar>(maxLength);
|
||||
for (GLint index = 0; index < count; ++index) {
|
||||
GLsizei length = 0; // "number of characters actually written in name (excluding the null terminator)"
|
||||
GLint size = 0; // "size of the attribute variable, in units of the type returned in type"
|
||||
GLenum glType = 0;
|
||||
MBGL_CHECK_ERROR(glGetActiveAttrib(program, index, maxLength, &length, &size, &glType, name.data()));
|
||||
if (!strncmp(name.data(), "gl_", 3)) { // Is there a better way to detect built-in attributes?
|
||||
continue;
|
||||
SamplerLocationArray samplerLocations;
|
||||
for (const auto& textureInfo : texturesInfo) {
|
||||
GLint location = MBGL_CHECK_ERROR(glGetUniformLocation(program, textureInfo.name.data()));
|
||||
assert(location != -1);
|
||||
if (location != -1) {
|
||||
samplerLocations[textureInfo.id] = location;
|
||||
}
|
||||
}
|
||||
const GLint location = MBGL_CHECK_ERROR(glGetAttribLocation(program, name.data()));
|
||||
assert(attributesInfo[location].name == std::string_view(name.data()));
|
||||
addAttr(attrs, attributesInfo[location].id, location, length, size, glType);
|
||||
}
|
||||
|
||||
return std::make_shared<ShaderProgramGL>(
|
||||
std::move(program), std::move(uniformBlocks), std::move(attrs), std::move(samplerLocations));
|
||||
VertexAttributeArrayGL attrs;
|
||||
GLint count = 0;
|
||||
GLint maxLength = 0;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &count));
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength));
|
||||
auto name = std::vector<GLchar>(maxLength);
|
||||
for (GLint index = 0; index < count; ++index) {
|
||||
GLsizei length = 0; // "number of characters actually written in name (excluding the null terminator)"
|
||||
GLint size = 0; // "size of the attribute variable, in units of the type returned in type"
|
||||
GLenum glType = 0;
|
||||
MBGL_CHECK_ERROR(glGetActiveAttrib(program, index, maxLength, &length, &size, &glType, name.data()));
|
||||
if (!strncmp(name.data(), "gl_", 3)) { // Is there a better way to detect built-in attributes?
|
||||
continue;
|
||||
}
|
||||
const GLint location = MBGL_CHECK_ERROR(glGetAttribLocation(program, name.data()));
|
||||
assert(attributesInfo[location].name == std::string_view(name.data()));
|
||||
addAttr(attrs, attributesInfo[location].id, location, length, size, glType);
|
||||
}
|
||||
|
||||
return std::make_shared<ShaderProgramGL>(
|
||||
std::move(program), std::move(uniformBlocks), std::move(attrs), std::move(samplerLocations));
|
||||
} catch (const std::exception& e) {
|
||||
context.getObserver().onShaderCompileFailed(
|
||||
programParameters.getProgramType(), gfx::Backend::Type::OpenGL, additionalDefines);
|
||||
std::rethrow_exception(std::current_exception());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -26,26 +26,29 @@ namespace mbgl {
|
||||
|
||||
namespace vulkan {
|
||||
|
||||
ShaderProgram::ShaderProgram(const std::string& name,
|
||||
ShaderProgram::ShaderProgram(shaders::BuiltIn shaderID,
|
||||
const std::string& name,
|
||||
const std::string_view& vertex,
|
||||
const std::string_view& fragment,
|
||||
const ProgramParameters& programParameters,
|
||||
const mbgl::unordered_map<std::string, std::string>& additionalDefines,
|
||||
RendererBackend& backend_)
|
||||
RendererBackend& backend_,
|
||||
gfx::ContextObserver& observer)
|
||||
: ShaderProgramBase(),
|
||||
shaderName(name),
|
||||
backend(backend_) {
|
||||
std::string defineStr = programParameters.getDefinesString() + "\n\n";
|
||||
for (const auto& define : additionalDefines) {
|
||||
defineStr += "#define " + define.first + " " + define.second + "\n";
|
||||
}
|
||||
observer.onPreCompileShader(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
|
||||
constexpr auto targetClientVersion = glslang::EShTargetVulkan_1_0;
|
||||
constexpr auto targetLanguageVersion = glslang::EShTargetSpv_1_0;
|
||||
constexpr auto defaultVersion = 450;
|
||||
constexpr auto messages = EShMsgSpvRules | EShMsgVulkanRules;
|
||||
const auto defaultResources = GetDefaultResources();
|
||||
|
||||
std::string defineStr = programParameters.getDefinesString() + "\n\n";
|
||||
for (const auto& define : additionalDefines) {
|
||||
defineStr += "#define " + define.first + " " + define.second + "\n";
|
||||
}
|
||||
|
||||
const auto compileGlsl = [&](const EShLanguage& language, const std::string_view& data, const char* prelude) {
|
||||
glslang::TShader glslShader(language);
|
||||
|
||||
@@ -61,6 +64,7 @@ ShaderProgram::ShaderProgram(const std::string& name,
|
||||
|
||||
if (!glslShader.parse(defaultResources, defaultVersion, ENoProfile, false, true, messages)) {
|
||||
mbgl::Log::Error(mbgl::Event::Shader, shaderName + " - " + glslShader.getInfoLog());
|
||||
observer.onShaderCompileFailed(shaderID, gfx::Backend::Type::Vulkan, defineStr);
|
||||
return std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
@@ -69,6 +73,7 @@ ShaderProgram::ShaderProgram(const std::string& name,
|
||||
|
||||
if (!glslProgram.link(messages)) {
|
||||
mbgl::Log::Error(mbgl::Event::Shader, shaderName + " - " + glslProgram.getInfoLog());
|
||||
observer.onShaderCompileFailed(shaderID, gfx::Backend::Type::Vulkan, defineStr);
|
||||
return std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
@@ -100,6 +105,8 @@ ShaderProgram::ShaderProgram(const std::string& name,
|
||||
|
||||
backend.setDebugName(vertexShader.get(), shaderName + ".vert");
|
||||
backend.setDebugName(fragmentShader.get(), shaderName + ".frag");
|
||||
|
||||
observer.onPostCompileShader(shaderID, gfx::Backend::Type::Metal, defineStr);
|
||||
}
|
||||
|
||||
ShaderProgram::~ShaderProgram() noexcept = default;
|
||||
|
||||
@@ -40,6 +40,8 @@ void SpriteLoader::load(const std::optional<style::Sprite> sprite, FileSource& f
|
||||
return;
|
||||
}
|
||||
|
||||
observer->onSpriteRequested(sprite);
|
||||
|
||||
std::string id = sprite->id;
|
||||
std::string url = sprite->spriteURL;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ public:
|
||||
virtual void onSpriteLoaded(std::optional<style::Sprite>, std::vector<Immutable<style::Image::Impl>>) {}
|
||||
|
||||
virtual void onSpriteError(std::optional<style::Sprite>, std::exception_ptr) {}
|
||||
|
||||
virtual void onSpriteRequested(const std::optional<style::Sprite>&) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/source_observer.hpp>
|
||||
#include <mbgl/style/sprite.hpp>
|
||||
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
@@ -14,6 +16,10 @@ public:
|
||||
virtual void onUpdate() {}
|
||||
virtual void onStyleError(std::exception_ptr) {}
|
||||
virtual void onResourceError(std::exception_ptr) {}
|
||||
|
||||
virtual void onSpriteLoaded(const std::optional<Sprite>&) {}
|
||||
virtual void onSpriteError(const std::optional<Sprite>&, std::exception_ptr) {}
|
||||
virtual void onSpriteRequested(const std::optional<Sprite>&) {}
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
|
||||
@@ -386,6 +386,7 @@ void Style::Impl::onSpriteLoaded(std::optional<style::Sprite> sprite,
|
||||
spritesLoadingStatus["default"] = true;
|
||||
}
|
||||
observer->onUpdate(); // For *-pattern properties.
|
||||
observer->onSpriteLoaded(sprite);
|
||||
}
|
||||
|
||||
void Style::Impl::onSpriteError(std::optional<style::Sprite> sprite, std::exception_ptr error) {
|
||||
@@ -399,6 +400,11 @@ void Style::Impl::onSpriteError(std::optional<style::Sprite> sprite, std::except
|
||||
}
|
||||
// Unblock rendering tiles (even though sprite request has failed).
|
||||
observer->onUpdate();
|
||||
observer->onSpriteError(sprite, error);
|
||||
}
|
||||
|
||||
void Style::Impl::onSpriteRequested(const std::optional<style::Sprite>& sprite) {
|
||||
observer->onSpriteRequested(sprite);
|
||||
}
|
||||
|
||||
void Style::Impl::onLayerChanged(Layer& layer) {
|
||||
|
||||
@@ -118,6 +118,7 @@ private:
|
||||
// SpriteLoaderObserver implementation.
|
||||
void onSpriteLoaded(std::optional<style::Sprite> sprite, std::vector<Immutable<style::Image::Impl>>) override;
|
||||
void onSpriteError(std::optional<style::Sprite> sprite, std::exception_ptr) override;
|
||||
void onSpriteRequested(const std::optional<style::Sprite>&) override;
|
||||
|
||||
// SourceObserver implementation.
|
||||
void onSourceLoaded(Source&) override;
|
||||
|
||||
@@ -76,6 +76,8 @@ void GlyphManager::requestRange(GlyphRequest& request,
|
||||
return;
|
||||
}
|
||||
|
||||
observer->onGlyphsRequested(fontStack, range);
|
||||
|
||||
request.req = fileSource.request(
|
||||
Resource::glyphs(glyphURL, fontStack, range),
|
||||
[this, fontStack, range](const Response& res) { processResponse(res, fontStack, range); });
|
||||
|
||||
@@ -14,6 +14,7 @@ public:
|
||||
|
||||
virtual void onGlyphsLoaded(const FontStack&, const GlyphRange&) {}
|
||||
virtual void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) {}
|
||||
virtual void onGlyphsRequested(const FontStack&, const GlyphRange&) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -18,8 +18,9 @@ CustomGeometryTile::CustomGeometryTile(const OverscaledTileID& overscaledTileID,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
Immutable<style::CustomGeometrySource::TileOptions> options_,
|
||||
ActorRef<style::CustomTileLoader> loader_)
|
||||
: GeometryTile(overscaledTileID, std::move(sourceID_), parameters),
|
||||
ActorRef<style::CustomTileLoader> loader_,
|
||||
TileObserver* observer_)
|
||||
: GeometryTile(overscaledTileID, std::move(sourceID_), parameters, observer_),
|
||||
necessity(TileNecessity::Optional),
|
||||
options(std::move(options_)),
|
||||
loader(std::move(loader_)),
|
||||
|
||||
@@ -17,10 +17,11 @@ class CustomTileLoader;
|
||||
class CustomGeometryTile : public GeometryTile {
|
||||
public:
|
||||
CustomGeometryTile(const OverscaledTileID&,
|
||||
std::string sourceID,
|
||||
std::string,
|
||||
const TileParameters&,
|
||||
Immutable<style::CustomGeometrySource::TileOptions>,
|
||||
ActorRef<style::CustomTileLoader> loader);
|
||||
ActorRef<style::CustomTileLoader> loader,
|
||||
TileObserver* observer = nullptr);
|
||||
~CustomGeometryTile() override;
|
||||
|
||||
void setTileData(const GeoJSON& geoJSON);
|
||||
@@ -32,6 +33,7 @@ public:
|
||||
|
||||
private:
|
||||
bool stale = true;
|
||||
std::string sourceID;
|
||||
TileNecessity necessity;
|
||||
Immutable<style::CustomGeometrySource::TileOptions> options;
|
||||
ActorRef<style::CustomTileLoader> loader;
|
||||
|
||||
@@ -11,8 +11,9 @@ namespace mbgl {
|
||||
GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
std::shared_ptr<style::GeoJSONData> data_)
|
||||
: GeometryTile(overscaledTileID, std::move(sourceID_), parameters) {
|
||||
std::shared_ptr<style::GeoJSONData> data_,
|
||||
TileObserver* observer_)
|
||||
: GeometryTile(overscaledTileID, std::move(sourceID_), parameters, observer_) {
|
||||
updateData(std::move(data_), false /*needsRelayout*/);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ public:
|
||||
GeoJSONTile(const OverscaledTileID&,
|
||||
std::string sourceID,
|
||||
const TileParameters&,
|
||||
std::shared_ptr<style::GeoJSONData>);
|
||||
std::shared_ptr<style::GeoJSONData>,
|
||||
TileObserver* observer = nullptr);
|
||||
|
||||
void updateData(std::shared_ptr<style::GeoJSONData> data, bool needsRelayout = false);
|
||||
|
||||
|
||||
@@ -166,10 +166,12 @@ const LayerRenderData* GeometryTileRenderData::getLayerRenderData(const style::L
|
||||
that could flag the tile as non-pending too early.
|
||||
*/
|
||||
|
||||
GeometryTile::GeometryTile(const OverscaledTileID& id_, std::string sourceID_, const TileParameters& parameters)
|
||||
: Tile(Kind::Geometry, id_),
|
||||
GeometryTile::GeometryTile(const OverscaledTileID& id_,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
TileObserver* observer_)
|
||||
: Tile(Kind::Geometry, id_, std::move(sourceID_), observer_),
|
||||
ImageRequestor(parameters.imageManager),
|
||||
sourceID(std::move(sourceID_)),
|
||||
threadPool(parameters.threadPool),
|
||||
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
|
||||
worker(parameters.threadPool, // Scheduler reference for the Actor retainer
|
||||
@@ -195,6 +197,11 @@ GeometryTile::~GeometryTile() {
|
||||
glyphManager->removeRequestor(*this);
|
||||
imageManager->removeRequestor(*this);
|
||||
|
||||
if (pending) {
|
||||
// This tile never finished loading or was abandoned, emit a cancellation event
|
||||
observer->onTileAction(id, sourceID, TileOperation::Cancelled);
|
||||
}
|
||||
|
||||
if (layoutResult) {
|
||||
threadPool.runOnRenderThread(
|
||||
[layoutResult_{std::move(layoutResult)}, atlasTextures_{std::move(atlasTextures)}]() {});
|
||||
@@ -222,6 +229,10 @@ void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data_) {
|
||||
observer->onTileAction(id, sourceID, TileOperation::StartParse);
|
||||
}
|
||||
|
||||
// Mark the tile as pending again if it was complete before to prevent
|
||||
// signaling a complete state despite pending parse operations.
|
||||
pending = true;
|
||||
@@ -238,6 +249,8 @@ void GeometryTile::reset() {
|
||||
// signaling a complete state despite pending parse operations.
|
||||
pending = true;
|
||||
|
||||
observer->onTileAction(id, sourceID, TileOperation::Cancelled);
|
||||
|
||||
++correlationID;
|
||||
worker.self().invoke(&GeometryTileWorker::reset, correlationID);
|
||||
}
|
||||
@@ -319,6 +332,10 @@ void GeometryTile::onLayout(std::shared_ptr<LayoutResult> result, const uint64_t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pending) {
|
||||
observer->onTileAction(id, sourceID, TileOperation::EndParse);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryTile::onError(std::exception_ptr err, const uint64_t resultCorrelationID) {
|
||||
|
||||
@@ -30,7 +30,10 @@ class GeometryTile : public Tile, public GlyphRequestor, public ImageRequestor {
|
||||
public:
|
||||
const std::thread::id renderThreadID = std::this_thread::get_id();
|
||||
|
||||
GeometryTile(const OverscaledTileID&, std::string sourceID, const TileParameters&);
|
||||
GeometryTile(const OverscaledTileID&,
|
||||
std::string sourceID,
|
||||
const TileParameters&,
|
||||
TileObserver* observer = nullptr);
|
||||
|
||||
~GeometryTile() override;
|
||||
|
||||
@@ -94,8 +97,6 @@ public:
|
||||
void performedFadePlacement() override;
|
||||
std::shared_ptr<FeatureIndex> getFeatureIndex() const;
|
||||
|
||||
const std::string sourceID;
|
||||
|
||||
void setFeatureState(const LayerFeatureStates&) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_, const TileParameters& parameters, const Tileset& tileset)
|
||||
: Tile(Kind::RasterDEM, id_),
|
||||
RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
const Tileset& tileset,
|
||||
TileObserver* observer_)
|
||||
: Tile(Kind::RasterDEM, id_, std::move(sourceID_), observer_),
|
||||
loader(*this, id_, parameters, tileset),
|
||||
threadPool(parameters.threadPool),
|
||||
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
|
||||
@@ -35,6 +39,11 @@ RasterDEMTile::RasterDEMTile(const OverscaledTileID& id_, const TileParameters&
|
||||
RasterDEMTile::~RasterDEMTile() {
|
||||
markObsolete();
|
||||
|
||||
if (pending) {
|
||||
// This tile never finished loading or was abandoned, emit a cancellation event
|
||||
observer->onTileAction(id, sourceID, TileOperation::Cancelled);
|
||||
}
|
||||
|
||||
// The bucket has resources that need to be released on the render thread.
|
||||
if (bucket) {
|
||||
threadPool.runOnRenderThread([bucket_{std::move(bucket)}]() {});
|
||||
@@ -59,6 +68,11 @@ void RasterDEMTile::setData(const std::shared_ptr<const std::string>& data) {
|
||||
if (!obsolete) {
|
||||
pending = true;
|
||||
++correlationID;
|
||||
|
||||
if (data) {
|
||||
observer->onTileAction(id, sourceID, TileOperation::StartParse);
|
||||
}
|
||||
|
||||
worker.self().invoke(&RasterDEMTileWorker::parse, data, correlationID, encoding);
|
||||
}
|
||||
}
|
||||
@@ -72,6 +86,7 @@ void RasterDEMTile::onParsed(std::unique_ptr<HillshadeBucket> result, const uint
|
||||
}
|
||||
renderable = static_cast<bool>(bucket);
|
||||
observer->onTileChanged(*this);
|
||||
observer->onTileAction(id, sourceID, TileOperation::EndParse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ class Layer;
|
||||
|
||||
class RasterDEMTile final : public Tile {
|
||||
public:
|
||||
RasterDEMTile(const OverscaledTileID&, const TileParameters&, const Tileset&);
|
||||
RasterDEMTile(
|
||||
const OverscaledTileID&, std::string, const TileParameters&, const Tileset&, TileObserver* observer = nullptr);
|
||||
~RasterDEMTile() override;
|
||||
|
||||
std::unique_ptr<TileRenderData> createRenderData() override;
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
RasterTile::RasterTile(const OverscaledTileID& id_, const TileParameters& parameters, const Tileset& tileset)
|
||||
: Tile(Kind::Raster, id_),
|
||||
RasterTile::RasterTile(const OverscaledTileID& id_,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
const Tileset& tileset,
|
||||
TileObserver* observer_)
|
||||
: Tile(Kind::Raster, id_, std::move(sourceID_), observer_),
|
||||
loader(*this, id_, parameters, tileset),
|
||||
threadPool(parameters.threadPool),
|
||||
mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
|
||||
@@ -24,6 +28,11 @@ RasterTile::RasterTile(const OverscaledTileID& id_, const TileParameters& parame
|
||||
RasterTile::~RasterTile() {
|
||||
markObsolete();
|
||||
|
||||
if (pending) {
|
||||
// This tile never finished loading or was abandoned, emit a cancellation event
|
||||
observer->onTileAction(id, sourceID, TileOperation::Cancelled);
|
||||
}
|
||||
|
||||
// The bucket has resources that need to be released on the render thread.
|
||||
if (bucket) {
|
||||
threadPool.runOnRenderThread([bucket_{std::move(bucket)}]() {});
|
||||
@@ -48,6 +57,11 @@ void RasterTile::setData(const std::shared_ptr<const std::string>& data) {
|
||||
if (!obsolete) {
|
||||
pending = true;
|
||||
++correlationID;
|
||||
|
||||
if (data) {
|
||||
observer->onTileAction(id, sourceID, TileOperation::StartParse);
|
||||
}
|
||||
|
||||
worker.self().invoke(&RasterTileWorker::parse, data, correlationID);
|
||||
}
|
||||
}
|
||||
@@ -61,6 +75,7 @@ void RasterTile::onParsed(std::unique_ptr<RasterBucket> result, const uint64_t r
|
||||
}
|
||||
renderable = static_cast<bool>(bucket);
|
||||
observer->onTileChanged(*this);
|
||||
observer->onTileAction(id, sourceID, TileOperation::EndParse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ class Layer;
|
||||
|
||||
class RasterTile final : public Tile {
|
||||
public:
|
||||
RasterTile(const OverscaledTileID&, const TileParameters&, const Tileset&);
|
||||
RasterTile(
|
||||
const OverscaledTileID&, std::string, const TileParameters&, const Tileset&, TileObserver* observer = nullptr);
|
||||
~RasterTile() override;
|
||||
|
||||
std::unique_ptr<TileRenderData> createRenderData() override;
|
||||
|
||||
@@ -8,10 +8,12 @@ namespace mbgl {
|
||||
|
||||
static TileObserver nullObserver;
|
||||
|
||||
Tile::Tile(Kind kind_, OverscaledTileID id_)
|
||||
Tile::Tile(Kind kind_, OverscaledTileID id_, std::string sourceID_, TileObserver* observer_)
|
||||
: kind(kind_),
|
||||
id(id_),
|
||||
observer(&nullObserver) {}
|
||||
sourceID(std::move(sourceID_)) {
|
||||
observer = observer_ ? observer_ : &nullObserver;
|
||||
}
|
||||
|
||||
Tile::~Tile() = default;
|
||||
|
||||
@@ -61,4 +63,8 @@ float Tile::getQueryPadding(const std::unordered_map<std::string, const RenderLa
|
||||
|
||||
void Tile::querySourceFeatures(std::vector<Feature>&, const SourceQueryOptions&) {}
|
||||
|
||||
void Tile::onTileAction(TileOperation op) {
|
||||
observer->onTileAction(id, sourceID, op);
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/tile_coordinate.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/tile/tile_necessity.hpp>
|
||||
#include <mbgl/tile/tile_loader_observer.hpp>
|
||||
#include <mbgl/renderer/tile_mask.hpp>
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
@@ -46,7 +47,7 @@ inline bool operator==(const TileUpdateParameters& a, const TileUpdateParameters
|
||||
inline bool operator!=(const TileUpdateParameters& a, const TileUpdateParameters& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
class Tile {
|
||||
class Tile : public TileLoaderObserver {
|
||||
public:
|
||||
enum class Kind : uint8_t {
|
||||
Geometry,
|
||||
@@ -56,8 +57,8 @@ public:
|
||||
Tile(const Tile&) = delete;
|
||||
Tile& operator=(const Tile&) = delete;
|
||||
|
||||
Tile(Kind, OverscaledTileID);
|
||||
virtual ~Tile();
|
||||
Tile(Kind, OverscaledTileID, std::string, TileObserver* observer = nullptr);
|
||||
~Tile() override;
|
||||
|
||||
virtual std::unique_ptr<TileRenderData> createRenderData() = 0;
|
||||
|
||||
@@ -135,8 +136,12 @@ public:
|
||||
|
||||
void dumpDebugLogs() const;
|
||||
|
||||
// TileLoaderObserver
|
||||
void onTileAction(TileOperation op) override;
|
||||
|
||||
const Kind kind;
|
||||
OverscaledTileID id;
|
||||
const std::string sourceID;
|
||||
std::optional<Timestamp> modified;
|
||||
std::optional<Timestamp> expires;
|
||||
// Indicates whether this tile is used for the currently visible layers on
|
||||
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
void makeOptional();
|
||||
|
||||
void loadFromCache();
|
||||
void loadedData(const Response&);
|
||||
void loadedData(const Response&, Resource::LoadingMethod);
|
||||
void loadFromNetwork();
|
||||
|
||||
bool hasPendingNetworkRequest() const {
|
||||
|
||||
@@ -106,6 +106,8 @@ void TileLoader<T>::loadFromCache() {
|
||||
return;
|
||||
}
|
||||
|
||||
tile.onTileAction(TileOperation::RequestedFromCache);
|
||||
|
||||
resource.loadingMethod = Resource::LoadingMethod::CacheOnly;
|
||||
request = fileSource->request(resource, [this, shared_{shared}](const Response& res) {
|
||||
do {
|
||||
@@ -128,7 +130,7 @@ void TileLoader<T>::loadFromCache() {
|
||||
resource.priorEtag = res.etag;
|
||||
resource.priorData = res.data;
|
||||
} else {
|
||||
loadedData(res);
|
||||
loadedData(res, Resource::LoadingMethod::CacheOnly);
|
||||
}
|
||||
|
||||
if (necessity == TileNecessity::Required) {
|
||||
@@ -157,10 +159,19 @@ void TileLoader<T>::makeOptional() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TileLoader<T>::loadedData(const Response& res) {
|
||||
void TileLoader<T>::loadedData(const Response& res, Resource::LoadingMethod method) {
|
||||
if (res.error && res.error->reason != Response::Error::Reason::NotFound) {
|
||||
tile.setError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
||||
} else if (res.notModified) {
|
||||
tile.onTileAction(TileOperation::Error);
|
||||
return;
|
||||
}
|
||||
if (method == Resource::LoadingMethod::NetworkOnly) {
|
||||
tile.onTileAction(TileOperation::LoadFromNetwork);
|
||||
} else if (method == Resource::LoadingMethod::CacheOnly) {
|
||||
tile.onTileAction(TileOperation::LoadFromCache);
|
||||
}
|
||||
|
||||
if (res.notModified) {
|
||||
resource.priorExpires = res.expires;
|
||||
// Do not notify the tile; when we get this message, it already has the
|
||||
// current version of the data.
|
||||
@@ -182,6 +193,8 @@ void TileLoader<T>::loadFromNetwork() {
|
||||
return;
|
||||
}
|
||||
|
||||
tile.onTileAction(TileOperation::RequestedFromNetwork);
|
||||
|
||||
// Instead of using Resource::LoadingMethod::All, we're first doing a
|
||||
// CacheOnly, and then a NetworkOnly request.
|
||||
resource.loadingMethod = Resource::LoadingMethod::NetworkOnly;
|
||||
@@ -196,7 +209,7 @@ void TileLoader<T>::loadFromNetwork() {
|
||||
if (shared_->aborted) return;
|
||||
|
||||
request.reset();
|
||||
loadedData(res);
|
||||
loadedData(res, Resource::LoadingMethod::NetworkOnly);
|
||||
break;
|
||||
}
|
||||
} while (!shared_->aborted);
|
||||
|
||||
17
src/mbgl/tile/tile_loader_observer.hpp
Normal file
17
src/mbgl/tile/tile_loader_observer.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Tile;
|
||||
|
||||
class TileLoaderObserver {
|
||||
public:
|
||||
virtual ~TileLoaderObserver() = default;
|
||||
|
||||
virtual void onTileAction(TileOperation) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/tile/tile_operation.hpp>
|
||||
#include <exception>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -12,6 +14,7 @@ public:
|
||||
|
||||
virtual void onTileChanged(Tile&) {}
|
||||
virtual void onTileError(Tile&, std::exception_ptr) {}
|
||||
virtual void onTileAction(OverscaledTileID, std::string, TileOperation) {}
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -9,8 +9,9 @@ namespace mbgl {
|
||||
VectorTile::VectorTile(const OverscaledTileID& id_,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters,
|
||||
const Tileset& tileset)
|
||||
: GeometryTile(id_, std::move(sourceID_), parameters),
|
||||
const Tileset& tileset,
|
||||
TileObserver* observer_)
|
||||
: GeometryTile(id_, std::move(sourceID_), parameters, observer_),
|
||||
loader(*this, id_, parameters, tileset) {}
|
||||
|
||||
VectorTile::~VectorTile() {
|
||||
|
||||
@@ -10,7 +10,11 @@ class TileParameters;
|
||||
|
||||
class VectorTile : public GeometryTile {
|
||||
public:
|
||||
VectorTile(const OverscaledTileID&, std::string sourceID, const TileParameters&, const Tileset&);
|
||||
VectorTile(const OverscaledTileID&,
|
||||
std::string sourceID,
|
||||
const TileParameters&,
|
||||
const Tileset&,
|
||||
TileObserver* observer = nullptr);
|
||||
~VectorTile() override;
|
||||
|
||||
void setNecessity(TileNecessity) final;
|
||||
|
||||
@@ -252,12 +252,15 @@ BufferResource Context::createBuffer(const void* data, std::size_t size, std::ui
|
||||
return BufferResource(const_cast<Context&>(*this), data, size, usage, persistent);
|
||||
}
|
||||
|
||||
UniqueShaderProgram Context::createProgram(std::string name,
|
||||
UniqueShaderProgram Context::createProgram(shaders::BuiltIn shaderID,
|
||||
std::string name,
|
||||
const std::string_view vertex,
|
||||
const std::string_view fragment,
|
||||
const ProgramParameters& programParameters,
|
||||
const mbgl::unordered_map<std::string, std::string>& additionalDefines) {
|
||||
return std::make_unique<ShaderProgram>(name, vertex, fragment, programParameters, additionalDefines, backend);
|
||||
auto program = std::make_unique<ShaderProgram>(
|
||||
shaderID, name, vertex, fragment, programParameters, additionalDefines, backend, *observer);
|
||||
return program;
|
||||
}
|
||||
|
||||
gfx::UniqueDrawableBuilder Context::createDrawableBuilder(std::string name) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/test/stub_file_source.hpp>
|
||||
#include <mbgl/test/stub_map_observer.hpp>
|
||||
@@ -28,6 +30,7 @@
|
||||
#include <mbgl/style/sources/image_source.hpp>
|
||||
#include <mbgl/style/sources/vector_source.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_impl.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/client_options.hpp>
|
||||
#include <mbgl/util/color.hpp>
|
||||
@@ -1684,3 +1687,162 @@ TEST(Map, InvalidUTF8InTile) {
|
||||
|
||||
test.runLoop.run();
|
||||
}
|
||||
|
||||
TEST(Map, ObserveTileLifecycle) {
|
||||
util::RunLoop runLoop;
|
||||
|
||||
struct TileEntry {
|
||||
OverscaledTileID id;
|
||||
std::string sourceID;
|
||||
TileOperation op;
|
||||
};
|
||||
std::mutex tileMutex;
|
||||
std::vector<TileEntry> tileOps;
|
||||
|
||||
struct ShaderEntry {
|
||||
shaders::BuiltIn id;
|
||||
gfx::Backend::Type type;
|
||||
std::string defines;
|
||||
bool isPostCompile;
|
||||
};
|
||||
std::vector<ShaderEntry> shaderOps;
|
||||
|
||||
StubMapObserver observer;
|
||||
observer.onTileActionCallback = [&](TileOperation op, const OverscaledTileID& id, const std::string& sourceID) {
|
||||
if (sourceID != "mapbox") return;
|
||||
std::lock_guard<std::mutex> lock(tileMutex);
|
||||
tileOps.push_back(TileEntry{id, sourceID, op});
|
||||
};
|
||||
observer.onPreCompileShaderCallback =
|
||||
[&](shaders::BuiltIn id, gfx::Backend::Type type, const std::string& additionalDefines) {
|
||||
shaderOps.push_back(ShaderEntry{id, type, additionalDefines, false});
|
||||
};
|
||||
observer.onPostCompileShaderCallback =
|
||||
[&](shaders::BuiltIn id, gfx::Backend::Type type, const std::string& additionalDefines) {
|
||||
shaderOps.push_back(ShaderEntry{id, type, additionalDefines, true});
|
||||
};
|
||||
|
||||
HeadlessFrontend frontend{{512, 512}, 1};
|
||||
MapAdapter map(
|
||||
frontend,
|
||||
observer,
|
||||
std::make_shared<MainResourceLoader>(
|
||||
ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets"), ClientOptions()),
|
||||
MapOptions().withMapMode(MapMode::Static).withSize(frontend.getSize()));
|
||||
|
||||
map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));
|
||||
auto layer = std::make_unique<FillLayer>("landcover", "mapbox");
|
||||
layer->setSourceLayer("landcover");
|
||||
layer->setFillColor(Color{0.0, 1.0, 0.0, 1.0});
|
||||
map.getStyle().addLayer(std::move(layer));
|
||||
map.jumpTo(CameraOptions().withCenter(LatLng{37.8, -122.5}).withZoom(10.0));
|
||||
(void)frontend.render(map);
|
||||
|
||||
// We expect to see a valid shader lifecycle for every entry in this list.
|
||||
const std::vector<std::pair<shaders::BuiltIn, size_t>> expectedShaders = {
|
||||
{shaders::BuiltIn::FillShader, 16114602744458825542ULL},
|
||||
{shaders::BuiltIn::FillOutlineShader, 16114602744458825542ULL},
|
||||
};
|
||||
|
||||
for (const auto& [id, defineHash] : expectedShaders) {
|
||||
bool seenPreEvent = false;
|
||||
|
||||
for (const auto& op : shaderOps) {
|
||||
if (op.id != id || std::hash<std::string>()(op.defines) != defineHash) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!seenPreEvent) {
|
||||
EXPECT_EQ(op.isPostCompile, false);
|
||||
seenPreEvent = true;
|
||||
} else {
|
||||
EXPECT_EQ(op.isPostCompile, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We expect to see a valid lifecycle for every tile in this list.
|
||||
const std::vector<OverscaledTileID> expectedTiles = {
|
||||
{10, 0, 10, 163, 395}, {10, 0, 10, 163, 396}, {10, 0, 10, 164, 395}, {10, 0, 10, 164, 396},
|
||||
// Lower zooms can also be seen, but not always, so we
|
||||
// ignore them.
|
||||
};
|
||||
|
||||
for (const auto& tile : expectedTiles) {
|
||||
TileOperation stage = TileOperation::NullOp;
|
||||
|
||||
for (const auto& op : tileOps) {
|
||||
if (op.id != tile) continue;
|
||||
switch (op.op) {
|
||||
case TileOperation::RequestedFromCache: {
|
||||
EXPECT_EQ(stage, TileOperation::NullOp);
|
||||
stage = TileOperation::RequestedFromCache;
|
||||
break;
|
||||
}
|
||||
case TileOperation::RequestedFromNetwork: {
|
||||
EXPECT_THAT(
|
||||
stage,
|
||||
testing::AnyOf(
|
||||
TileOperation::StartParse, TileOperation::EndParse, TileOperation::RequestedFromCache));
|
||||
stage = TileOperation::RequestedFromNetwork;
|
||||
break;
|
||||
}
|
||||
case TileOperation::LoadFromNetwork: {
|
||||
EXPECT_THAT(stage, TileOperation::RequestedFromNetwork);
|
||||
stage = TileOperation::LoadFromNetwork;
|
||||
break;
|
||||
}
|
||||
case TileOperation::LoadFromCache: {
|
||||
EXPECT_EQ(stage, TileOperation::RequestedFromCache);
|
||||
stage = TileOperation::LoadFromCache;
|
||||
break;
|
||||
}
|
||||
case TileOperation::StartParse: {
|
||||
EXPECT_THAT(stage, testing::AnyOf(TileOperation::LoadFromNetwork, TileOperation::LoadFromCache));
|
||||
stage = TileOperation::StartParse;
|
||||
break;
|
||||
}
|
||||
case TileOperation::Cancelled: {
|
||||
EXPECT_THAT(stage,
|
||||
testing::AnyOf(TileOperation::RequestedFromCache,
|
||||
TileOperation::RequestedFromNetwork,
|
||||
TileOperation::LoadFromNetwork,
|
||||
TileOperation::LoadFromCache,
|
||||
TileOperation::StartParse));
|
||||
stage = TileOperation::Cancelled;
|
||||
break;
|
||||
}
|
||||
case TileOperation::EndParse: {
|
||||
// The following are both possible:
|
||||
// * RequestedFromCache -> LoadFromCache -> StartParse -> RequestedFromNetwork -> EndParse ->
|
||||
// LoadFromNetwork -> StartParse -> EndParse
|
||||
// The parsing stage is initiated by the cached version. The network request doesn't arrive
|
||||
// until after the cached version has completed parsing. A new parsing task is spawned, resulting
|
||||
// in a pair of Start and EndParse events.
|
||||
//
|
||||
// * RequestedFromCache -> LoadFromCache -> StartParse ->
|
||||
// RequestedFromNetwork -> LoadFromNetwork -> EndParse
|
||||
// The parsing stage is initiated by the cached version before being interrupted
|
||||
// by data from a new version downloaded over the network. This interruption doesn't cancel the
|
||||
// ongoing parsing task, so ::EndParse will end up being emitted only once by completion of the
|
||||
// newer tile's data.
|
||||
EXPECT_THAT(stage,
|
||||
testing::AnyOf(TileOperation::StartParse,
|
||||
TileOperation::LoadFromNetwork,
|
||||
TileOperation::RequestedFromNetwork));
|
||||
stage = TileOperation::EndParse;
|
||||
break;
|
||||
}
|
||||
case TileOperation::NullOp:
|
||||
[[fallthrough]];
|
||||
case TileOperation::Error: {
|
||||
ADD_FAILURE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_THAT(stage, testing::AnyOf(TileOperation::EndParse, TileOperation::Cancelled));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,50 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void onPreCompileShader(shaders::BuiltIn id, gfx::Backend::Type type, const std::string& additionalDefines) final {
|
||||
if (onPreCompileShaderCallback) {
|
||||
onPreCompileShaderCallback(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
void onPostCompileShader(shaders::BuiltIn id, gfx::Backend::Type type, const std::string& additionalDefines) final {
|
||||
if (onPostCompileShaderCallback) {
|
||||
onPostCompileShaderCallback(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
void onShaderCompileFailed(shaders::BuiltIn id,
|
||||
gfx::Backend::Type type,
|
||||
const std::string& additionalDefines) final {
|
||||
if (onShaderCompileFailedCallback) {
|
||||
onShaderCompileFailedCallback(id, type, additionalDefines);
|
||||
}
|
||||
}
|
||||
|
||||
void onGlyphsLoaded(const FontStack& stack, const GlyphRange& range) final {
|
||||
if (onGlyphsLoadedCallback) {
|
||||
onGlyphsLoadedCallback(stack, range);
|
||||
}
|
||||
}
|
||||
|
||||
void onGlyphsError(const FontStack& stack, const GlyphRange& range, std::exception_ptr ex) final {
|
||||
if (onGlyphsErrorCallback) {
|
||||
onGlyphsErrorCallback(stack, range, ex);
|
||||
}
|
||||
}
|
||||
|
||||
void onGlyphsRequested(const FontStack& stack, const GlyphRange& range) final {
|
||||
if (onGlyphsRequestedCallback) {
|
||||
onGlyphsRequestedCallback(stack, range);
|
||||
}
|
||||
}
|
||||
|
||||
void onTileAction(TileOperation op, const OverscaledTileID& id, const std::string& sourceID) final {
|
||||
if (onTileActionCallback) {
|
||||
onTileActionCallback(op, id, sourceID);
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void()> willStartLoadingMapCallback;
|
||||
std::function<void()> didFinishLoadingMapCallback;
|
||||
std::function<void()> didFailLoadingMapCallback;
|
||||
@@ -57,6 +101,13 @@ public:
|
||||
std::function<void(RenderFrameStatus)> didFinishRenderingFrameCallback;
|
||||
std::function<void()> didBecomeIdleCallback;
|
||||
std::function<void(gfx::ShaderRegistry&)> onRegisterShadersCallback;
|
||||
std::function<void(shaders::BuiltIn, gfx::Backend::Type, const std::string&)> onPreCompileShaderCallback;
|
||||
std::function<void(shaders::BuiltIn, gfx::Backend::Type, const std::string&)> onPostCompileShaderCallback;
|
||||
std::function<void(shaders::BuiltIn, gfx::Backend::Type, const std::string&)> onShaderCompileFailedCallback;
|
||||
std::function<void(const FontStack&, const GlyphRange&)> onGlyphsLoadedCallback;
|
||||
std::function<void(const FontStack&, const GlyphRange&, std::exception_ptr)> onGlyphsErrorCallback;
|
||||
std::function<void(const FontStack&, const GlyphRange&)> onGlyphsRequestedCallback;
|
||||
std::function<void(TileOperation, const OverscaledTileID&, const std::string&)> onTileActionCallback;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -765,8 +765,8 @@ class FakeTileSource;
|
||||
|
||||
class FakeTile : public Tile {
|
||||
public:
|
||||
FakeTile(FakeTileSource& source_, const OverscaledTileID& tileID)
|
||||
: Tile(Tile::Kind::Geometry, tileID),
|
||||
FakeTile(FakeTileSource& source_, const OverscaledTileID& tileID, TileObserver* observer_)
|
||||
: Tile(Tile::Kind::Geometry, tileID, "FakeTileSource", observer_),
|
||||
source(source_) {
|
||||
renderable = true;
|
||||
}
|
||||
@@ -802,7 +802,9 @@ public:
|
||||
util::tileSize_I,
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID) { return std::make_unique<FakeTile>(*this, tileID); });
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) {
|
||||
return std::make_unique<FakeTile>(*this, tileID, observer_);
|
||||
});
|
||||
}
|
||||
|
||||
const std::optional<Tileset>& getTileset() const override {
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
TEST(RasterDEMTile, setError) {
|
||||
RasterDEMTileTest test;
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.setError(std::make_exception_ptr(std::runtime_error("test")));
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -52,7 +52,7 @@ TEST(RasterDEMTile, setError) {
|
||||
|
||||
TEST(RasterDEMTile, onError) {
|
||||
RasterDEMTileTest test;
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0);
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -61,7 +61,7 @@ TEST(RasterDEMTile, onError) {
|
||||
|
||||
TEST(RasterDEMTile, onParsed) {
|
||||
RasterDEMTileTest test;
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onParsed(std::make_unique<HillshadeBucket>(PremultipliedImage({16, 16}), Tileset::DEMEncoding::Mapbox), 0);
|
||||
EXPECT_TRUE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -85,7 +85,7 @@ TEST(RasterDEMTile, onParsed) {
|
||||
|
||||
TEST(RasterDEMTile, onParsedEmpty) {
|
||||
RasterDEMTileTest test;
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterDEMTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onParsed(nullptr, 0);
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
TEST(RasterTile, setError) {
|
||||
RasterTileTest test;
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.setError(std::make_exception_ptr(std::runtime_error("test")));
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -52,7 +52,7 @@ TEST(RasterTile, setError) {
|
||||
|
||||
TEST(RasterTile, onError) {
|
||||
RasterTileTest test;
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0);
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -61,7 +61,7 @@ TEST(RasterTile, onError) {
|
||||
|
||||
TEST(RasterTile, onParsed) {
|
||||
RasterTileTest test;
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onParsed(std::make_unique<RasterBucket>(PremultipliedImage{}), 0);
|
||||
EXPECT_TRUE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
@@ -85,7 +85,7 @@ TEST(RasterTile, onParsed) {
|
||||
|
||||
TEST(RasterTile, onParsedEmpty) {
|
||||
RasterTileTest test;
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset);
|
||||
RasterTile tile(OverscaledTileID(0, 0, 0), "testSource", test.tileParameters, test.tileset);
|
||||
tile.onParsed(nullptr, 0);
|
||||
EXPECT_FALSE(tile.isRenderable());
|
||||
EXPECT_TRUE(tile.isLoaded());
|
||||
|
||||
Reference in New Issue
Block a user