summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Rex <julian.rex@mapbox.com>2018-03-22 14:58:54 -0400
committerJulian Rex <julian.rex@mapbox.com>2018-03-22 14:58:54 -0400
commit7556299851d8ba7067500369545af4d2aa5b4c77 (patch)
tree9fbfeb38cf5a7a36b1e5963c8b423679c54f69aa
parentbcdf23028e93a8216fc6b877486a04ac5a579c58 (diff)
downloadqtlocation-mapboxgl-7556299851d8ba7067500369545af4d2aa5b4c77.tar.gz
WIP - adds a new object that retains/releases the MGLOpenGLLayer through callbacks.
-rw-r--r--include/mbgl/style/layer.hpp2
-rw-r--r--include/mbgl/style/layers/custom_layer.hpp34
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.h18
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.mm194
-rw-r--r--platform/darwin/src/MGLStyle.mm12
-rw-r--r--platform/darwin/src/MGLStyleLayerRetentionManager.mm53
-rw-r--r--platform/darwin/src/MGLStyleLayerRetentionManager_Private.h16
-rw-r--r--platform/darwin/src/MGLStyle_Private.h5
-rw-r--r--platform/ios/Integration Tests/MBGLIntegrationTests.mm128
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj12
-rw-r--r--platform/ios/src/MGLMapView.mm13
-rw-r--r--platform/ios/src/MGLMapView_Private.h2
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.cpp12
-rw-r--r--src/mbgl/style/layers/custom_layer.cpp44
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp47
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp13
16 files changed, 415 insertions, 190 deletions
diff --git a/include/mbgl/style/layer.hpp b/include/mbgl/style/layer.hpp
index 12494f5387..259fb30b6d 100644
--- a/include/mbgl/style/layer.hpp
+++ b/include/mbgl/style/layer.hpp
@@ -127,7 +127,7 @@ public:
virtual std::unique_ptr<Layer> cloneRef(const std::string& id) const = 0;
LayerObserver* observer = nullptr;
- void setObserver(LayerObserver*);
+ virtual void setObserver(LayerObserver*);
// For use in SDK bindings, which store a reference to a platform-native peer
// object here, so that separately-obtained references to this object share
diff --git a/include/mbgl/style/layers/custom_layer.hpp b/include/mbgl/style/layers/custom_layer.hpp
index cd54c54ffb..05d12f47f4 100644
--- a/include/mbgl/style/layers/custom_layer.hpp
+++ b/include/mbgl/style/layers/custom_layer.hpp
@@ -54,16 +54,12 @@ using CustomLayerContextLostFunction = void (*)(void* context);
*/
using CustomLayerDeinitializeFunction = void (*)(void* context);
-/**
- * Called from `CustomLayer`'s destructor.
- * This provides a mechanism to handle any necessary clean-up using the provided `peer` object.
- * For example, if a platform-native peer object has a raw pointer to the CustomLayer it could be
- * set to NULL.
- *
- * This function is called from CustomLayer, unlike the above functions that are passed into the
- * private implementation.
- */
-using CustomLayerDeallocationFunction = void (*)(util::unique_any *peer);
+
+
+using CustomLayerContextOwnerChangedFunction = void (*)(void* context, void* owner);
+using CustomLayerContextAttachFunction = void (*)(void* context);
+using CustomLayerContextDetachFunction = void (*)(void* context);
+
class CustomLayer : public Layer {
public:
@@ -72,14 +68,22 @@ public:
CustomLayerRenderFunction,
CustomLayerContextLostFunction,
CustomLayerDeinitializeFunction,
- CustomLayerDeallocationFunction,
+
+ // Wrap these 4?
+ CustomLayerContextOwnerChangedFunction,
+ CustomLayerContextAttachFunction,
+ CustomLayerContextDetachFunction,
void* context);
CustomLayer(const std::string& id,
CustomLayerInitializeFunction,
CustomLayerRenderFunction,
CustomLayerDeinitializeFunction,
- CustomLayerDeallocationFunction,
+
+ // Wrap these 4?
+ CustomLayerContextOwnerChangedFunction,
+ CustomLayerContextAttachFunction,
+ CustomLayerContextDetachFunction,
void* context);
~CustomLayer() final;
@@ -96,12 +100,14 @@ public:
class Impl;
const Impl& impl() const;
+ const void* getContext() const;
+
+ void setObserver(LayerObserver* observer);
+
Mutable<Impl> mutableImpl() const;
std::unique_ptr<Layer> cloneRef(const std::string& id) const final;
CustomLayer(const CustomLayer&) = delete;
-
- CustomLayerDeallocationFunction deallocationFn = nullptr;
};
template <>
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h
index 0b494e8062..52173786f7 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.h
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.h
@@ -10,6 +10,21 @@ NS_ASSUME_NONNULL_BEGIN
@class MGLMapView;
@class MGLStyle;
+@class MGLOpenGLStyleLayer;
+
+MGL_EXPORT
+@interface MGLOpenGLStyleLayerRetainer: NSObject
+@property (nonatomic, weak, readonly) MGLOpenGLStyleLayer *layer;
+@property (nonatomic, assign, readonly) NSInteger layerRetainCount;
+@property (nonatomic, unsafe_unretained, nullable) void *owner;
+- (instancetype)initWithLayer:(MGLStyleLayer*)styleLayer;
+- (void)retainLayer;
+- (void)weakenLayer;
+@end
+
+
+
+
typedef struct MGLStyleLayerDrawingContext {
CGSize size;
CLLocationCoordinate2D centerCoordinate;
@@ -21,9 +36,10 @@ typedef struct MGLStyleLayerDrawingContext {
MGL_EXPORT
@interface MGLOpenGLStyleLayer : MGLStyleLayer
-
@property (nonatomic, weak, readonly) MGLStyle *style;
+- (BOOL)isBeingManaged;
+
- (instancetype)initWithIdentifier:(NSString *)identifier;
- (void)didMoveToMapView:(MGLMapView *)mapView;
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm
index a5f8b574a0..2b638e2067 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.mm
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm
@@ -7,6 +7,96 @@
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/math/wrap.hpp>
+@interface MGLOpenGLStyleLayerRetainer ()
+@property (nonatomic, weak, readwrite) MGLOpenGLStyleLayer *layer;
+@property (nonatomic, assign, readwrite) NSInteger layerRetainCount;
+@end
+
+@implementation MGLOpenGLStyleLayerRetainer
+
+- (void)dealloc {
+ NSLog(@"LayerRetainer dealloc start %p", self);
+
+ while (self.layerRetainCount) {
+ [self weakenLayer];
+ }
+
+ NSLog(@"LayerRetainer dealloc end %p", self);
+}
+
+- (instancetype)initWithLayer:(MGLOpenGLStyleLayer*)styleLayer {
+ if ((self = [super init])) {
+ _layer = styleLayer;
+ }
+ NSLog(@"LayerRetainer %p init with layer %p", self, styleLayer);
+ return self;
+}
+
+- (void)setOwner:(nullable void *)owner {
+ void* oldOwner = _owner;
+
+ _owner = owner;
+
+ if (oldOwner) {
+ NSLog(@"LayerRetainer %p released", self);
+ CFBridgingRelease((__bridge CFTypeRef)(self));
+ }
+
+ if (_owner) {
+ NSLog(@"LayerRetainer %p retained", self);
+ CFBridgingRetain(self);
+ }
+}
+
+- (void)retainLayer {
+
+ if (!self.layer)
+ return;
+
+ NSAssert(self.layerRetainCount >= 0, @"");
+
+ @autoreleasepool {
+ CFBridgingRetain(self.layer);
+ }
+ self.layerRetainCount++;
+
+ NSLog(@"LayerRetainer %p strengthen %ld", self, self.layerRetainCount);
+}
+
+
+- (void)weakenLayer {
+ if (!self.layer)
+ return;
+
+ NSAssert(self.layerRetainCount > 0, @"");
+
+ self.layerRetainCount--;
+
+ @autoreleasepool {
+ CFBridgingRelease((__bridge CFTypeRef)self.layer);
+ }
+
+ NSLog(@"LayerRetainer %p weaken %ld", self, self.layerRetainCount);
+}
+@end
+
+void MGLCustomLayerContextOwnerChangedFunction(void *context, void* owner) {
+ MGLOpenGLStyleLayerRetainer *contextRetainer = (__bridge MGLOpenGLStyleLayerRetainer*)context;
+ contextRetainer.owner = owner;
+}
+
+void MGLCustomLayerContextAttachFunction(void *context) {
+ MGLOpenGLStyleLayerRetainer *contextRetainer = (__bridge MGLOpenGLStyleLayerRetainer*)context;
+ [contextRetainer retainLayer];
+}
+
+void MGLCustomLayerContextDetachFunction(void *context) {
+ MGLOpenGLStyleLayerRetainer *contextRetainer = (__bridge MGLOpenGLStyleLayerRetainer*)context;
+ [contextRetainer weakenLayer];
+}
+
+
+
/**
Runs the preparation handler block contained in the given context, which is
implicitly an instance of `MGLOpenGLStyleLayer`.
@@ -17,7 +107,10 @@
void MGLPrepareCustomStyleLayer(void *context) {
// Note, that the layer is retained/released by MGLStyle, ensuring that the layer
// is alive during rendering
- MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer*)context;
+// MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer*)context;
+
+ MGLOpenGLStyleLayerRetainer *retainer = (__bridge MGLOpenGLStyleLayerRetainer*)context;
+ MGLOpenGLStyleLayer *layer = retainer.layer;
[layer didMoveToMapView:layer.style.mapView];
}
@@ -30,7 +123,15 @@ void MGLPrepareCustomStyleLayer(void *context) {
when creating an OpenGL style layer.
*/
void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRenderParameters &params) {
- MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
+// MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
+ MGLOpenGLStyleLayer *layer = ((__bridge MGLOpenGLStyleLayerRetainer*)context).layer;
+
+ if (!layer)
+ {
+ NSLog(@"no layer");
+ return;
+ }
+
MGLStyleLayerDrawingContext drawingContext = {
.size = CGSizeMake(params.width, params.height),
.centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude),
@@ -52,7 +153,9 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender
void MGLFinishCustomStyleLayer(void *context) {
// Note, that the layer is retained/released by MGLStyle, ensuring that the layer
// is alive during rendering
- MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer*)context;
+// MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer*)context;
+ MGLOpenGLStyleLayerRetainer *retainer = (__bridge MGLOpenGLStyleLayerRetainer*)context;
+ MGLOpenGLStyleLayer *layer = retainer.layer;
[layer willMoveFromMapView:layer.style.mapView];
}
@@ -62,29 +165,29 @@ void MGLFinishCustomStyleLayer(void *context) {
Function to be called when the core `CustomLayer` (not the Impl) gets deallocated.
It's possible taht at this stage the Obj-C style layer is being deallocated (but that case is detected).
*/
-void MGLDeallocateCustomStyleLayer(mbgl::util::unique_any *peer) {
-
- // We know that the peer object contains a LayerWrapper with a weak pointer to
- // our custom layer. We can use this to safely access the layer, and clear out the
- // raw pointer.
- //
- // If we don't do this rawLayer can become a dangling pointer (which was previously being
- // accessed via the description method)
-
- if (!(peer && peer->has_value()))
- return;
-
- LayerWrapper *wrapper = mbgl::util::any_cast<LayerWrapper>(peer);
-
- if (!wrapper)
- return;
-
- // If the MGLStyleLayer is currently being dealloc'd (and trigger the CustomLayer destructor, and
- // this function) then layer here will be nil (even though wrapper->layer may appear to be non-nil)
- MGLStyleLayer *layer = wrapper->layer;
-
- layer.rawLayer = NULL;
-}
+//void MGLDeallocateCustomStyleLayer(mbgl::util::unique_any *peer) {
+//
+// // We know that the peer object contains a LayerWrapper with a weak pointer to
+// // our custom layer. We can use this to safely access the layer, and clear out the
+// // raw pointer.
+// //
+// // If we don't do this rawLayer can become a dangling pointer (which was previously being
+// // accessed via the description method)
+//
+// if (!(peer && peer->has_value()))
+// return;
+//
+// LayerWrapper *wrapper = mbgl::util::any_cast<LayerWrapper>(peer);
+//
+// if (!wrapper)
+// return;
+//
+// // If the MGLStyleLayer is currently being dealloc'd (and trigger the CustomLayer destructor, and
+// // this function) then layer here will be nil (even though wrapper->layer may appear to be non-nil)
+// MGLStyleLayer *layer = wrapper->layer;
+//
+// layer.rawLayer = NULL;
+//}
/**
@@ -132,14 +235,45 @@ void MGLDeallocateCustomStyleLayer(mbgl::util::unique_any *peer) {
which it is added.
@return An initialized OpenGL style layer.
*/
+
+- (BOOL)isBeingManaged {
+ if (self.rawLayer == NULL) {
+ return NO;
+ }
+
+ auto customLayer = self.rawLayer->template as<mbgl::style::CustomLayer>();
+
+ if (!customLayer) {
+ return NO;
+ }
+
+ MGLOpenGLStyleLayerRetainer *retainer = (__bridge MGLOpenGLStyleLayerRetainer*)(customLayer->getContext());
+
+ return retainer.layerRetainCount > 0;
+}
+
+- (void)dealloc
+{
+ NSLog(@"MGLOpenGLStyleLayer dealloc %p\n", self);
+}
+
- (instancetype)initWithIdentifier:(NSString *)identifier {
+
+ NSLog(@"MGLOpenGLStyleLayer init %p\n", self);
+
+ MGLOpenGLStyleLayerRetainer *retainer = [[MGLOpenGLStyleLayerRetainer alloc] initWithLayer:self];
+
// Note, do not retain self here, otherwise MGLOpenGLStyleLayer will never be dealloc'd
auto layer = std::make_unique<mbgl::style::CustomLayer>(identifier.UTF8String,
MGLPrepareCustomStyleLayer,
MGLDrawCustomStyleLayer,
MGLFinishCustomStyleLayer,
- MGLDeallocateCustomStyleLayer,
- (__bridge void*)self);
+
+ MGLCustomLayerContextOwnerChangedFunction,
+ MGLCustomLayerContextAttachFunction,
+ MGLCustomLayerContextDetachFunction,
+
+ (__bridge void*)retainer);
return self = [super initWithPendingLayer:std::move(layer)];
}
@@ -163,7 +297,7 @@ void MGLDeallocateCustomStyleLayer(mbgl::util::unique_any *peer) {
// We need to ensure that this layer is retained, so that any references from layer impl's
// e.g. contexts) are still valid
- [style addToManagedLayers:self];
+// [style addToManagedLayers:self];
[super addToStyle:style belowLayer:otherLayer];
}
@@ -173,7 +307,7 @@ void MGLDeallocateCustomStyleLayer(mbgl::util::unique_any *peer) {
// We need to ensure that this layer is now released (however, if this layer is about to be
// used by the renderer then it will released once rendering is complete)
- [style removeFromManagedLayers:self];
+// [style removeFromManagedLayers:self];
self.style = nil;
}
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 3d503d77aa..f6fc5533be 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -84,7 +84,6 @@
@property (nonatomic, readonly) mbgl::style::Style *rawStyle;
@property (readonly, copy, nullable) NSURL *URL;
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, NS_DICTIONARY_OF(NSObject *, MGLTextLanguage *) *) *localizedLayersByIdentifier;
-@property (nonatomic, readwrite) NSMutableSet *managedLayers;
@end
@@ -173,7 +172,6 @@ static NSURL *MGLStyleURL_trafficNight;
- (instancetype)initWithRawStyle:(mbgl::style::Style *)rawStyle mapView:(MGLMapView *)mapView {
if (self = [super init]) {
- _managedLayers = [NSMutableSet set];
_mapView = mapView;
_rawStyle = rawStyle;
_localizedLayersByIdentifier = [NSMutableDictionary dictionary];
@@ -536,16 +534,6 @@ static NSURL *MGLStyleURL_trafficNight;
[self didChangeValueForKey:@"layers"];
}
-#pragma mark - Layer retain/release management
-
-- (void)addToManagedLayers:(MGLStyleLayer*)layer {
- [self.managedLayers addObject:layer];
-}
-
-- (void)removeFromManagedLayers:(MGLStyleLayer*)layer {
- [self.managedLayers removeObject:layer];
-}
-
#pragma mark Style classes
- (NS_ARRAY_OF(NSString *) *)styleClasses
diff --git a/platform/darwin/src/MGLStyleLayerRetentionManager.mm b/platform/darwin/src/MGLStyleLayerRetentionManager.mm
deleted file mode 100644
index 71ebd574ad..0000000000
--- a/platform/darwin/src/MGLStyleLayerRetentionManager.mm
+++ /dev/null
@@ -1,53 +0,0 @@
-#import "MGLStyle.h"
-#import "MGLStyleLayer.h"
-#import "MGLStyleLayerRetentionManager_Private.h"
-#include <mbgl/style/style.hpp>
-#include <mbgl/style/layers/custom_layer.hpp>
-
-static const NSUInteger MGLStyleLayerRetentionManagerCapacityHint = 100;
-
-@interface MGLStyleLayerRetentionManager ()
-@property (nonatomic) NSMapTable<MGLStyleLayer*, NSNumber*> *retentionTable;
-@end
-
-@implementation MGLStyleLayerRetentionManager
-
-- (instancetype)init {
- if ((self = [super init])) {
- _retentionTable = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality
- valueOptions:NSPointerFunctionsStrongMemory
- capacity:MGLStyleLayerRetentionManagerCapacityHint];
- }
- return self;
-}
-
-- (BOOL)isManagedLayer:(nullable MGLStyleLayer*)styleLayer {
- return [self.retentionTable objectForKey:styleLayer] != nil;
-}
-
-- (void)updateRetainedLayers:(nonnull NSSet<MGLStyleLayer*>*)sourceObjects {
-
- // Add/update the objects from the source set, with a default lifetime
- for (id layer in sourceObjects) {
- [self.retentionTable setObject:@(MGLStyleLayerRetentionManagerDefaultLifetime) forKey:layer];
- }
-}
-
-- (void)decrementLifetimes {
- // Consider double-buffering the two tables, so we don't keep allocing/deallocing tables.
- NSMapTable *retentionTable = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory|NSPointerFunctionsObjectPointerPersonality
- valueOptions:NSPointerFunctionsStrongMemory
- capacity:MGLStyleLayerRetentionManagerCapacityHint];
-
- for (MGLStyleLayer *layer in self.retentionTable) {
- NSInteger lifeTime = [[self.retentionTable objectForKey:layer] integerValue];
-
- if (lifeTime > 0) {
- [retentionTable setObject:@(lifeTime - 1) forKey:layer];
- }
- }
-
- self.retentionTable = retentionTable;
-}
-
-@end
diff --git a/platform/darwin/src/MGLStyleLayerRetentionManager_Private.h b/platform/darwin/src/MGLStyleLayerRetentionManager_Private.h
deleted file mode 100644
index 0063d342a5..0000000000
--- a/platform/darwin/src/MGLStyleLayerRetentionManager_Private.h
+++ /dev/null
@@ -1,16 +0,0 @@
-@class MGLStyle;
-
-static const NSInteger MGLStyleLayerRetentionManagerDefaultLifetime = 2;
-
-/**
- Object use to manage the retain/release of `MGLStyleLayer`s (currently only `MGLOpenGLStyleLayer`.
- Managed layers are given a "lifetime", and this is reset everytime `-updateRetainedLayers:` is called.
- The lifetime is decremented with each call to `-decrementLifetimes`, when it reaches 0 the layer
- is removed from the manager (potentially releasing it)
- */
-@interface MGLStyleLayerRetentionManager : NSObject
-- (BOOL)isManagedLayer:(nullable MGLStyleLayer*)styleLayer;
-- (void)updateRetainedLayers:(nonnull NSSet<MGLStyleLayer*>*)sourceObjects;
-- (void)decrementLifetimes;
-@end
-
diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h
index 00985403f5..55a84f432f 100644
--- a/platform/darwin/src/MGLStyle_Private.h
+++ b/platform/darwin/src/MGLStyle_Private.h
@@ -23,14 +23,13 @@ namespace mbgl {
@property (nonatomic, readonly, weak) MGLMapView *mapView;
@property (nonatomic, readonly) mbgl::style::Style *rawStyle;
-@property (nonatomic, readonly) NSMutableSet *managedLayers;
- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration;
-- (void)addToManagedLayers:(MGLStyleLayer*)layer;
-- (void)removeFromManagedLayers:(MGLStyleLayer*)layer;
+//- (void)addToManagedLayers:(MGLStyleLayer*)layer;
+//- (void)removeFromManagedLayers:(MGLStyleLayer*)layer;
@end
@interface MGLStyle (MGLStreetsAdditions)
diff --git a/platform/ios/Integration Tests/MBGLIntegrationTests.mm b/platform/ios/Integration Tests/MBGLIntegrationTests.mm
index 5e390bb8e6..2e01ce8ca2 100644
--- a/platform/ios/Integration Tests/MBGLIntegrationTests.mm
+++ b/platform/ios/Integration Tests/MBGLIntegrationTests.mm
@@ -2,10 +2,12 @@
#import <objc/message.h>
#import <Mapbox/Mapbox.h>
-#import "src/MGLStyleLayerRetentionManager_Private.h"
#import "src/MGLStyleLayer_Private.h"
#import "../ios/src/MGLMapView_Private.h"
+#define TRACE(message) NSLog(@"%@: %@", NSStringFromSelector(_cmd), message)
+
+
@interface MBGLIntegrationTests : XCTestCase <MGLMapViewDelegate>
@property (nonatomic) MGLMapView *mapView;
@@ -70,14 +72,17 @@
}
- (void)waitForManagedLayersToExpire {
- NSInteger count = MGLStyleLayerRetentionManagerDefaultLifetime;
- while (count--) {
- [self waitForMapViewToBeRendered];
- }
+ // NSInteger count = MGLStyleLayerRetentionManagerDefaultLifetime;
+ // while (count--) {
+ [self waitForMapViewToBeRendered];
+ // }
}
- (BOOL)isLayerBeingManaged:(MGLStyleLayer*)layer {
- return [self.mapView debugIsStyleLayerBeingManaged:layer];
+
+ MGLOpenGLStyleLayer *glLayer = [layer isKindOfClass:[MGLOpenGLStyleLayer class]] ? (MGLOpenGLStyleLayer*)layer : nil;
+
+ return [glLayer isBeingManaged];
}
- (MGLStyle *)style {
@@ -86,6 +91,108 @@
#pragma mark - Tests
+
+- (void)testLayerRetainer {
+
+ __weak MGLOpenGLStyleLayer *weaklayer1 = nil;
+ __weak MGLOpenGLStyleLayerRetainer *weakLayerRetainer = nil;
+ __unsafe_unretained MGLOpenGLStyleLayer *unsafelayer1 = nil;
+
+
+ // For test purposes, we look at the retain count, but for this to make any
+ // sense we also need to use unsafe unretained (to stop the call from retaining
+ // the very value we're intereested in. We also use autorelease pools. Do
+ // NOT use this in production code!!!
+ SEL retainCountSelector = NSSelectorFromString(@"retainCount");
+ NSInteger (*retainCount)(id, SEL) = (NSInteger (*)(id, SEL))objc_msgSend;
+
+ #define ASSERT_RETAIN_COUNT(object, expectedCount) { \
+ NSInteger count = retainCount(object, retainCountSelector); \
+ XCTAssert(count == (expectedCount), @"Expected retain count mismatch for %s. Expected %d, got %ld", #object, expectedCount, count); \
+ }
+
+
+
+ @autoreleasepool {
+
+ // Setup
+ TRACE(@"MGLOpenGLStyleLayer allocation:");
+ MGLOpenGLStyleLayer *layer1 = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"test"];
+ weaklayer1 = layer1;
+ unsafelayer1 = layer1;
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 1);
+
+ // First check to ensure a retainer gets released
+ {
+ TRACE(@"testing retainer dealloc");
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayerRetainer *layerRetainer = [[MGLOpenGLStyleLayerRetainer alloc] initWithLayer:layer1];
+ weakLayerRetainer = layerRetainer;
+ }
+
+ XCTAssertNil(weakLayerRetainer);
+ }
+
+ // Second check to check setting/unsetting owner
+ {
+ TRACE(@"testing retainer dealloc, after setting/clearing owner");
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayerRetainer *layerRetainer = [[MGLOpenGLStyleLayerRetainer alloc] initWithLayer:layer1];
+ weakLayerRetainer = layerRetainer;
+ layerRetainer.owner = (__bridge void*)self;
+ }
+ XCTAssertNotNil(weakLayerRetainer);
+ weakLayerRetainer.owner = NULL;
+ XCTAssertNil(weakLayerRetainer);
+ }
+
+ // Now test "retaining" (used by layer during render & adding to style)
+ @autoreleasepool {
+ TRACE(@"testing retaining");
+
+ // Create a retainer
+ MGLOpenGLStyleLayerRetainer *layerRetainer = [[MGLOpenGLStyleLayerRetainer alloc] initWithLayer:layer1];
+ weakLayerRetainer = layerRetainer;
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 1);
+
+ layerRetainer.owner = (__bridge void*)self;
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 1);
+
+ [layerRetainer retainLayer];
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 2);
+ }
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 2);
+
+ // Get rid of the layer, but we should still hold on to it via our
+ // retainer.
+ layer1 = nil;
+ }
+
+ XCTAssertNotNil(weaklayer1);
+ XCTAssertNotNil(weakLayerRetainer);
+
+ @autoreleasepool {
+ XCTAssertNotNil(weakLayerRetainer.layer);
+ }
+
+ ASSERT_RETAIN_COUNT(unsafelayer1, 1);
+
+ weakLayerRetainer.owner = NULL;
+
+ XCTAssertNil(weakLayerRetainer);
+ XCTAssertNil(weaklayer1);
+
+ #undef ASSERT_RETAIN_COUNT
+}
+
+
- (void)testStoringOpenGLLayerInCollections {
// If we change the meaning of equality for MGLStyleLayer we want to know about it - since we
// store layers in both a NSMutableSet and in a NSMapTable
@@ -307,7 +414,7 @@
- (void)testOpenGLLayerDoesNotLeakWhenRemovedFromStyle {
-// MGLOpenGLStyleLayer *layer;
+ // MGLOpenGLStyleLayer *layer;
__weak id weakLayer;
@autoreleasepool {
MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
@@ -328,9 +435,10 @@
XCTAssert([self isLayerBeingManaged:weakLayer]);
[self waitForMapViewToBeRendered];
- XCTAssertNotNil(weakLayer);
- XCTAssert([self isLayerBeingManaged:weakLayer]);
- [self waitForMapViewToBeRendered];
+
+ // XCTAssertNotNil(weakLayer);
+ // XCTAssert([self isLayerBeingManaged:weakLayer]);
+ // [self waitForMapViewToBeRendered];
XCTAssertNotNil(weakLayer);
XCTAssert(![self isLayerBeingManaged:weakLayer]);
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index ff1d447f78..bea9787192 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -311,10 +311,6 @@
CA67C7FB204CFC9000C1CBB4 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
CA67C7FD204CFCAA00C1CBB4 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA67C7FC204CFCAA00C1CBB4 /* UIKit.framework */; };
CA7F25182048841E00896957 /* polyline.geojson in Resources */ = {isa = PBXBuildFile; fileRef = DA1DC96D1CB6C6CE006E619F /* polyline.geojson */; };
- CA8F66E62049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CA8F66E42049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h */; };
- CA8F66E72049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CA8F66E42049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h */; };
- CA8F66E82049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA8F66E52049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm */; };
- CA8F66E92049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA8F66E52049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm */; };
CAAD2BD62041EF05003881EC /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; };
CAAD2BD72041EF05003881EC /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -875,8 +871,6 @@
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = "<group>"; };
CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = "<group>"; };
CA67C7FC204CFCAA00C1CBB4 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
- CA8F66E42049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayerRetentionManager_Private.h; sourceTree = "<group>"; };
- CA8F66E52049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleLayerRetentionManager.mm; sourceTree = "<group>"; };
DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = "<group>"; };
DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = "<group>"; };
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
@@ -1625,8 +1619,6 @@
DA8847EE1CBAFA5100AB86E3 /* MGLTypes.h */,
DA8848111CBAFA6200AB86E3 /* MGLTypes.m */,
35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */,
- CA8F66E42049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h */,
- CA8F66E52049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm */,
);
name = Foundation;
path = ../darwin/src;
@@ -1939,7 +1931,6 @@
9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */,
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */,
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
- CA8F66E62049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h in Headers */,
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
@@ -2138,7 +2129,6 @@
DABFB8651CBE99E500D62B32 /* MGLOverlay.h in Headers */,
35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */,
350098DD1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
- CA8F66E72049DD2900B5B9DC /* MGLStyleLayerRetentionManager_Private.h in Headers */,
DABFB8681CBE99E500D62B32 /* MGLPolyline.h in Headers */,
96E516DF200054FB00A02306 /* MGLShape_Private.h in Headers */,
DABFB86F1CBE9A0F00D62B32 /* MGLMapView.h in Headers */,
@@ -2710,7 +2700,6 @@
404C26E41D89B877000AA13D /* MGLTileSource.mm in Sources */,
07D947541F67489200E37934 /* MGLAbstractShapeSource.mm in Sources */,
355AE0011E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
- CA8F66E82049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm in Sources */,
DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */,
DACA86282019218600E9693A /* MGLRasterDEMSource.mm in Sources */,
DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */,
@@ -2804,7 +2793,6 @@
355AE0021E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */,
07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */,
- CA8F66E92049DD2900B5B9DC /* MGLStyleLayerRetentionManager.mm in Sources */,
DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
DACA86292019218600E9693A /* MGLRasterDEMSource.mm in Sources */,
35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 91121670a2..0db0488063 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -65,7 +65,6 @@
#import "MGLScaleBar.h"
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
-#import "MGLStyleLayerRetentionManager_Private.h"
#import "MGLMapboxEvents.h"
#import "MGLSDKUpdateChecker.h"
#import "MGLCompactCalloutView.h"
@@ -201,8 +200,6 @@ public:
@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints;
@property (nonatomic, readwrite) MGLStyle *style;
-@property (nonatomic) MGLStyleLayerRetentionManager* styleLayerRetentionManager;
-
@property (nonatomic) UITapGestureRecognizer *singleTapGestureRecognizer;
@property (nonatomic) UITapGestureRecognizer *doubleTap;
@@ -395,8 +392,6 @@ public:
[self createGLView];
}
- _styleLayerRetentionManager = [[MGLStyleLayerRetentionManager alloc] init];
-
// setup accessibility
//
// self.isAccessibilityElement = YES;
@@ -5561,8 +5556,6 @@ public:
return;
}
- [self.styleLayerRetentionManager updateRetainedLayers:self.style.managedLayers];
-
if ([self.delegate respondsToSelector:@selector(mapViewWillStartRenderingFrame:)])
{
[self.delegate mapViewWillStartRenderingFrame:self];
@@ -5581,7 +5574,6 @@ public:
}
[self updateAnnotationViews];
[self updateCalloutView];
- [self.styleLayerRetentionManager decrementLifetimes];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)])
{
@@ -6358,9 +6350,4 @@ private:
self.showsUserHeadingIndicator = showsHeading;
}
-- (BOOL)debugIsStyleLayerBeingManaged:(MGLStyleLayer*)layer {
- return [self.styleLayerRetentionManager isManagedLayer:layer];
-}
-
-
@end
diff --git a/platform/ios/src/MGLMapView_Private.h b/platform/ios/src/MGLMapView_Private.h
index 00900c9ef2..ca26af84a1 100644
--- a/platform/ios/src/MGLMapView_Private.h
+++ b/platform/ios/src/MGLMapView_Private.h
@@ -28,6 +28,4 @@ extern const CGSize MGLAnnotationAccessibilityElementMinimumSize;
/** Empties the in-memory tile cache. */
- (void)didReceiveMemoryWarning;
-/** Debug method, used in testing, to check if a layer's retain/release is being managed */
-- (BOOL)debugIsStyleLayerBeingManaged:(MGLStyleLayer*)layer;
@end
diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp
index adafd8583f..eab87b19c5 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.cpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.cpp
@@ -22,6 +22,8 @@ RenderCustomLayer::~RenderCustomLayer() {
} else if (!contextDestroyed && impl().deinitializeFn) {
impl().deinitializeFn(impl().context);
}
+
+ impl().detachFn(impl().context);
}
}
@@ -47,10 +49,20 @@ void RenderCustomLayer::render(PaintParameters& paintParameters, RenderSource*)
//If the context changed, deinitialize the previous one before initializing the new one.
if (context && !contextDestroyed && impl().deinitializeFn) {
impl().deinitializeFn(context);
+
+ if (impl().detachFn) {
+ impl().detachFn(context);
+ }
}
context = impl().context;
+
+ if (impl().attachFn) {
+ impl().attachFn(context);
+ }
+
assert(impl().initializeFn);
impl().initializeFn(impl().context);
+
initialized = true;
}
diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp
index 40013f3422..3198173412 100644
--- a/src/mbgl/style/layers/custom_layer.cpp
+++ b/src/mbgl/style/layers/custom_layer.cpp
@@ -5,37 +5,50 @@
namespace mbgl {
namespace style {
+CustomLayer::~CustomLayer()
+{
+ printf("~CustomLayer destructor %p\n", this);
+
+}
+
CustomLayer::CustomLayer(const std::string& layerID,
CustomLayerInitializeFunction init,
CustomLayerRenderFunction render,
CustomLayerContextLostFunction contextLost,
CustomLayerDeinitializeFunction deinit,
- CustomLayerDeallocationFunction deallocation,
+
+ CustomLayerContextOwnerChangedFunction ownerChanged,
+ CustomLayerContextAttachFunction attach,
+ CustomLayerContextDetachFunction detach,
void* context)
- : Layer(makeMutable<Impl>(layerID, init, render, contextLost, deinit, context)),
- deallocationFn(deallocation) {
+ : Layer(makeMutable<Impl>(layerID, init, render, contextLost, deinit, ownerChanged, attach, detach, context))
+{
+ printf("CustomLayer::CustomLayer %p\n", this);
+
}
CustomLayer::CustomLayer(const std::string& layerID,
CustomLayerInitializeFunction init,
CustomLayerRenderFunction render,
CustomLayerDeinitializeFunction deinit,
- CustomLayerDeallocationFunction deallocation,
+
+ CustomLayerContextOwnerChangedFunction ownerChanged,
+ CustomLayerContextAttachFunction attach,
+ CustomLayerContextDetachFunction detach,
void* context)
- : Layer(makeMutable<Impl>(layerID, init, render, nullptr, deinit, context)),
- deallocationFn(deallocation) {
+ : Layer(makeMutable<Impl>(layerID, init, render, nullptr, deinit, ownerChanged, attach, detach, context))
+{
+ printf("CustomLayer::CustomLayer %p\n", this);
}
-CustomLayer::~CustomLayer() {
- if (deallocationFn) {
- deallocationFn(&peer);
- }
-};
-
const CustomLayer::Impl& CustomLayer::impl() const {
return static_cast<const Impl&>(*baseImpl);
}
+const void* CustomLayer::getContext() const {
+ return impl().context;
+}
+
Mutable<CustomLayer::Impl> CustomLayer::mutableImpl() const {
return makeMutable<Impl>(impl());
}
@@ -45,6 +58,13 @@ std::unique_ptr<Layer> CustomLayer::cloneRef(const std::string&) const {
return nullptr;
}
+void CustomLayer::setObserver(LayerObserver* observer) {
+
+ Layer::setObserver(observer);
+
+ impl().didSetObserver(observer != NULL);
+}
+
// Visibility
void CustomLayer::setVisibility(VisibilityType value) {
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
index 1de268d2e2..5d1e1f6ab5 100644
--- a/src/mbgl/style/layers/custom_layer_impl.cpp
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -3,18 +3,43 @@
namespace mbgl {
namespace style {
+CustomLayer::Impl::~Impl() {
+ if (changeOwnerFn)
+ changeOwnerFn(context, NULL);
+}
+
CustomLayer::Impl::Impl(const std::string& id_,
- CustomLayerInitializeFunction initializeFn_,
- CustomLayerRenderFunction renderFn_,
- CustomLayerContextLostFunction contextLostFn_,
- CustomLayerDeinitializeFunction deinitializeFn_,
- void* context_)
- : Layer::Impl(LayerType::Custom, id_, std::string()) {
- initializeFn = initializeFn_;
- renderFn = renderFn_;
- deinitializeFn = deinitializeFn_;
- contextLostFn = contextLostFn_;
- context = context_;
+ CustomLayerInitializeFunction initializeFn_,
+ CustomLayerRenderFunction renderFn_,
+ CustomLayerContextLostFunction contextLostFn_,
+ CustomLayerDeinitializeFunction deinitializeFn_,
+
+ CustomLayerContextOwnerChangedFunction changeOwnerFn_,
+ CustomLayerContextAttachFunction attachFn_,
+ CustomLayerContextDetachFunction detachFn_,
+
+ void* context_):
+ Layer::Impl(LayerType::Custom, id_, std::string()),
+ initializeFn(initializeFn_),
+ renderFn(renderFn_),
+ contextLostFn(contextLostFn_),
+ deinitializeFn(deinitializeFn_),
+ changeOwnerFn(changeOwnerFn_),
+ attachFn(attachFn_),
+ detachFn(detachFn_),
+ context(context_) {
+
+ if (changeOwnerFn)
+ changeOwnerFn(context, this);
+}
+
+void CustomLayer::Impl::didSetObserver(bool didSet) const {
+ if (didSet) {
+ if (attachFn) attachFn(context);
+ }
+ else {
+ if (detachFn) detachFn(context);
+ }
}
bool CustomLayer::Impl::hasLayoutDifference(const Layer::Impl&) const {
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
index 62efbbe15b..6bc23f0759 100644
--- a/src/mbgl/style/layers/custom_layer_impl.hpp
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -11,11 +11,17 @@ namespace style {
class CustomLayer::Impl : public Layer::Impl {
public:
+ virtual ~Impl();
+
Impl(const std::string& id,
CustomLayerInitializeFunction,
CustomLayerRenderFunction,
CustomLayerContextLostFunction,
CustomLayerDeinitializeFunction,
+
+ CustomLayerContextOwnerChangedFunction,
+ CustomLayerContextAttachFunction,
+ CustomLayerContextDetachFunction,
void* context);
bool hasLayoutDifference(const Layer::Impl&) const override;
@@ -25,7 +31,14 @@ public:
CustomLayerRenderFunction renderFn = nullptr;
CustomLayerContextLostFunction contextLostFn = nullptr;
CustomLayerDeinitializeFunction deinitializeFn = nullptr;
+
+ CustomLayerContextOwnerChangedFunction changeOwnerFn = nullptr;
+ CustomLayerContextAttachFunction attachFn = nullptr;
+ CustomLayerContextDetachFunction detachFn = nullptr;
+
void* context = nullptr;
+
+ void didSetObserver(bool didSet) const;
};
} // namespace style