Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Migrate MGLCustomStyleLayerAdditions to style layer API #7250

Merged
merged 5 commits into from
Dec 7, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[ios, macos] Rationalized MGLOpenGLStyleLayer API
MGLStyle now strongly references any MGLOpenGLStyleLayer object that’s added to it, in order to prevent pointers from going stale and make it easy for layer drawing code to get more information about the map view. Replaced the MGLOpenGLStyleLayer callback blocks with overridable instance methods. Added internal documentation for each method. Subclassed MGLOpenGLStyleLayer as LimeGreenStyleLayer inside macosapp.

Consolidated -addToMapView: into -addToMapView:belowLayer: to ensure that MGLRedundantLayerException gets raised even if the layer is being inserted rather than added to the bottom of the stack.
1ec5 committed Dec 7, 2016

Verified

This commit was signed with the committer’s verified signature. The key has expired.
tvdeyen Thomas von Deyen
commit 25cb13fb4f9129f6286588c2caddd02188b2fe72
7 changes: 1 addition & 6 deletions platform/darwin/src/MGLBackgroundStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -33,19 +33,14 @@ - (instancetype)initWithIdentifier:(NSString *)identifier

#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView
- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
[NSException raise:@"MGLRedundantLayerException"
format:@"This instance %@ was already added to %@. Adding the same layer instance " \
"to the style more than once is invalid.", self, mapView.style];
}

[self addToMapView:mapView belowLayer:nil];
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
7 changes: 1 addition & 6 deletions platform/darwin/src/MGLCircleStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -73,19 +73,14 @@ - (NSPredicate *)predicate
}
#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView
- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
[NSException raise:@"MGLRedundantLayerException"
format:@"This instance %@ was already added to %@. Adding the same layer instance " \
"to the style more than once is invalid.", self, mapView.style];
}

[self addToMapView:mapView belowLayer:nil];
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
7 changes: 1 addition & 6 deletions platform/darwin/src/MGLFillStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -68,19 +68,14 @@ - (NSPredicate *)predicate
}
#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView
- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
[NSException raise:@"MGLRedundantLayerException"
format:@"This instance %@ was already added to %@. Adding the same layer instance " \
"to the style more than once is invalid.", self, mapView.style];
}

[self addToMapView:mapView belowLayer:nil];
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
7 changes: 1 addition & 6 deletions platform/darwin/src/MGLLineStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -80,19 +80,14 @@ - (NSPredicate *)predicate
}
#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView
- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
[NSException raise:@"MGLRedundantLayerException"
format:@"This instance %@ was already added to %@. Adding the same layer instance " \
"to the style more than once is invalid.", self, mapView.style];
}

[self addToMapView:mapView belowLayer:nil];
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
23 changes: 10 additions & 13 deletions platform/darwin/src/MGLOpenGLStyleLayer.h
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

#import "MGLMapView.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"

NS_ASSUME_NONNULL_BEGIN

typedef struct MGLOpenGLStyleLayerDrawingState {
@class MGLMapView;

typedef struct MGLStyleLayerDrawingContext {
CGSize size;
CLLocationCoordinate2D centerCoordinate;
double zoomLevel;
CLLocationDirection direction;
CGFloat pitch;
CGFloat perspectiveSkew;
} MGLOpenGLStyleLayerDrawingState;

typedef void (^MGLOpenGLStyleLayerPreparationHandler)(void);

typedef void (^MGLOpenGLStyleLayerDrawingHandler)(MGLOpenGLStyleLayerDrawingState state);

typedef void (^MGLOpenGLStyleLayerCompletionHandler)(void);
} MGLStyleLayerDrawingContext;

@interface MGLOpenGLStyleLayer : MGLStyleLayer

- (instancetype)initWithIdentifier:(NSString *)identifier preparationHandler:(MGLOpenGLStyleLayerPreparationHandler)preparation drawingHandler:(MGLOpenGLStyleLayerDrawingHandler)drawing completionHandler:(MGLOpenGLStyleLayerCompletionHandler)completion NS_DESIGNATED_INITIALIZER;
@property (nonatomic, weak, readonly) MGLMapView *mapView;

@end
- (void)didMoveToMapView:(MGLMapView *)mapView;

- (void)willMoveFromMapView:(MGLMapView *)mapView;

@interface MGLMapView (MGLOpenGLStyleLayerAdditions)
- (void)drawInMapView:(MGLMapView *)mapView withContext:(MGLStyleLayerDrawingContext)context;

- (void)setStyleLayersNeedDisplay;
- (void)setNeedsDisplay;

@end

164 changes: 104 additions & 60 deletions platform/darwin/src/MGLOpenGLStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -1,75 +1,53 @@
#import "MGLOpenGLStyleLayer.h"

#import "MGLMapView_Private.h"
#import "MGLStyle_Private.h"

#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/math/wrap.hpp>

/**
An `MGLOpenGLStyleLayerHandlers` object owns an OpenGL style layer’s callback
blocks.
*/
class MGLOpenGLStyleLayerHandlers {
public:
MGLOpenGLStyleLayerHandlers(MGLOpenGLStyleLayerPreparationHandler p,
MGLOpenGLStyleLayerDrawingHandler d,
MGLOpenGLStyleLayerCompletionHandler f)
: prepare(p), draw(d), finish(f) {}

MGLOpenGLStyleLayerPreparationHandler prepare;
MGLOpenGLStyleLayerDrawingHandler draw;
MGLOpenGLStyleLayerCompletionHandler finish;
};

/**
Runs the preparation handler block contained in the given context, which is
implicitly an instance of `MGLOpenGLStyleLayerHandlers`.
implicitly an instance of `MGLOpenGLStyleLayer`.

@param context An `MGLOpenGLStyleLayerHandlers` instance that was provided as
context when creating an OpenGL style layer.
@param context An `MGLOpenGLStyleLayer` instance that was provided as context
when creating an OpenGL style layer.
*/
void MGLPrepareCustomStyleLayer(void *context) {
MGLOpenGLStyleLayerPreparationHandler prepare = reinterpret_cast<MGLOpenGLStyleLayerHandlers *>(context)->prepare;
if (prepare) {
prepare();
}
MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
[layer didMoveToMapView:layer.mapView];
}

/**
Runs the drawing handler block contained in the given context, which is
implicitly an instance of `MGLOpenGLStyleLayerHandlers`.
implicitly an instance of `MGLOpenGLStyleLayer`.

@param context An `MGLOpenGLStyleLayerHandlers` instance that was provided as
context when creating an OpenGL style layer.
@param context An `MGLOpenGLStyleLayer` instance that was provided as context
when creating an OpenGL style layer.
*/
void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRenderParameters &params) {
MGLOpenGLStyleLayerDrawingHandler draw = reinterpret_cast<MGLOpenGLStyleLayerHandlers *>(context)->draw;
if (draw) {
draw({
.size = CGSizeMake(params.width, params.height),
.centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude),
.zoomLevel = params.zoom,
.direction = mbgl::util::wrap(params.bearing, 0., 360.),
.pitch = params.pitch,
.perspectiveSkew = params.altitude,
});
}
MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
MGLStyleLayerDrawingContext drawingContext = {
.size = CGSizeMake(params.width, params.height),
.centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude),
.zoomLevel = params.zoom,
.direction = mbgl::util::wrap(params.bearing, 0., 360.),
.pitch = params.pitch,
.perspectiveSkew = params.altitude,
};
[layer drawInMapView:layer.mapView withContext:drawingContext];
}

/**
Runs the completion handler block contained in the given context, which is
implicitly an instance of `MGLOpenGLStyleLayerHandlers`.
implicitly an instance of `MGLOpenGLStyleLayer`.

@param context An `MGLOpenGLStyleLayerHandlers` instance that was provided as
context when creating an OpenGL style layer.
@param context An `MGLOpenGLStyleLayer` instance that was provided as context
when creating an OpenGL style layer.
*/
void MGLFinishCustomStyleLayer(void *context) {
MGLOpenGLStyleLayerHandlers *handlers = reinterpret_cast<MGLOpenGLStyleLayerHandlers *>(context);
MGLOpenGLStyleLayerCompletionHandler finish = handlers->finish;
if (finish) {
finish();
}
delete handlers;
MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
[layer willMoveFromMapView:layer.mapView];
}

/**
@@ -85,6 +63,14 @@ @interface MGLOpenGLStyleLayer ()

@property (nonatomic) mbgl::style::CustomLayer *rawLayer;

/**
The map view whose style currently contains the layer.

If the layer is not currently part of any map view’s style, this property is
set to `nil`.
*/
@property (nonatomic, weak, readwrite) MGLMapView *mapView;

@end

@implementation MGLOpenGLStyleLayer {
@@ -100,16 +86,15 @@ @implementation MGLOpenGLStyleLayer {

@param identifier A string that uniquely identifies the layer in the style to
which it is added.
@param preparation A block that sets up OpenGL state for the layer.
@param drawing A block that draws a single frame of the layer.
@param completion A block that cleans up OpenGL resources used by the layer.
@return An initialized OpenGL style layer.
*/
- (instancetype)initWithIdentifier:(NSString *)identifier preparationHandler:(MGLOpenGLStyleLayerPreparationHandler)preparation drawingHandler:(MGLOpenGLStyleLayerDrawingHandler)drawing completionHandler:(MGLOpenGLStyleLayerCompletionHandler)completion {
- (instancetype)initWithIdentifier:(NSString *)identifier {
if (self = [super initWithIdentifier:identifier]) {
MGLOpenGLStyleLayerHandlers *context = new MGLOpenGLStyleLayerHandlers(preparation, drawing, completion);
auto layer = std::make_unique<mbgl::style::CustomLayer>(identifier.UTF8String,
MGLPrepareCustomStyleLayer, MGLDrawCustomStyleLayer, MGLFinishCustomStyleLayer, context);
MGLPrepareCustomStyleLayer,
MGLDrawCustomStyleLayer,
MGLFinishCustomStyleLayer,
(__bridge void *)self);
_pendingLayer = std::move(layer);
_rawLayer = _pendingLayer.get();
}
@@ -118,11 +103,17 @@ - (instancetype)initWithIdentifier:(NSString *)identifier preparationHandler:(MG

#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView {
[self addToMapView:mapView belowLayer:nil];
- (void)setMapView:(MGLMapView *)mapView {
if (_mapView) {
[NSException raise:@"MGLLayerReuseException"
format:@"%@ cannot be added to more than one MGLStyle at a time.", self];
}
_mapView = mapView;
mapView.style.openGLLayers[self.identifier] = self;
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer {
self.mapView = mapView;
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{ otherLayer.identifier.UTF8String };
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
@@ -133,23 +124,76 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye

- (void)removeFromMapView:(MGLMapView *)mapView {
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
self.mapView = nil;
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::CustomLayer> &>(removedLayer));
_rawLayer = _pendingLayer.get();
}

@end
/**
Called immediately after a layer is added to a map view’s style.

This method is intended to be overridden in a subclass. You can use this method
to perform any setup work before the layer is used to draw a frame. For
example, you might use this method to compile an OpenGL shader. The default
implementation of this method does nothing.

Any resource acquired in this method must be released in
`-willMoveFromMapView:`.

@param mapView The map view to whose style the layer has been added.
*/
- (void)didMoveToMapView:(MGLMapView *)mapView {

}

/**
Called immediately before a layer is removed from a map view’s style.

This method is intended to be overridden in a subclass. You can use this method
to perform any teardown work once the layer has drawn its last frame and is
about to be removed from the style. The default implementation of this method
does nothing.

This method may be called even if `-didMoveToMapView:` has not been called.

@param mapView The map view from whose style the layer is about to be removed.
*/
- (void)willMoveFromMapView:(MGLMapView *)mapView {

}

@implementation MGLMapView (MGLOpenGLStyleLayerAdditions)
/**
Called each time the layer needs to draw a new frame in a map view.

This method is intended to be overridden in a subclass. You can use this method
to draw the layer’s content. The default implementation of this method does
nothing.

Your implementation should not make any assumptions about the OpenGL state,
other than that the current OpenGL context is active. It may make changes to
the OpenGL state. It is not required to reset values such as the depth mask,
stencil mask, or corresponding test flags to their original values.

Be sure to draw your fragments with a <var>z</var> value of 1 to take advantage
of the opaque fragment culling, in case the style contains any opaque layers
above this layer.

@param mapView The map view to which the layer draws.
@param context A context structure with information defining the frame to draw.
*/
- (void)drawInMapView:(MGLMapView *)mapView withContext:(MGLStyleLayerDrawingContext)context {

}

/**
Forces the map view associated with this style to redraw its style layers,
causing any OpenGL sources’ drawing handlers to be run.
Forces the map view associated with this style to redraw the receiving layer,
causing its drawing handler to be run.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

causing its drawing handler to be run

This is a holdover from the former block-based API. I reworded this sentence in 1781302.

*/
- (void)setStyleLayersNeedDisplay {
[self setNeedsGLDisplay];
- (void)setNeedsDisplay {
[self.mapView setNeedsGLDisplay];
}

@end
7 changes: 1 addition & 6 deletions platform/darwin/src/MGLRasterStyleLayer.mm
Original file line number Diff line number Diff line change
@@ -32,19 +32,14 @@ - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)so
}
#pragma mark - Adding to and removing from a map view

- (void)addToMapView:(MGLMapView *)mapView
- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (_pendingLayer == nullptr) {
[NSException raise:@"MGLRedundantLayerException"
format:@"This instance %@ was already added to %@. Adding the same layer instance " \
"to the style more than once is invalid.", self, mapView.style];
}

[self addToMapView:mapView belowLayer:nil];
}

- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
{
if (otherLayer) {
const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
Loading