[core] Reduce custom layer API to lowest common denominator
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/vec.hpp>
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/style/types.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@@ -27,7 +28,6 @@ class Transform;
|
||||
class PointAnnotation;
|
||||
class ShapeAnnotation;
|
||||
struct CameraOptions;
|
||||
class StyleLayer;
|
||||
|
||||
namespace util {
|
||||
template <class T> class Thread;
|
||||
@@ -164,9 +164,12 @@ public:
|
||||
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&);
|
||||
LatLngBounds getBoundsForAnnotations(const AnnotationIDs&);
|
||||
|
||||
// Style API
|
||||
void addLayer(std::unique_ptr<StyleLayer>);
|
||||
void addLayer(std::unique_ptr<StyleLayer>, const std::string& before);
|
||||
void addCustomLayer(const std::string& id,
|
||||
CustomLayerInitializeFunction,
|
||||
CustomLayerRenderFunction,
|
||||
CustomLayerDeinitializeFunction,
|
||||
void* context,
|
||||
const char* before = nullptr);
|
||||
|
||||
// Memory
|
||||
void setSourceTileCacheSize(size_t);
|
||||
|
||||
@@ -189,6 +189,45 @@ MBGL_DEFINE_ENUM_CLASS(TextTransformTypeClass, TextTransformType, {
|
||||
{ TextTransformType::Lowercase, "lowercase" },
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize any GL state needed by the custom layer. This method is called once, from the
|
||||
* rendering thread, at a point when the GL context is active but before rendering for the
|
||||
* first time.
|
||||
*
|
||||
* Resources that are acquired in this method must be released in the UninitializeFunction.
|
||||
*/
|
||||
using CustomLayerInitializeFunction = void (*)(void* context);
|
||||
|
||||
/**
|
||||
* Parameters that define the current camera position for a CustomLayerRenderFunction.
|
||||
*/
|
||||
struct CustomLayerRenderParameters {
|
||||
double width;
|
||||
double height;
|
||||
double latitude;
|
||||
double longitude;
|
||||
double zoom;
|
||||
double bearing;
|
||||
double pitch;
|
||||
double altitude;
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the layer. This method is called once per frame. The implementation should not make
|
||||
* any assumptions about the GL state (other than that the correct context is active). It may
|
||||
* make changes to the state, and is not required to reset values such as the depth mask, stencil
|
||||
* mask, and corresponding test flags to their original values.
|
||||
*/
|
||||
using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&);
|
||||
|
||||
/**
|
||||
* Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
|
||||
* method is called once, from the rendering thread, at a point when the GL context is active.
|
||||
*
|
||||
* Note that it may be called even when the InitializeFunction has not been called.
|
||||
*/
|
||||
using CustomLayerDeinitializeFunction = void (*)(void* context);
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,53 @@
|
||||
#include <mbgl/layer/custom_layer.hpp>
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
CustomLayer::CustomLayer(const std::string& id_) {
|
||||
CustomLayer::CustomLayer(const std::string& id_,
|
||||
CustomLayerInitializeFunction initializeFn_,
|
||||
CustomLayerRenderFunction renderFn_,
|
||||
CustomLayerDeinitializeFunction deinitializeFn_,
|
||||
void * context_) {
|
||||
id = id_;
|
||||
initializeFn = initializeFn_;
|
||||
renderFn = renderFn_;
|
||||
deinitializeFn = deinitializeFn_;
|
||||
context = context_;
|
||||
}
|
||||
|
||||
CustomLayer::CustomLayer(const CustomLayer& other)
|
||||
: StyleLayer(other) {
|
||||
id = other.id;
|
||||
// Don't copy anything else.
|
||||
}
|
||||
|
||||
CustomLayer::~CustomLayer() {
|
||||
if (deinitializeFn) {
|
||||
deinitializeFn(context);
|
||||
}
|
||||
}
|
||||
|
||||
void CustomLayer::initialize() {
|
||||
assert(initializeFn);
|
||||
initializeFn(context);
|
||||
}
|
||||
|
||||
void CustomLayer::render(const TransformState& state) const {
|
||||
assert(renderFn);
|
||||
|
||||
CustomLayerRenderParameters parameters;
|
||||
|
||||
parameters.width = state.getWidth();
|
||||
parameters.height = state.getHeight();
|
||||
parameters.latitude = state.getLatLng().latitude;
|
||||
parameters.longitude = state.getLatLng().longitude;
|
||||
parameters.zoom = state.getZoom();
|
||||
parameters.bearing = -state.getAngle() / M_PI * 180;
|
||||
parameters.pitch = state.getPitch();
|
||||
parameters.altitude = state.getAltitude();
|
||||
|
||||
renderFn(context, parameters);
|
||||
}
|
||||
|
||||
bool CustomLayer::recalculate(const StyleCalculationParameters&) {
|
||||
@@ -12,6 +55,10 @@ bool CustomLayer::recalculate(const StyleCalculationParameters&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<StyleLayer> CustomLayer::clone() const {
|
||||
return std::make_unique<CustomLayer>(*this);
|
||||
}
|
||||
|
||||
std::unique_ptr<Bucket> CustomLayer::createBucket(StyleBucketParameters&) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -5,35 +5,24 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class StyleRenderParameters;
|
||||
class TransformState;
|
||||
|
||||
class CustomLayer : public StyleLayer {
|
||||
public:
|
||||
CustomLayer(const std::string& id);
|
||||
CustomLayer(const CustomLayer&) = default;
|
||||
CustomLayer(const std::string& id,
|
||||
CustomLayerInitializeFunction,
|
||||
CustomLayerRenderFunction,
|
||||
CustomLayerDeinitializeFunction,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Initialize any GL state needed by the custom layer. This method is called once, from the
|
||||
* rendering thread, at a point when the GL context is active but before rendering for the
|
||||
* first time.
|
||||
*
|
||||
* Resources that are acquired in this method must be released in the subclass's destructor.
|
||||
* However, note that in some situations the destructor may be called without initialize()
|
||||
* having been called. The destructor should be prepared for this case, e.g. by checking if
|
||||
* the resources were actually acquired before releasing them.
|
||||
*/
|
||||
virtual void initialize() = 0;
|
||||
CustomLayer(const CustomLayer&);
|
||||
~CustomLayer();
|
||||
|
||||
/**
|
||||
* Render the layer. This method is called once per frame. The implementation should not make
|
||||
* any assumptions about the GL state (other than that the correct context is active). It may
|
||||
* make changes to the state, and is not required to reset values such as the depth mask, stencil
|
||||
* mask, and corresponding test flags to their original values.
|
||||
*
|
||||
* The input StyleRenderParameters object has a `TransformState state` member that can be queried
|
||||
* for information about the current map view.
|
||||
*/
|
||||
virtual void render(const StyleRenderParameters&) const = 0;
|
||||
void initialize();
|
||||
void render(const TransformState&) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<StyleLayer> clone() const final;
|
||||
|
||||
void parseLayout(const JSVal&) final {}
|
||||
void parsePaints(const JSVal&) final {}
|
||||
@@ -42,6 +31,11 @@ public:
|
||||
bool recalculate(const StyleCalculationParameters&) final;
|
||||
|
||||
std::unique_ptr<Bucket> createBucket(StyleBucketParameters&) const final;
|
||||
|
||||
CustomLayerInitializeFunction initializeFn;
|
||||
CustomLayerRenderFunction renderFn;
|
||||
CustomLayerDeinitializeFunction deinitializeFn;
|
||||
void* context;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/annotation/point_annotation.hpp>
|
||||
#include <mbgl/annotation/shape_annotation.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/layer/custom_layer.hpp>
|
||||
|
||||
#include <mbgl/util/projection.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
@@ -425,12 +426,15 @@ LatLngBounds Map::getBoundsForAnnotations(const AnnotationIDs& annotations) {
|
||||
|
||||
#pragma mark - Style API
|
||||
|
||||
void Map::addLayer(std::unique_ptr<StyleLayer> layer) {
|
||||
context->invoke(&MapContext::addLayer, std::move(layer), mapbox::util::optional<std::string>());
|
||||
}
|
||||
|
||||
void Map::addLayer(std::unique_ptr<StyleLayer> layer, const std::string& before) {
|
||||
context->invoke(&MapContext::addLayer, std::move(layer), before);
|
||||
void Map::addCustomLayer(const std::string& id,
|
||||
CustomLayerInitializeFunction initialize,
|
||||
CustomLayerRenderFunction render,
|
||||
CustomLayerDeinitializeFunction deinitialize,
|
||||
void* context_,
|
||||
const char* before) {
|
||||
context->invoke(&MapContext::addLayer,
|
||||
std::make_unique<CustomLayer>(id, initialize, render, deinitialize, context_),
|
||||
before ? std::string(before) : mapbox::util::optional<std::string>());
|
||||
}
|
||||
|
||||
#pragma mark - Toggles
|
||||
|
||||
@@ -239,7 +239,7 @@ void Painter::renderPass(RenderPass pass_,
|
||||
renderBackground(*layer.as<BackgroundLayer>());
|
||||
} else if (layer.is<CustomLayer>()) {
|
||||
MBGL_DEBUG_GROUP(layer.id + " - custom");
|
||||
layer.as<CustomLayer>()->render(StyleRenderParameters(state));
|
||||
layer.as<CustomLayer>()->render(state);
|
||||
config.setDirty();
|
||||
} else {
|
||||
MBGL_DEBUG_GROUP(layer.id + " - " + std::string(item.tile->id));
|
||||
|
||||
@@ -13,11 +13,8 @@ using namespace mbgl;
|
||||
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
|
||||
static const GLchar * fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }";
|
||||
|
||||
class TestLayer : public CustomLayer {
|
||||
class TestLayer {
|
||||
public:
|
||||
TestLayer() : CustomLayer("custom") {}
|
||||
TestLayer(const TestLayer& copy) : CustomLayer(copy) {} // Don't copy GL resources
|
||||
|
||||
~TestLayer() {
|
||||
if (program) {
|
||||
MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer));
|
||||
@@ -29,7 +26,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void initialize() override {
|
||||
void initialize() {
|
||||
program = MBGL_CHECK_ERROR(glCreateProgram());
|
||||
vertexShader = MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
|
||||
fragmentShader = MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER));
|
||||
@@ -49,7 +46,7 @@ public:
|
||||
MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
void render(const StyleRenderParameters&) const override {
|
||||
void render() {
|
||||
MBGL_CHECK_ERROR(glUseProgram(program));
|
||||
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
|
||||
@@ -59,10 +56,6 @@ public:
|
||||
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
std::unique_ptr<StyleLayer> clone() const override {
|
||||
return std::make_unique<TestLayer>(*this);
|
||||
}
|
||||
|
||||
GLuint program = 0;
|
||||
GLuint vertexShader = 0;
|
||||
GLuint fragmentShader = 0;
|
||||
@@ -77,7 +70,17 @@ TEST(CustomLayer, Basic) {
|
||||
|
||||
Map map(view, fileSource, MapMode::Still);
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"), "");
|
||||
map.addLayer(std::make_unique<TestLayer>());
|
||||
map.addCustomLayer(
|
||||
"custom",
|
||||
[] (void* context) {
|
||||
reinterpret_cast<TestLayer*>(context)->initialize();
|
||||
},
|
||||
[] (void* context, const CustomLayerRenderParameters&) {
|
||||
reinterpret_cast<TestLayer*>(context)->render();
|
||||
},
|
||||
[] (void* context) {
|
||||
delete reinterpret_cast<TestLayer*>(context);
|
||||
}, new TestLayer());
|
||||
|
||||
test::checkImage("test/fixtures/custom_layer/basic", test::render(map));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user