[ios,macos] refactor MGLMapViewImpl
This commit is contained in:
@@ -191,7 +191,7 @@ private:
|
||||
causing the `-drawInMapView:withContext:` method to be called.
|
||||
*/
|
||||
- (void)setNeedsDisplay {
|
||||
[self.style.mapView setNeedsGLDisplay];
|
||||
[self.style.mapView setNeedsRerender];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#include <mbgl/renderer/renderer_frontend.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
#include <mbgl/gfx/renderer_backend.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
class MGLRenderFrontend : public mbgl::RendererFrontend
|
||||
{
|
||||
public:
|
||||
MGLRenderFrontend(std::unique_ptr<mbgl::Renderer> renderer_, MGLMapView* nativeView_, mbgl::gl::RendererBackend& mbglBackend_, bool async = false)
|
||||
MGLRenderFrontend(std::unique_ptr<mbgl::Renderer> renderer_, MGLMapView* nativeView_, mbgl::gfx::RendererBackend& mbglBackend_, bool async = false)
|
||||
: renderer(std::move(renderer_))
|
||||
, nativeView(nativeView_)
|
||||
, mbglBackend(mbglBackend_) {
|
||||
if (async) {
|
||||
asyncInvalidate.emplace([&]() {
|
||||
[nativeView setNeedsGLDisplay];
|
||||
[nativeView setNeedsRerender];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
if (asyncInvalidate) {
|
||||
asyncInvalidate->send();
|
||||
} else {
|
||||
[nativeView setNeedsGLDisplay];
|
||||
[nativeView setNeedsRerender];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
private:
|
||||
std::unique_ptr<mbgl::Renderer> renderer;
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
mbgl::gl::RendererBackend& mbglBackend;
|
||||
mbgl::gfx::RendererBackend& mbglBackend;
|
||||
std::shared_ptr<mbgl::UpdateParameters> updateParameters;
|
||||
mbgl::optional<mbgl::util::AsyncTask> asyncInvalidate;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <string>
|
||||
@@ -92,12 +93,8 @@ public:
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str =
|
||||
CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::ProcAddress>(symbol);
|
||||
return reinterpret_cast<gl::ProcAddress>(CFBundleGetFunctionPointerForName(
|
||||
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
@@ -26,12 +26,8 @@ public:
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str =
|
||||
CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::ProcAddress>(symbol);
|
||||
return reinterpret_cast<gl::ProcAddress>(CFBundleGetFunctionPointerForName(
|
||||
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
|
||||
@@ -269,9 +269,18 @@
|
||||
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
|
||||
40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */; };
|
||||
40FDA76B1CCAAA6800442548 /* MBXAnnotationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */; };
|
||||
550570C622958FB400228ECF /* MGLMapView+Impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 550570C422958FB300228ECF /* MGLMapView+Impl.mm */; };
|
||||
550570C722958FB400228ECF /* MGLMapView+Impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 550570C422958FB300228ECF /* MGLMapView+Impl.mm */; };
|
||||
550570C822958FB400228ECF /* MGLMapView+Impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 550570C522958FB400228ECF /* MGLMapView+Impl.h */; };
|
||||
550570C922958FB400228ECF /* MGLMapView+Impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 550570C522958FB400228ECF /* MGLMapView+Impl.h */; };
|
||||
550570D22296E96E00228ECF /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA27C24D1CBB3811000B0ECD /* GLKit.framework */; };
|
||||
556660CA1E1BF3A900E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C91E1BF3A900E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
556660D81E1D085500E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D71E1D085500E2C41B /* MGLVersionNumber.m */; };
|
||||
556660DB1E1D8E8D00E2C41B /* MGLFoundation.h in Headers */ = {isa = PBXBuildFile; fileRef = 556660C91E1BF3A900E2C41B /* MGLFoundation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
5580B45B229570A10091291B /* MGLMapView+OpenGL.h in Headers */ = {isa = PBXBuildFile; fileRef = 5580B459229570A00091291B /* MGLMapView+OpenGL.h */; };
|
||||
5580B45C229570A10091291B /* MGLMapView+OpenGL.h in Headers */ = {isa = PBXBuildFile; fileRef = 5580B459229570A00091291B /* MGLMapView+OpenGL.h */; };
|
||||
5580B45D229570A10091291B /* MGLMapView+OpenGL.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5580B45A229570A10091291B /* MGLMapView+OpenGL.mm */; };
|
||||
5580B45E229570A10091291B /* MGLMapView+OpenGL.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5580B45A229570A10091291B /* MGLMapView+OpenGL.mm */; };
|
||||
558DE7A01E5615E400C7916D /* MGLFoundation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 558DE79E1E5615E400C7916D /* MGLFoundation_Private.h */; };
|
||||
558DE7A11E5615E400C7916D /* MGLFoundation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 558DE79E1E5615E400C7916D /* MGLFoundation_Private.h */; };
|
||||
558DE7A21E5615E400C7916D /* MGLFoundation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 558DE79F1E5615E400C7916D /* MGLFoundation.mm */; };
|
||||
@@ -1009,9 +1018,13 @@
|
||||
40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = "<group>"; };
|
||||
40FDA7691CCAAA6800442548 /* MBXAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MBXAnnotationView.h; sourceTree = "<group>"; };
|
||||
40FDA76A1CCAAA6800442548 /* MBXAnnotationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MBXAnnotationView.m; sourceTree = "<group>"; };
|
||||
550570C422958FB300228ECF /* MGLMapView+Impl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "MGLMapView+Impl.mm"; sourceTree = "<group>"; };
|
||||
550570C522958FB400228ECF /* MGLMapView+Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+Impl.h"; sourceTree = "<group>"; };
|
||||
554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
556660C91E1BF3A900E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; wrapsLines = 0; };
|
||||
556660D71E1D085500E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
|
||||
5580B459229570A00091291B /* MGLMapView+OpenGL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+OpenGL.h"; sourceTree = "<group>"; };
|
||||
5580B45A229570A10091291B /* MGLMapView+OpenGL.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "MGLMapView+OpenGL.mm"; sourceTree = "<group>"; };
|
||||
558DE79E1E5615E400C7916D /* MGLFoundation_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFoundation_Private.h; sourceTree = "<group>"; };
|
||||
558DE79F1E5615E400C7916D /* MGLFoundation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFoundation.mm; sourceTree = "<group>"; };
|
||||
55CF752E213ED92000ED86C4 /* libicu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libicu.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -1435,6 +1448,7 @@
|
||||
DAAE5F8920F047240089D85B /* libmbgl-filesource.a in Frameworks */,
|
||||
DAAE5F8A20F0472E0089D85B /* libmbgl-loop-darwin.a in Frameworks */,
|
||||
55CF7531213ED92A00ED86C4 /* libicu.a in Frameworks */,
|
||||
550570D22296E96E00228ECF /* GLKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -2033,6 +2047,10 @@
|
||||
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */,
|
||||
DA8848361CBAFB8500AB86E3 /* MGLMapView.h */,
|
||||
DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */,
|
||||
550570C522958FB400228ECF /* MGLMapView+Impl.h */,
|
||||
550570C422958FB300228ECF /* MGLMapView+Impl.mm */,
|
||||
5580B459229570A00091291B /* MGLMapView+OpenGL.h */,
|
||||
5580B45A229570A10091291B /* MGLMapView+OpenGL.mm */,
|
||||
DA8848371CBAFB8500AB86E3 /* MGLMapView+IBAdditions.h */,
|
||||
DA737EE01D056A4E005BDA16 /* MGLMapViewDelegate.h */,
|
||||
);
|
||||
@@ -2346,6 +2364,7 @@
|
||||
353933FB1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */,
|
||||
6F018BB0220031BF003E7269 /* UIView+MGLAdditions.h in Headers */,
|
||||
1FCAE2A820B88B3800C577DD /* MGLLocationManager_Private.h in Headers */,
|
||||
5580B45B229570A10091291B /* MGLMapView+OpenGL.h in Headers */,
|
||||
DA8847EF1CBAFA5100AB86E3 /* MGLAccountManager.h in Headers */,
|
||||
DA35A2C91CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
|
||||
1F6A82A82138871900BA5B41 /* MGLLoggingConfiguration_Private.h in Headers */,
|
||||
@@ -2458,6 +2477,7 @@
|
||||
55E5666321C2A2080008B8B5 /* MMEMetrics.h in Headers */,
|
||||
55E5666421C2A2080008B8B5 /* MMEMetricsManager.h in Headers */,
|
||||
55E5666621C2A2080008B8B5 /* MMENSURLSessionWrapper.h in Headers */,
|
||||
550570C822958FB400228ECF /* MGLMapView+Impl.h in Headers */,
|
||||
55E5666721C2A2080008B8B5 /* MMETimerManager.h in Headers */,
|
||||
55E5666821C2A2080008B8B5 /* MMETypes.h in Headers */,
|
||||
55E5666921C2A2080008B8B5 /* MMEUIApplicationWrapper.h in Headers */,
|
||||
@@ -2530,6 +2550,8 @@
|
||||
96E516FA20005A3D00A02306 /* MGLUserLocationHeadingArrowLayer.h in Headers */,
|
||||
96E516E62000560B00A02306 /* MGLOfflineRegion_Private.h in Headers */,
|
||||
DAD1656D1CF41981001FF4B9 /* MGLFeature.h in Headers */,
|
||||
550570C922958FB400228ECF /* MGLMapView+Impl.h in Headers */,
|
||||
5580B45C229570A10091291B /* MGLMapView+OpenGL.h in Headers */,
|
||||
96E516E72000560B00A02306 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
DA17BE311CC4BDAA00402C41 /* MGLMapView_Private.h in Headers */,
|
||||
DABFB86C1CBE99E500D62B32 /* MGLTypes.h in Headers */,
|
||||
@@ -3131,10 +3153,12 @@
|
||||
DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */,
|
||||
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
|
||||
ACD0245A2187EABA00D8C8A7 /* MMEMetricsManager.m in Sources */,
|
||||
550570C622958FB400228ECF /* MGLMapView+Impl.mm in Sources */,
|
||||
40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
|
||||
DA8848541CBAFB9800AB86E3 /* MGLCompactCalloutView.m in Sources */,
|
||||
40834BEB1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */,
|
||||
DA8848251CBAFA6200AB86E3 /* MGLPointAnnotation.mm in Sources */,
|
||||
5580B45D229570A10091291B /* MGLMapView+OpenGL.mm in Sources */,
|
||||
40834BEA1FE05E1800C1BD0D /* MMEConstants.m in Sources */,
|
||||
AC46EB5F225E60510039C013 /* MMEPinningConfigurationProvider.m in Sources */,
|
||||
929EFFAB1F56DCD4003A77D5 /* MGLAnnotationView.mm in Sources */,
|
||||
@@ -3255,10 +3279,12 @@
|
||||
30E5781A1DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
|
||||
ACD0245B2187EABA00D8C8A7 /* MMEMetricsManager.m in Sources */,
|
||||
40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
|
||||
550570C722958FB400228ECF /* MGLMapView+Impl.mm in Sources */,
|
||||
DAA4E4291CBB730400178DFB /* NSBundle+MGLAdditions.m in Sources */,
|
||||
40834BFF1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */,
|
||||
40834BFE1FE05E1800C1BD0D /* MMEConstants.m in Sources */,
|
||||
35136D3D1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */,
|
||||
5580B45E229570A10091291B /* MGLMapView+OpenGL.mm in Sources */,
|
||||
DD9BE4FA1EB263F40079A3AF /* UIViewController+MGLAdditions.m in Sources */,
|
||||
AC46EB60225E60510039C013 /* MMEPinningConfigurationProvider.m in Sources */,
|
||||
350098DF1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
"platform/darwin/src/MGLFeature.mm",
|
||||
"platform/ios/src/UIImage+MGLAdditions.mm",
|
||||
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetricsManager.m",
|
||||
"platform/ios/src/MGLMapView+Impl.mm",
|
||||
"platform/ios/src/MGLAnnotationContainerView.m",
|
||||
"platform/ios/src/MGLCompactCalloutView.m",
|
||||
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEDependencyManager.m",
|
||||
"platform/darwin/src/MGLPointAnnotation.mm",
|
||||
"platform/ios/src/MGLMapView+OpenGL.mm",
|
||||
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEConstants.m",
|
||||
"platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEPinningConfigurationProvider.m",
|
||||
"platform/ios/src/MGLAnnotationView.mm",
|
||||
@@ -228,6 +230,7 @@
|
||||
"MGLStyleLayer_Private.h": "platform/darwin/src/MGLStyleLayer_Private.h",
|
||||
"UIView+MGLAdditions.h": "platform/ios/src/UIView+MGLAdditions.h",
|
||||
"MGLLocationManager_Private.h": "platform/darwin/src/MGLLocationManager_Private.h",
|
||||
"MGLMapView+OpenGL.h": "platform/ios/src/MGLMapView+OpenGL.h",
|
||||
"MGLLoggingConfiguration_Private.h": "platform/darwin/src/MGLLoggingConfiguration_Private.h",
|
||||
"NSComparisonPredicate+MGLAdditions.h": "platform/darwin/src/NSComparisonPredicate+MGLAdditions.h",
|
||||
"MGLMapAccessibilityElement.h": "platform/ios/src/MGLMapAccessibilityElement.h",
|
||||
@@ -295,6 +298,7 @@
|
||||
"MMEMetrics.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetrics.h",
|
||||
"MMEMetricsManager.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEMetricsManager.h",
|
||||
"MMENSURLSessionWrapper.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMENSURLSessionWrapper.h",
|
||||
"MGLMapView+Impl.h": "platform/ios/src/MGLMapView+Impl.h",
|
||||
"MMETimerManager.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.h",
|
||||
"MMETypes.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMETypes.h",
|
||||
"MMEUIApplicationWrapper.h": "platform/ios/vendor/mapbox-events-ios/MapboxMobileEvents/MMEUIApplicationWrapper.h",
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#import "MGLAnnotationView.h"
|
||||
#import "MGLAnnotationView_Private.h"
|
||||
#import "MGLMapView_Private.h"
|
||||
#import "MGLCalloutView.h"
|
||||
#import "MGLAnnotation.h"
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
#import "NSValue+MGLAdditions.h"
|
||||
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
|
||||
73
platform/ios/src/MGLMapView+Impl.h
Normal file
73
platform/ios/src/MGLMapView+Impl.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#import <mbgl/gfx/renderer_backend.hpp>
|
||||
#import <mbgl/map/map_observer.hpp>
|
||||
#import <mbgl/util/image.hpp>
|
||||
|
||||
#import <UIKit/UIView.h>
|
||||
#import <UIKit/UIImage.h>
|
||||
#import <QuartzCore/CALayer.h>
|
||||
|
||||
@class MGLMapView;
|
||||
|
||||
class MGLMapViewImpl : public mbgl::MapObserver {
|
||||
public:
|
||||
static std::unique_ptr<MGLMapViewImpl> Create(MGLMapView*);
|
||||
|
||||
MGLMapViewImpl(MGLMapView*);
|
||||
virtual ~MGLMapViewImpl() = default;
|
||||
|
||||
virtual mbgl::gfx::RendererBackend& getRendererBackend() = 0;
|
||||
|
||||
// Returns a handle to the OpenGL context object if this view is rendered with OpenGL.
|
||||
virtual EAGLContext* getEAGLContext() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Gets called when the opaqueness of the view changes.
|
||||
virtual void setOpaque(bool) = 0;
|
||||
|
||||
// Triggers an immediate render of the underlying view.
|
||||
virtual void display() = 0;
|
||||
|
||||
// We update the transaction mode when the user adds annotation views that need to be layered on
|
||||
// top of the view.
|
||||
virtual void setPresentsWithTransaction(bool) = 0;
|
||||
|
||||
// Called when initially creating the rendering view, and when resuming rendering after returning
|
||||
// from the background.
|
||||
virtual void createView() = 0;
|
||||
|
||||
// We expose the underlying UIView because we need it in order to add annotation views above it.
|
||||
virtual UIView* getView() = 0;
|
||||
|
||||
// Called when the application goes to the background and we've replaced the interactively
|
||||
// rendered map view with a static image.
|
||||
virtual void deleteView() = 0;
|
||||
|
||||
// called before the application goes to the background. The resulting image is used as a place
|
||||
// holder instead of the regular view. This allows us to drop the framebuffers associated with
|
||||
// the rendering context and reduce memory while in the background.
|
||||
virtual UIImage* snapshot() = 0;
|
||||
|
||||
// Called by the view delegate when it's time to render.
|
||||
void render();
|
||||
|
||||
// mbgl::MapObserver implementation
|
||||
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) override;
|
||||
void onCameraIsChanging() override;
|
||||
void onCameraDidChange(mbgl::MapObserver::CameraChangeMode) override;
|
||||
void onWillStartLoadingMap() override;
|
||||
void onDidFinishLoadingMap() override;
|
||||
void onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) override;
|
||||
void onWillStartRenderingFrame() override;
|
||||
void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode) override;
|
||||
void onWillStartRenderingMap() override;
|
||||
void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode) override;
|
||||
void onDidFinishLoadingStyle() override;
|
||||
void onSourceChanged(mbgl::style::Source& source) override;
|
||||
void onDidBecomeIdle() override;
|
||||
void onStyleImageMissing(const std::string& imageIdentifier) override;
|
||||
|
||||
protected:
|
||||
/// Cocoa map view that this adapter bridges to.
|
||||
__weak MGLMapView *mapView = nullptr;
|
||||
};
|
||||
102
platform/ios/src/MGLMapView+Impl.mm
Normal file
102
platform/ios/src/MGLMapView+Impl.mm
Normal file
@@ -0,0 +1,102 @@
|
||||
#import "MGLMapView+Impl.h"
|
||||
#import "MGLMapView+OpenGL.h"
|
||||
#import "MGLStyle_Private.h"
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
|
||||
std::unique_ptr<MGLMapViewImpl> MGLMapViewImpl::Create(MGLMapView* nativeView) {
|
||||
return std::make_unique<MGLMapViewOpenGLImpl>(nativeView);
|
||||
}
|
||||
|
||||
MGLMapViewImpl::MGLMapViewImpl(MGLMapView* nativeView_) : mapView(nativeView_) {
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::render() {
|
||||
[mapView renderSync];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[mapView cameraWillChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraIsChanging() {
|
||||
[mapView cameraIsChanging];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[mapView cameraDidChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartLoadingMap() {
|
||||
[mapView mapViewWillStartLoadingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishLoadingMap() {
|
||||
[mapView mapViewDidFinishLoadingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) {
|
||||
NSString *description;
|
||||
MGLErrorCode code;
|
||||
switch (mapError) {
|
||||
case mbgl::MapLoadError::StyleParseError:
|
||||
code = MGLErrorCodeParseStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::StyleLoadError:
|
||||
code = MGLErrorCodeLoadStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::NotFoundError:
|
||||
code = MGLErrorCodeNotFound;
|
||||
description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
|
||||
break;
|
||||
default:
|
||||
code = MGLErrorCodeUnknown;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
|
||||
}
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
NSLocalizedFailureReasonErrorKey: @(what.c_str()),
|
||||
};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
|
||||
[mapView mapViewDidFailLoadingMapWithError:error];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartRenderingFrame() {
|
||||
[mapView mapViewWillStartRenderingFrame];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartRenderingMap() {
|
||||
[mapView mapViewWillStartRenderingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[mapView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishLoadingStyle() {
|
||||
[mapView mapViewDidFinishLoadingStyle];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onSourceChanged(mbgl::style::Source& source) {
|
||||
NSString *identifier = @(source.getID().c_str());
|
||||
MGLSource * nativeSource = [mapView.style sourceWithIdentifier:identifier];
|
||||
[mapView sourceDidChange:nativeSource];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidBecomeIdle() {
|
||||
[mapView mapViewDidBecomeIdle];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onStyleImageMissing(const std::string& imageIdentifier) {
|
||||
NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()];
|
||||
[mapView didFailToLoadImage:imageName];
|
||||
}
|
||||
59
platform/ios/src/MGLMapView+OpenGL.h
Normal file
59
platform/ios/src/MGLMapView+OpenGL.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#import "MGLMapView+Impl.h"
|
||||
#import "MGLMapView_Private.h"
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
|
||||
@class MGLMapViewImplDelegate;
|
||||
|
||||
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
|
||||
class MGLMapViewOpenGLImpl final : public MGLMapViewImpl,
|
||||
public mbgl::gl::RendererBackend,
|
||||
public mbgl::gfx::Renderable {
|
||||
public:
|
||||
MGLMapViewOpenGLImpl(MGLMapView*);
|
||||
~MGLMapViewOpenGLImpl() override;
|
||||
|
||||
public:
|
||||
void restoreFramebufferBinding();
|
||||
|
||||
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
|
||||
private:
|
||||
void emergencyRecreateGL();
|
||||
#endif
|
||||
|
||||
// Implementation of mbgl::gfx::RendererBackend
|
||||
public:
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
// End implementation of mbgl::gfx::RendererBackend
|
||||
|
||||
// Implementation of mbgl::gl::RendererBackend
|
||||
public:
|
||||
void updateAssumedState() override;
|
||||
|
||||
private:
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override;
|
||||
// End implementation of mbgl::gl::Rendererbackend
|
||||
|
||||
// Implementation of MGLMapViewImpl
|
||||
public:
|
||||
mbgl::gfx::RendererBackend& getRendererBackend() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
EAGLContext* getEAGLContext() override;
|
||||
void setOpaque(bool) override;
|
||||
void display() override;
|
||||
void setPresentsWithTransaction(bool) override;
|
||||
void createView() override;
|
||||
UIView* getView() override;
|
||||
void deleteView() override;
|
||||
UIImage* snapshot() override;
|
||||
// End implementation of MGLMapViewImpl
|
||||
};
|
||||
253
platform/ios/src/MGLMapView+OpenGL.mm
Normal file
253
platform/ios/src/MGLMapView+OpenGL.mm
Normal file
@@ -0,0 +1,253 @@
|
||||
#import "MGLFoundation_Private.h"
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
#import "MGLMapView+OpenGL.h"
|
||||
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import <QuartzCore/CAEAGLLayer.h>
|
||||
|
||||
@interface MGLMapViewImplDelegate : NSObject <GLKViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation MGLMapViewImplDelegate {
|
||||
MGLMapViewOpenGLImpl* _impl;
|
||||
}
|
||||
|
||||
- (instancetype)initWithImpl:(MGLMapViewOpenGLImpl*)impl {
|
||||
if (self = [super init]) {
|
||||
_impl = impl;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)glkView:(nonnull GLKView*)view drawInRect:(CGRect)rect {
|
||||
_impl->render();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
class MGLMapViewOpenGLRenderableResource final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
MGLMapViewOpenGLRenderableResource(MGLMapViewOpenGLImpl& backend_)
|
||||
: backend(backend_),
|
||||
delegate([[MGLMapViewImplDelegate alloc] initWithImpl:&backend]),
|
||||
atLeastiOS_12_2_0([NSProcessInfo.processInfo
|
||||
isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){ 12, 2, 0 }]) {
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
backend.restoreFramebufferBinding();
|
||||
}
|
||||
|
||||
mbgl::Size framebufferSize() {
|
||||
assert(glView);
|
||||
return { static_cast<uint32_t>(glView.drawableWidth),
|
||||
static_cast<uint32_t>(glView.drawableHeight) };
|
||||
}
|
||||
|
||||
private:
|
||||
MGLMapViewOpenGLImpl& backend;
|
||||
|
||||
public:
|
||||
MGLMapViewImplDelegate* delegate = nil;
|
||||
GLKView *glView = nil;
|
||||
EAGLContext *context = nil;
|
||||
const bool atLeastiOS_12_2_0;
|
||||
|
||||
// We count how often the context was activated/deactivated so that we can truly deactivate it
|
||||
// after the activation count drops to 0.
|
||||
NSUInteger activationCount = 0;
|
||||
};
|
||||
|
||||
MGLMapViewOpenGLImpl::MGLMapViewOpenGLImpl(MGLMapView* nativeView_)
|
||||
: MGLMapViewImpl(nativeView_),
|
||||
mbgl::gl::RendererBackend(mbgl::gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable({ 0, 0 }, std::make_unique<MGLMapViewOpenGLRenderableResource>(*this)) {
|
||||
}
|
||||
|
||||
MGLMapViewOpenGLImpl::~MGLMapViewOpenGLImpl() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (resource.context && [[EAGLContext currentContext] isEqual:resource.context]) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::setOpaque(const bool opaque) {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
resource.glView.opaque = opaque;
|
||||
resource.glView.layer.opaque = opaque;
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::setPresentsWithTransaction(const bool value) {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = value;
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::display() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
|
||||
// glClear can be blocked for 1 second. This code is an "escape hatch",
|
||||
// an attempt to detect this situation and rebuild the GL views.
|
||||
if (mapView.enablePresentsWithTransaction && resource.atLeastiOS_12_2_0) {
|
||||
CFTimeInterval before = CACurrentMediaTime();
|
||||
[resource.glView display];
|
||||
CFTimeInterval after = CACurrentMediaTime();
|
||||
|
||||
if (after - before >= 1.0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
emergencyRecreateGL();
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
[resource.glView display];
|
||||
}
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::createView() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (resource.glView) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!resource.context) {
|
||||
resource.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
assert(resource.context);
|
||||
}
|
||||
|
||||
resource.glView = [[GLKView alloc] initWithFrame:mapView.bounds context:resource.context];
|
||||
resource.glView.delegate = resource.delegate;
|
||||
resource.glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
resource.glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)]
|
||||
? [[UIScreen mainScreen] nativeScale]
|
||||
: [[UIScreen mainScreen] scale];
|
||||
resource.glView.contentMode = UIViewContentModeCenter;
|
||||
resource.glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
|
||||
resource.glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
|
||||
resource.glView.opaque = mapView.opaque;
|
||||
resource.glView.layer.opaque = mapView.opaque;
|
||||
resource.glView.enableSetNeedsDisplay = NO;
|
||||
CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = NO;
|
||||
|
||||
[mapView insertSubview:resource.glView atIndex:0];
|
||||
size = resource.framebufferSize();
|
||||
}
|
||||
|
||||
UIView* MGLMapViewOpenGLImpl::getView() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
return resource.glView;
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::deleteView() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
[resource.glView deleteDrawable];
|
||||
}
|
||||
|
||||
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
|
||||
void MGLMapViewOpenGLImpl::emergencyRecreateGL() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
MGLLogError(@"Rendering took too long - creating GL views");
|
||||
|
||||
CAEAGLLayer* eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = NO;
|
||||
|
||||
[mapView pauseRendering:nil];
|
||||
|
||||
// Just performing a pauseRendering:/resumeRendering: pair isn't sufficient - in this case
|
||||
// we can still get errors when calling bindDrawable. Here we completely
|
||||
// recreate the GLKView
|
||||
|
||||
[mapView.userLocationAnnotationView removeFromSuperview];
|
||||
[resource.glView removeFromSuperview];
|
||||
|
||||
// Recreate the view
|
||||
resource.glView = nil;
|
||||
createView();
|
||||
|
||||
if (mapView.annotationContainerView) {
|
||||
[resource.glView insertSubview:mapView.annotationContainerView atIndex:0];
|
||||
}
|
||||
|
||||
[mapView updateUserLocationAnnotationView];
|
||||
|
||||
// Do not bind...yet
|
||||
|
||||
if (mapView.window) {
|
||||
[mapView resumeRendering:nil];
|
||||
eaglLayer = MGL_OBJC_DYNAMIC_CAST(resource.glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = mapView.enablePresentsWithTransaction;
|
||||
} else {
|
||||
MGLLogDebug(@"No window - skipping resumeRendering");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mbgl::gl::ProcAddress MGLMapViewOpenGLImpl::getExtensionFunctionPointer(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
return reinterpret_cast<mbgl::gl::ProcAddress>(CFBundleGetFunctionPointerForName(
|
||||
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::activate() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (resource.activationCount++) {
|
||||
return;
|
||||
}
|
||||
|
||||
[EAGLContext setCurrentContext:resource.context];
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::deactivate() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (--resource.activationCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
/// This function is called before we start rendering, when iOS invokes our rendering method.
|
||||
/// iOS already sets the correct framebuffer and viewport for us, so we need to update the
|
||||
/// context state with the anticipated values.
|
||||
void MGLMapViewOpenGLImpl::updateAssumedState() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
assumeFramebufferBinding(ImplicitFramebufferBinding);
|
||||
assumeViewport(0, 0, resource.framebufferSize());
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::restoreFramebufferBinding() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (!implicitFramebufferBound()) {
|
||||
// Something modified our state, and we need to bind the original drawable again.
|
||||
// Doing this also sets the viewport to the full framebuffer.
|
||||
// Note that in reality, iOS does not use the Framebuffer 0 (it's typically 1), and we
|
||||
// only use this is a placeholder value.
|
||||
[resource.glView bindDrawable];
|
||||
updateAssumedState();
|
||||
} else {
|
||||
// Our framebuffer is still bound, but the viewport might have changed.
|
||||
setViewport(0, 0, resource.framebufferSize());
|
||||
}
|
||||
}
|
||||
|
||||
UIImage* MGLMapViewOpenGLImpl::snapshot() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
return resource.glView.snapshot;
|
||||
}
|
||||
|
||||
EAGLContext* MGLMapViewOpenGLImpl::getEAGLContext() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
return resource.context;
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
#import "MGLMapView_Private.h"
|
||||
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
#import "MGLMapView+Impl.h"
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/map_options.hpp>
|
||||
@@ -17,8 +15,6 @@
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/style/layers/custom_layer.hpp>
|
||||
#include <mbgl/renderer/renderer.hpp>
|
||||
#import <mbgl/gl/renderer_backend.hpp>
|
||||
#import <mbgl/gl/renderable_resource.hpp>
|
||||
#include <mbgl/math/wrap.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
@@ -78,7 +74,6 @@
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
|
||||
class MBGLView;
|
||||
class MGLAnnotationContext;
|
||||
|
||||
const MGLMapViewDecelerationRate MGLMapViewDecelerationRateNormal = UIScrollViewDecelerationRateNormal;
|
||||
@@ -192,15 +187,12 @@ public:
|
||||
#pragma mark - Private -
|
||||
|
||||
@interface MGLMapView () <UIGestureRecognizerDelegate,
|
||||
GLKViewDelegate,
|
||||
MGLLocationManagerDelegate,
|
||||
MGLSMCalloutViewDelegate,
|
||||
MGLCalloutViewDelegate,
|
||||
MGLMultiPointDelegate,
|
||||
MGLAnnotationImageDelegate>
|
||||
|
||||
@property (nonatomic, readwrite) EAGLContext *context;
|
||||
@property (nonatomic) GLKView *glView;
|
||||
@property (nonatomic) UIImageView *glSnapshotView;
|
||||
|
||||
@property (nonatomic) NSMutableArray<NSLayoutConstraint *> *scaleBarConstraints;
|
||||
@@ -275,7 +267,7 @@ public:
|
||||
@implementation MGLMapView
|
||||
{
|
||||
mbgl::Map *_mbglMap;
|
||||
MBGLView *_mbglView;
|
||||
std::unique_ptr<MGLMapViewImpl> _mbglView;
|
||||
std::unique_ptr<MGLRenderFrontend> _rendererFrontend;
|
||||
|
||||
BOOL _opaque;
|
||||
@@ -328,9 +320,6 @@ public:
|
||||
CFTimeInterval _frameCounterStartTime;
|
||||
NSInteger _frameCount;
|
||||
CFTimeInterval _frameDurations;
|
||||
|
||||
BOOL _atLeastiOS_12_2_0;
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Setup & Teardown -
|
||||
@@ -441,13 +430,6 @@ public:
|
||||
- (void)commonInit
|
||||
{
|
||||
_opaque = NO;
|
||||
_atLeastiOS_12_2_0 = [NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){12,2,0}];
|
||||
|
||||
BOOL background = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
|
||||
if (!background)
|
||||
{
|
||||
[self createGLView];
|
||||
}
|
||||
|
||||
// setup accessibility
|
||||
//
|
||||
@@ -463,8 +445,13 @@ public:
|
||||
self.preferredFramesPerSecond = MGLMapViewPreferredFramesPerSecondDefault;
|
||||
|
||||
// setup mbgl view
|
||||
_mbglView = new MBGLView(self);
|
||||
|
||||
_mbglView = MGLMapViewImpl::Create(self);
|
||||
|
||||
BOOL background = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
|
||||
if (!background)
|
||||
{
|
||||
_mbglView->createView();
|
||||
}
|
||||
// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:@"cache.db"];
|
||||
@@ -473,9 +460,9 @@ public:
|
||||
// setup mbgl map
|
||||
MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration];
|
||||
|
||||
auto renderer = std::make_unique<mbgl::Renderer>(*_mbglView, config.scaleFactor, config.cacheDir, config.localFontFamilyName);
|
||||
auto renderer = std::make_unique<mbgl::Renderer>(_mbglView->getRendererBackend(), config.scaleFactor, config.cacheDir, config.localFontFamilyName);
|
||||
BOOL enableCrossSourceCollisions = !config.perSourceCollisions;
|
||||
_rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, *_mbglView);
|
||||
_rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, _mbglView->getRendererBackend());
|
||||
|
||||
mbgl::MapOptions mapOptions;
|
||||
mapOptions.withMapMode(mbgl::MapMode::Continuous)
|
||||
@@ -636,7 +623,7 @@ public:
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
|
||||
// As of 3.7.5, we intentionally do not listen for `UIApplicationWillResignActiveNotification` or call `sleepGL:` in response to it, as doing
|
||||
// As of 3.7.5, we intentionally do not listen for `UIApplicationWillResignActiveNotification` or call `pauseRendering:` in response to it, as doing
|
||||
// so causes a loop when asking for location permission. See: https://github.com/mapbox/mapbox-gl-native/issues/11225
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
||||
@@ -677,47 +664,6 @@ public:
|
||||
static_cast<uint32_t>(size.height) };
|
||||
}
|
||||
|
||||
- (mbgl::Size)framebufferSize
|
||||
{
|
||||
return { static_cast<uint32_t>(self.glView.drawableWidth),
|
||||
static_cast<uint32_t>(self.glView.drawableHeight) };
|
||||
}
|
||||
|
||||
+ (GLKView *)GLKViewWithFrame:(CGRect)frame context:(EAGLContext *)context opaque:(BOOL)opaque
|
||||
{
|
||||
GLKView *glView = [[GLKView alloc] initWithFrame:frame context:context];
|
||||
glView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
glView.enableSetNeedsDisplay = NO;
|
||||
glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
|
||||
glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
|
||||
glView.contentScaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
|
||||
glView.layer.opaque = opaque;
|
||||
glView.contentMode = UIViewContentModeCenter;
|
||||
|
||||
return glView;
|
||||
}
|
||||
|
||||
- (void)createGLView
|
||||
{
|
||||
if (_context) return;
|
||||
|
||||
// create context
|
||||
//
|
||||
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
MGLAssert(_context, @"Failed to create OpenGL ES context.");
|
||||
|
||||
// create GL view
|
||||
//
|
||||
_glView = [MGLMapView GLKViewWithFrame:self.bounds context:_context opaque:_opaque];
|
||||
_glView.delegate = self;
|
||||
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = NO;
|
||||
|
||||
[_glView bindDrawable];
|
||||
[self insertSubview:_glView atIndex:0];
|
||||
}
|
||||
|
||||
- (UIImage *)compassImage
|
||||
{
|
||||
UIImage *scaleImage = [MGLMapView resourceImageNamed:@"Compass"];
|
||||
@@ -763,8 +709,7 @@ public:
|
||||
delete _mbglMap;
|
||||
_mbglMap = nullptr;
|
||||
|
||||
delete _mbglView;
|
||||
_mbglView = nullptr;
|
||||
_mbglView.reset();
|
||||
|
||||
_rendererFrontend.reset();
|
||||
}
|
||||
@@ -789,11 +734,6 @@ public:
|
||||
|
||||
[self destroyCoreObjects];
|
||||
|
||||
if ([[EAGLContext currentContext] isEqual:_context])
|
||||
{
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
[self.compassViewConstraints removeAllObjects];
|
||||
self.compassViewConstraints = nil;
|
||||
|
||||
@@ -977,11 +917,13 @@ public:
|
||||
|
||||
- (void)setOpaque:(BOOL)opaque
|
||||
{
|
||||
_glView.layer.opaque = _opaque = opaque;
|
||||
_opaque = opaque;
|
||||
if (_mbglView) {
|
||||
_mbglView->setOpaque(opaque);
|
||||
}
|
||||
}
|
||||
|
||||
// This is the delegate of the GLKView object's display call.
|
||||
- (void)glkView:(__unused GLKView *)view drawInRect:(__unused CGRect)rect
|
||||
- (void)renderSync
|
||||
{
|
||||
if ( ! self.dormant && _rendererFrontend)
|
||||
{
|
||||
@@ -1138,27 +1080,7 @@ public:
|
||||
[self updateAnnotationViews];
|
||||
[self updateCalloutView];
|
||||
|
||||
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
|
||||
// glClear can be blocked for 1 second. This code is an "escape hatch",
|
||||
// an attempt to detect this situation and rebuild the GL views.
|
||||
if (self.enablePresentsWithTransaction && _atLeastiOS_12_2_0)
|
||||
{
|
||||
CFTimeInterval before = CACurrentMediaTime();
|
||||
[self.glView display];
|
||||
CFTimeInterval after = CACurrentMediaTime();
|
||||
|
||||
if (after-before >= 1.0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self emergencyRecreateGL];
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
[self.glView display];
|
||||
}
|
||||
_mbglView->display();
|
||||
}
|
||||
|
||||
if (self.experimental_enableFrameRateMeasurement)
|
||||
@@ -1183,7 +1105,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setNeedsGLDisplay
|
||||
- (void)setNeedsRerender
|
||||
{
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
@@ -1198,7 +1120,7 @@ public:
|
||||
{
|
||||
[self validateDisplayLink];
|
||||
self.dormant = YES;
|
||||
[self.glView deleteDrawable];
|
||||
_mbglView->deleteView();
|
||||
}
|
||||
|
||||
[self destroyCoreObjects];
|
||||
@@ -1284,53 +1206,10 @@ public:
|
||||
|
||||
// If the map is visible, change the layer property too
|
||||
if (self.window) {
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = _enablePresentsWithTransaction;
|
||||
_mbglView->setPresentsWithTransaction(_enablePresentsWithTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
|
||||
// See https://github.com/mapbox/mapbox-gl-native/issues/14232
|
||||
- (void)emergencyRecreateGL {
|
||||
MGLLogError(@"Rendering took too long - creating GL views");
|
||||
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = NO;
|
||||
|
||||
[self sleepGL:nil];
|
||||
|
||||
// Just performing a sleepGL/wakeGL pair isn't sufficient - in this case
|
||||
// we can still get errors when calling bindDrawable. Here we completely
|
||||
// recreate the GLKView
|
||||
|
||||
[self.userLocationAnnotationView removeFromSuperview];
|
||||
[_glView removeFromSuperview];
|
||||
|
||||
_glView = [MGLMapView GLKViewWithFrame:self.bounds context:_context opaque:_opaque];
|
||||
_glView.delegate = self;
|
||||
|
||||
[self insertSubview:_glView atIndex:0];
|
||||
|
||||
if (self.annotationContainerView)
|
||||
{
|
||||
[_glView insertSubview:self.annotationContainerView atIndex:0];
|
||||
}
|
||||
|
||||
[self updateUserLocationAnnotationView];
|
||||
|
||||
// Do not bind...yet
|
||||
|
||||
if (self.window) {
|
||||
[self wakeGL:nil];
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = self.enablePresentsWithTransaction;
|
||||
}
|
||||
else {
|
||||
MGLLogDebug(@"No window - skipping wakeGL");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)willMoveToWindow:(UIWindow *)newWindow {
|
||||
[super willMoveToWindow:newWindow];
|
||||
[self refreshSupportedInterfaceOrientationsWithWindow:newWindow];
|
||||
@@ -1341,9 +1220,8 @@ public:
|
||||
// In iOS 12.2, CAEAGLLayer.presentsWithTransaction can cause dramatic
|
||||
// slow down. The exact cause of this is unknown, but this work around
|
||||
// appears to lessen the effects.
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = NO;
|
||||
|
||||
_mbglView->setPresentsWithTransaction(NO);
|
||||
|
||||
// Moved from didMoveToWindow
|
||||
[self validateDisplayLink];
|
||||
}
|
||||
@@ -1356,9 +1234,8 @@ public:
|
||||
if (self.window)
|
||||
{
|
||||
// See above comment
|
||||
CAEAGLLayer *eaglLayer = MGL_OBJC_DYNAMIC_CAST(_glView.layer, CAEAGLLayer);
|
||||
eaglLayer.presentsWithTransaction = self.enablePresentsWithTransaction;
|
||||
|
||||
_mbglView->setPresentsWithTransaction(self.enablePresentsWithTransaction);
|
||||
|
||||
[self validateDisplayLink];
|
||||
}
|
||||
}
|
||||
@@ -1475,7 +1352,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
self.lastSnapshotImage = self.glView.snapshot;
|
||||
self.lastSnapshotImage = _mbglView->snapshot();
|
||||
|
||||
// For OpenGL this calls glFinish as recommended in
|
||||
// https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/ImplementingaMultitasking-awareOpenGLESApplication/ImplementingaMultitasking-awareOpenGLESApplication.html#//apple_ref/doc/uid/TP40008793-CH5-SW1
|
||||
@@ -1488,22 +1365,26 @@ public:
|
||||
|
||||
- (void)didEnterBackground:(NSNotification *)notification
|
||||
{
|
||||
[self sleepGL:notification];
|
||||
[self pauseRendering:notification];
|
||||
}
|
||||
|
||||
- (void)willEnterForeground:(NSNotification *)notification
|
||||
{
|
||||
// Do nothing, currently if wakeGL is called here it's a no-op.
|
||||
// Do nothing, currently if resumeRendering is called here it's a no-op.
|
||||
}
|
||||
|
||||
- (void)didBecomeActive:(NSNotification *)notification
|
||||
{
|
||||
[self wakeGL:notification];
|
||||
[self resumeRendering:notification];
|
||||
self.lastSnapshotImage = nil;
|
||||
}
|
||||
|
||||
#pragma mark - GL / display link wake/sleep
|
||||
|
||||
- (EAGLContext *)context {
|
||||
return _mbglView->getEAGLContext();
|
||||
}
|
||||
|
||||
- (BOOL)supportsBackgroundRendering
|
||||
{
|
||||
// If this view targets an external display, such as AirPlay or CarPlay, we
|
||||
@@ -1514,9 +1395,7 @@ public:
|
||||
return (self.window.screen != [UIScreen mainScreen]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)sleepGL:(__unused NSNotification *)notification
|
||||
- (void)pauseRendering:(__unused NSNotification *)notification
|
||||
{
|
||||
// If this view targets an external display, such as AirPlay or CarPlay, we
|
||||
// can safely continue to render OpenGL content without tripping
|
||||
@@ -1553,10 +1432,10 @@ public:
|
||||
|
||||
if ( ! self.glSnapshotView)
|
||||
{
|
||||
self.glSnapshotView = [[UIImageView alloc] initWithFrame:self.glView.frame];
|
||||
self.glSnapshotView.autoresizingMask = self.glView.autoresizingMask;
|
||||
self.glSnapshotView = [[UIImageView alloc] initWithFrame: _mbglView->getView().frame];
|
||||
self.glSnapshotView.autoresizingMask = _mbglView->getView().autoresizingMask;
|
||||
self.glSnapshotView.contentMode = UIViewContentModeCenter;
|
||||
[self insertSubview:self.glSnapshotView aboveSubview:self.glView];
|
||||
[self insertSubview:self.glSnapshotView aboveSubview:_mbglView->getView()];
|
||||
}
|
||||
|
||||
self.glSnapshotView.image = self.lastSnapshotImage;
|
||||
@@ -1570,11 +1449,11 @@ public:
|
||||
[self.glSnapshotView addSubview:snapshotTint];
|
||||
}
|
||||
|
||||
[self.glView deleteDrawable];
|
||||
_mbglView->deleteView();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)wakeGL:(__unused NSNotification *)notification
|
||||
- (void)resumeRendering:(__unused NSNotification *)notification
|
||||
{
|
||||
MGLLogInfo(@"Entering foreground.");
|
||||
MGLAssertIsMainThread();
|
||||
@@ -1583,14 +1462,12 @@ public:
|
||||
{
|
||||
self.dormant = NO;
|
||||
|
||||
[self createGLView];
|
||||
_mbglView->createView();
|
||||
|
||||
self.glSnapshotView.hidden = YES;
|
||||
|
||||
[self.glSnapshotView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
|
||||
[self.glView bindDrawable];
|
||||
|
||||
_displayLink.paused = NO;
|
||||
|
||||
[self validateLocationServices];
|
||||
@@ -4286,7 +4163,7 @@ public:
|
||||
newAnnotationContainerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
newAnnotationContainerView.contentMode = UIViewContentModeCenter;
|
||||
[newAnnotationContainerView addSubviews:annotationViews];
|
||||
[_glView insertSubview:newAnnotationContainerView atIndex:0];
|
||||
[_mbglView->getView() insertSubview:newAnnotationContainerView atIndex:0];
|
||||
self.annotationContainerView = newAnnotationContainerView;
|
||||
|
||||
[self updatePresentsWithTransaction];
|
||||
@@ -4992,7 +4869,7 @@ public:
|
||||
|
||||
// Remember, calloutView can be nil here.
|
||||
[calloutView presentCalloutFromRect:calloutPositioningRect
|
||||
inView:self.glView
|
||||
inView:_mbglView->getView()
|
||||
constrainedToRect:constrainedRect
|
||||
animated:animateSelection];
|
||||
|
||||
@@ -6269,7 +6146,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didFinishLoadingStyle {
|
||||
- (void)mapViewDidFinishLoadingStyle {
|
||||
if (!_mbglMap)
|
||||
{
|
||||
return;
|
||||
@@ -6282,6 +6159,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sourceDidChange:(MGLSource *)source {
|
||||
// no-op: we only show attribution after tapping the info button, so there's no
|
||||
// interactive update needed.
|
||||
}
|
||||
|
||||
- (void)didFailToLoadImage:(NSString *)imageName {
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:didFailToLoadImage:)]) {
|
||||
MGLImage *imageToLoad = [self.delegate mapView:self didFailToLoadImage:imageName];
|
||||
if (imageToLoad) {
|
||||
auto image = [imageToLoad mgl_styleImageWithIdentifier:imageName];
|
||||
_mbglMap->getStyle().addImage(std::move(image));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateUserLocationAnnotationView
|
||||
{
|
||||
[self updateUserLocationAnnotationViewAnimatedWithDuration:0];
|
||||
@@ -6497,7 +6390,7 @@ public:
|
||||
|
||||
if ( ! annotationView.superview)
|
||||
{
|
||||
[self.glView addSubview:annotationView];
|
||||
[_mbglView->getView() addSubview:annotationView];
|
||||
// Prevents the view from sliding in from the origin.
|
||||
annotationView.center = userPoint;
|
||||
}
|
||||
@@ -6765,190 +6658,6 @@ public:
|
||||
return _annotationViewReuseQueueByIdentifier[identifier];
|
||||
}
|
||||
|
||||
class MBGLView;
|
||||
|
||||
class MBGLMapViewRenderable final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
MBGLMapViewRenderable(MBGLView& backend_) : backend(backend_) {
|
||||
}
|
||||
|
||||
void bind() override;
|
||||
|
||||
private:
|
||||
MBGLView& backend;
|
||||
};
|
||||
|
||||
class MBGLView : public mbgl::gl::RendererBackend,
|
||||
public mbgl::gfx::Renderable,
|
||||
public mbgl::MapObserver {
|
||||
public:
|
||||
MBGLView(MGLMapView* nativeView_)
|
||||
: mbgl::gl::RendererBackend(mbgl::gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable(nativeView_.framebufferSize,
|
||||
std::make_unique<MBGLMapViewRenderable>(*this)),
|
||||
nativeView(nativeView_) {
|
||||
}
|
||||
|
||||
/// This function is called before we start rendering, when iOS invokes our rendering method.
|
||||
/// iOS already sets the correct framebuffer and viewport for us, so we need to update the
|
||||
/// context state with the anticipated values.
|
||||
void updateAssumedState() override {
|
||||
assumeFramebufferBinding(ImplicitFramebufferBinding);
|
||||
assumeViewport(0, 0, nativeView.framebufferSize);
|
||||
}
|
||||
|
||||
void restoreFramebufferBinding() {
|
||||
if (!implicitFramebufferBound()) {
|
||||
// Something modified our state, and we need to bind the original drawable again.
|
||||
// Doing this also sets the viewport to the full framebuffer.
|
||||
// Note that in reality, iOS does not use the Framebuffer 0 (it's typically 1), and we
|
||||
// only use this is a placeholder value.
|
||||
[nativeView.glView bindDrawable];
|
||||
updateAssumedState();
|
||||
} else {
|
||||
// Our framebuffer is still bound, but the viewport might have changed.
|
||||
setViewport(0, 0, nativeView.framebufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[nativeView cameraWillChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void onCameraIsChanging() override {
|
||||
[nativeView cameraIsChanging];
|
||||
}
|
||||
|
||||
void onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) override {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[nativeView cameraDidChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void onWillStartLoadingMap() override {
|
||||
[nativeView mapViewWillStartLoadingMap];
|
||||
}
|
||||
|
||||
void onDidFinishLoadingMap() override {
|
||||
[nativeView mapViewDidFinishLoadingMap];
|
||||
}
|
||||
|
||||
void onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) override {
|
||||
NSString *description;
|
||||
MGLErrorCode code;
|
||||
switch (mapError) {
|
||||
case mbgl::MapLoadError::StyleParseError:
|
||||
code = MGLErrorCodeParseStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::StyleLoadError:
|
||||
code = MGLErrorCodeLoadStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::NotFoundError:
|
||||
code = MGLErrorCodeNotFound;
|
||||
description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
|
||||
break;
|
||||
default:
|
||||
code = MGLErrorCodeUnknown;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
|
||||
}
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
NSLocalizedFailureReasonErrorKey: @(what.c_str()),
|
||||
};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
|
||||
[nativeView mapViewDidFailLoadingMapWithError:error];
|
||||
}
|
||||
|
||||
void onWillStartRenderingFrame() override {
|
||||
[nativeView mapViewWillStartRenderingFrame];
|
||||
}
|
||||
|
||||
void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) override {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[nativeView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void onWillStartRenderingMap() override {
|
||||
[nativeView mapViewWillStartRenderingMap];
|
||||
}
|
||||
|
||||
void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) override {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[nativeView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void onDidBecomeIdle() override {
|
||||
[nativeView mapViewDidBecomeIdle];
|
||||
}
|
||||
|
||||
void onDidFinishLoadingStyle() override {
|
||||
[nativeView didFinishLoadingStyle];
|
||||
}
|
||||
|
||||
void onStyleImageMissing(const std::string& imageIdentifier) override {
|
||||
NSString *imageName = [NSString stringWithUTF8String:imageIdentifier.c_str()];
|
||||
|
||||
if ([nativeView.delegate respondsToSelector:@selector(mapView:didFailToLoadImage:)]) {
|
||||
UIImage *imageToLoad = [nativeView.delegate mapView:nativeView didFailToLoadImage:imageName];
|
||||
|
||||
if (imageToLoad) {
|
||||
auto image = [imageToLoad mgl_styleImageWithIdentifier:imageName];
|
||||
nativeView.mbglMap.getStyle().addImage(std::move(image));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str =
|
||||
CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void activate() override
|
||||
{
|
||||
if (activationCount++)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[EAGLContext setCurrentContext:nativeView.context];
|
||||
}
|
||||
|
||||
void deactivate() override
|
||||
{
|
||||
if (--activationCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
private:
|
||||
__weak MGLMapView* nativeView = nullptr;
|
||||
|
||||
NSUInteger activationCount = 0;
|
||||
};
|
||||
|
||||
void MBGLMapViewRenderable::bind() {
|
||||
backend.restoreFramebufferBinding();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - IBAdditions methods
|
||||
|
||||
@@ -1,28 +1,55 @@
|
||||
#import <Mapbox/Mapbox.h>
|
||||
#import "MGLMapView.h"
|
||||
#import "MGLUserLocationAnnotationView.h"
|
||||
#import "MGLAnnotationContainerView.h"
|
||||
|
||||
#include <mbgl/util/size.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
class Map;
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
@class MGLSource;
|
||||
|
||||
/// Minimum size of an annotation’s accessibility element.
|
||||
FOUNDATION_EXTERN const CGSize MGLAnnotationAccessibilityElementMinimumSize;
|
||||
|
||||
/// Indicates that a method (that uses `mbgl::Map`) was called after app termination.
|
||||
FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const MGLUnderlyingMapUnavailableException;
|
||||
FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const _Nonnull MGLUnderlyingMapUnavailableException;
|
||||
|
||||
@interface MGLMapView (Private)
|
||||
|
||||
/// The map view’s OpenGL rendering context.
|
||||
@property (nonatomic, readonly) EAGLContext *context;
|
||||
@property (nonatomic, readonly, nullable) EAGLContext *context;
|
||||
|
||||
/// Currently shown popover representing the selected annotation.
|
||||
@property (nonatomic) UIView<MGLCalloutView> *calloutViewForSelectedAnnotation;
|
||||
@property (nonatomic, nonnull) UIView<MGLCalloutView> *calloutViewForSelectedAnnotation;
|
||||
|
||||
/// Map observers
|
||||
- (void)cameraWillChangeAnimated:(BOOL)animated;
|
||||
- (void)cameraIsChanging;
|
||||
- (void)cameraDidChangeAnimated:(BOOL)animated;
|
||||
- (void)mapViewWillStartLoadingMap;
|
||||
- (void)mapViewDidFinishLoadingMap;
|
||||
- (void)mapViewDidFailLoadingMapWithError:(nonnull NSError *)error;
|
||||
- (void)mapViewWillStartRenderingFrame;
|
||||
- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered;
|
||||
- (void)mapViewWillStartRenderingMap;
|
||||
- (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered;
|
||||
- (void)mapViewDidBecomeIdle;
|
||||
- (void)mapViewDidFinishLoadingStyle;
|
||||
- (void)sourceDidChange:(nonnull MGLSource *)source;
|
||||
- (void)didFailToLoadImage:(nonnull NSString *)imageName;
|
||||
|
||||
/** Triggers another render pass even when it is not necessary. */
|
||||
- (void)setNeedsGLDisplay;
|
||||
- (void)setNeedsRerender;
|
||||
|
||||
- (mbgl::Renderer *)renderer;
|
||||
/// Synchronously render a frame of the map.
|
||||
- (void)renderSync;
|
||||
|
||||
- (nonnull mbgl::Map *)mbglMap;
|
||||
|
||||
- (nonnull mbgl::Renderer *)renderer;
|
||||
|
||||
/** Returns whether the map view is currently loading or processing any assets required to render the map */
|
||||
- (BOOL)isFullyLoaded;
|
||||
@@ -30,4 +57,12 @@ FOUNDATION_EXTERN MGL_EXPORT MGLExceptionName const MGLUnderlyingMapUnavailableE
|
||||
/** Empties the in-memory tile cache. */
|
||||
- (void)didReceiveMemoryWarning;
|
||||
|
||||
- (void)pauseRendering:(nonnull NSNotification *)notification;
|
||||
- (void)resumeRendering:(nonnull NSNotification *)notification;
|
||||
@property (nonatomic, nonnull) MGLUserLocationAnnotationView *userLocationAnnotationView;
|
||||
@property (nonatomic, nonnull) MGLAnnotationContainerView *annotationContainerView;
|
||||
@property (nonatomic, readonly) BOOL enablePresentsWithTransaction;
|
||||
|
||||
- (BOOL) _opaque;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,7 +10,7 @@ macro(mbgl_platform_core)
|
||||
target_add_mason_package(mbgl-core PUBLIC swiftshader)
|
||||
else()
|
||||
target_sources(mbgl-core
|
||||
PRIVATE platform/darwin/src/headless_backend_cgl.cpp
|
||||
PRIVATE platform/darwin/src/headless_backend_cgl.mm
|
||||
)
|
||||
target_link_libraries(mbgl-core
|
||||
PUBLIC "-framework OpenGL"
|
||||
|
||||
@@ -95,6 +95,10 @@
|
||||
556660D61E1D07E400E2C41B /* MGLVersionNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 556660D51E1D07E400E2C41B /* MGLVersionNumber.m */; };
|
||||
558DE7A61E56161C00C7916D /* MGLFoundation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 558DE7A41E56161C00C7916D /* MGLFoundation_Private.h */; };
|
||||
558DE7A71E56161C00C7916D /* MGLFoundation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 558DE7A51E56161C00C7916D /* MGLFoundation.mm */; };
|
||||
5591AC6A2298361600FF9ADF /* MGLMapView+Impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 5591AC682298361600FF9ADF /* MGLMapView+Impl.h */; };
|
||||
5591AC6B2298361600FF9ADF /* MGLMapView+Impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5591AC692298361600FF9ADF /* MGLMapView+Impl.mm */; };
|
||||
55CAF6322294407F00F17770 /* MGLMapView+OpenGL.h in Headers */ = {isa = PBXBuildFile; fileRef = 55CAF6312294407F00F17770 /* MGLMapView+OpenGL.h */; };
|
||||
55CAF6342294409B00F17770 /* MGLMapView+OpenGL.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55CAF6332294409B00F17770 /* MGLMapView+OpenGL.mm */; };
|
||||
55CF7533213EDADF00ED86C4 /* libicu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55CF7532213EDADF00ED86C4 /* libicu.a */; };
|
||||
55D120A31F7906E6004B6D81 /* libmbgl-filesource.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D120A41F7906E6004B6D81 /* libmbgl-filesource.a */; };
|
||||
55D120A51F790A0C004B6D81 /* libmbgl-filesource.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D120A41F7906E6004B6D81 /* libmbgl-filesource.a */; };
|
||||
@@ -416,6 +420,10 @@
|
||||
556660D51E1D07E400E2C41B /* MGLVersionNumber.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = MGLVersionNumber.m; path = ../../darwin/test/MGLVersionNumber.m; sourceTree = "<group>"; };
|
||||
558DE7A41E56161C00C7916D /* MGLFoundation_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFoundation_Private.h; sourceTree = "<group>"; };
|
||||
558DE7A51E56161C00C7916D /* MGLFoundation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFoundation.mm; sourceTree = "<group>"; };
|
||||
5591AC682298361600FF9ADF /* MGLMapView+Impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+Impl.h"; sourceTree = "<group>"; };
|
||||
5591AC692298361600FF9ADF /* MGLMapView+Impl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "MGLMapView+Impl.mm"; sourceTree = "<group>"; };
|
||||
55CAF6312294407F00F17770 /* MGLMapView+OpenGL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MGLMapView+OpenGL.h"; sourceTree = "<group>"; };
|
||||
55CAF6332294409B00F17770 /* MGLMapView+OpenGL.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "MGLMapView+OpenGL.mm"; sourceTree = "<group>"; };
|
||||
55CF7532213EDADF00ED86C4 /* libicu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libicu.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
55D120A41F7906E6004B6D81 /* libmbgl-filesource.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libmbgl-filesource.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
55D9B4B01D005D3900C1CCE2 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
@@ -1262,6 +1270,10 @@
|
||||
DAE6C3A01CC31E9400DB3429 /* MGLMapView.h */,
|
||||
DAE6C3AC1CC31EF300DB3429 /* MGLMapView_Private.h */,
|
||||
DAE6C3AD1CC31EF300DB3429 /* MGLMapView.mm */,
|
||||
5591AC682298361600FF9ADF /* MGLMapView+Impl.h */,
|
||||
5591AC692298361600FF9ADF /* MGLMapView+Impl.mm */,
|
||||
55CAF6332294409B00F17770 /* MGLMapView+OpenGL.mm */,
|
||||
55CAF6312294407F00F17770 /* MGLMapView+OpenGL.h */,
|
||||
DAE6C3A11CC31E9400DB3429 /* MGLMapView+IBAdditions.h */,
|
||||
DAE6C3AE1CC31EF300DB3429 /* MGLMapView+IBAdditions.mm */,
|
||||
DAE6C3A21CC31E9400DB3429 /* MGLMapViewDelegate.h */,
|
||||
@@ -1357,6 +1369,7 @@
|
||||
35C5D8491D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
|
||||
9250B8C32073C69100EF338C /* MGLShapeOfflineRegion.h in Headers */,
|
||||
747ABE67219B2C3200523B67 /* MGLSymbolStyleLayer_Private.h in Headers */,
|
||||
55CAF6322294407F00F17770 /* MGLMapView+OpenGL.h in Headers */,
|
||||
DD0902B31DB1AC6400C5BDCE /* MGLNetworkConfiguration.h in Headers */,
|
||||
DAE6C3621CC31E0400DB3429 /* MGLOverlay.h in Headers */,
|
||||
DAE6C3651CC31E0400DB3429 /* MGLPolyline.h in Headers */,
|
||||
@@ -1367,6 +1380,7 @@
|
||||
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
|
||||
55335DF9212EC542000CE5F8 /* NSImage+MGLAdditions.h in Headers */,
|
||||
1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */,
|
||||
5591AC6A2298361600FF9ADF /* MGLMapView+Impl.h in Headers */,
|
||||
359819591E02F611008FC139 /* NSCoder+MGLAdditions.h in Headers */,
|
||||
DAE6C38E1CC31E2A00DB3429 /* MGLOfflineStorage_Private.h in Headers */,
|
||||
747ABE61219B2C0000523B67 /* MGLLineStyleLayer_Private.h in Headers */,
|
||||
@@ -1638,6 +1652,7 @@
|
||||
1FCCEC53222EF9FE00302E3B /* MGLSDKMetricsManager.m in Sources */,
|
||||
DAE6C3981CC31E2A00DB3429 /* NSBundle+MGLAdditions.m in Sources */,
|
||||
DAE6C3B71CC31EF300DB3429 /* MGLMapView.mm in Sources */,
|
||||
55CAF6342294409B00F17770 /* MGLMapView+OpenGL.mm in Sources */,
|
||||
40B77E461DB11BCD003DA2FE /* NSArray+MGLAdditions.mm in Sources */,
|
||||
DAE6C38C1CC31E2A00DB3429 /* MGLOfflinePack.mm in Sources */,
|
||||
35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */,
|
||||
@@ -1697,6 +1712,7 @@
|
||||
DAD165751CF4CD7A001FF4B9 /* MGLShapeCollection.mm in Sources */,
|
||||
92FC0AE6207CDD8D007B6B54 /* MGLShapeOfflineRegion.mm in Sources */,
|
||||
35C5D8481D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
|
||||
5591AC6B2298361600FF9ADF /* MGLMapView+Impl.mm in Sources */,
|
||||
DA35A2AE1CCA091800E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
|
||||
DACA8623201920BE00E9693A /* MGLRasterDEMSource.mm in Sources */,
|
||||
DA8F258C1D51CA540010E6B5 /* MGLLineStyleLayer.mm in Sources */,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"platform/darwin/src/MGLSDKMetricsManager.m",
|
||||
"platform/darwin/src/NSBundle+MGLAdditions.m",
|
||||
"platform/macos/src/MGLMapView.mm",
|
||||
"platform/macos/src/MGLMapView+OpenGL.mm",
|
||||
"platform/darwin/src/NSArray+MGLAdditions.mm",
|
||||
"platform/darwin/src/MGLOfflinePack.mm",
|
||||
"platform/darwin/src/NSDate+MGLAdditions.mm",
|
||||
@@ -68,6 +69,7 @@
|
||||
"platform/darwin/src/MGLShapeCollection.mm",
|
||||
"platform/darwin/src/MGLShapeOfflineRegion.mm",
|
||||
"platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm",
|
||||
"platform/macos/src/MGLMapView+Impl.mm",
|
||||
"platform/darwin/src/MGLCompassDirectionFormatter.m",
|
||||
"platform/darwin/src/MGLRasterDEMSource.mm",
|
||||
"platform/darwin/src/MGLLineStyleLayer.mm",
|
||||
@@ -177,11 +179,13 @@
|
||||
"MGLNetworkConfiguration_Private.h": "platform/darwin/src/MGLNetworkConfiguration_Private.h",
|
||||
"NSCompoundPredicate+MGLAdditions.h": "platform/darwin/src/NSCompoundPredicate+MGLAdditions.h",
|
||||
"MGLSymbolStyleLayer_Private.h": "platform/darwin/src/MGLSymbolStyleLayer_Private.h",
|
||||
"MGLMapView+OpenGL.h": "platform/macos/src/MGLMapView+OpenGL.h",
|
||||
"NSProcessInfo+MGLAdditions.h": "platform/macos/src/NSProcessInfo+MGLAdditions.h",
|
||||
"MGLRendererFrontend.h": "platform/darwin/src/MGLRendererFrontend.h",
|
||||
"NSValue+MGLStyleAttributeAdditions.h": "platform/darwin/src/NSValue+MGLStyleAttributeAdditions.h",
|
||||
"NSImage+MGLAdditions.h": "platform/macos/src/NSImage+MGLAdditions.h",
|
||||
"MGLLight_Private.h": "platform/darwin/src/MGLLight_Private.h",
|
||||
"MGLMapView+Impl.h": "platform/macos/src/MGLMapView+Impl.h",
|
||||
"NSCoder+MGLAdditions.h": "platform/darwin/src/NSCoder+MGLAdditions.h",
|
||||
"MGLOfflineStorage_Private.h": "platform/darwin/src/MGLOfflineStorage_Private.h",
|
||||
"MGLLineStyleLayer_Private.h": "platform/darwin/src/MGLLineStyleLayer_Private.h",
|
||||
|
||||
43
platform/macos/src/MGLMapView+Impl.h
Normal file
43
platform/macos/src/MGLMapView+Impl.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#import <mbgl/gfx/renderer_backend.hpp>
|
||||
#import <mbgl/map/map_observer.hpp>
|
||||
#import <mbgl/util/image.hpp>
|
||||
|
||||
@class MGLMapView;
|
||||
|
||||
typedef struct _CGLContextObject* CGLContextObj;
|
||||
|
||||
class MGLMapViewImpl : public mbgl::MapObserver {
|
||||
public:
|
||||
static std::unique_ptr<MGLMapViewImpl> Create(MGLMapView*);
|
||||
|
||||
MGLMapViewImpl(MGLMapView*);
|
||||
virtual ~MGLMapViewImpl() = default;
|
||||
|
||||
virtual mbgl::gfx::RendererBackend& getRendererBackend() = 0;
|
||||
|
||||
// We need a static image of what was rendered for printing.
|
||||
virtual mbgl::PremultipliedImage readStillImage() = 0;
|
||||
|
||||
virtual CGLContextObj getCGLContextObj() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// mbgl::MapObserver implementation
|
||||
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) override;
|
||||
void onCameraIsChanging() override;
|
||||
void onCameraDidChange(mbgl::MapObserver::CameraChangeMode) override;
|
||||
void onWillStartLoadingMap() override;
|
||||
void onDidFinishLoadingMap() override;
|
||||
void onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) override;
|
||||
void onWillStartRenderingFrame() override;
|
||||
void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode) override;
|
||||
void onWillStartRenderingMap() override;
|
||||
void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode) override;
|
||||
void onDidFinishLoadingStyle() override;
|
||||
void onSourceChanged(mbgl::style::Source& source) override;
|
||||
void onDidBecomeIdle() override;
|
||||
|
||||
protected:
|
||||
/// Cocoa map view that this adapter bridges to.
|
||||
__weak MGLMapView *mapView = nullptr;
|
||||
};
|
||||
96
platform/macos/src/MGLMapView+Impl.mm
Normal file
96
platform/macos/src/MGLMapView+Impl.mm
Normal file
@@ -0,0 +1,96 @@
|
||||
#import "MGLMapView+Impl.h"
|
||||
#import "MGLMapView+OpenGL.h"
|
||||
#import "MGLStyle_Private.h"
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
|
||||
std::unique_ptr<MGLMapViewImpl> MGLMapViewImpl::Create(MGLMapView* nativeView) {
|
||||
return std::make_unique<MGLMapViewOpenGLImpl>(nativeView);
|
||||
}
|
||||
|
||||
MGLMapViewImpl::MGLMapViewImpl(MGLMapView* nativeView_) : mapView(nativeView_) {
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[mapView cameraWillChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraIsChanging() {
|
||||
[mapView cameraIsChanging];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[mapView cameraDidChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartLoadingMap() {
|
||||
[mapView mapViewWillStartLoadingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishLoadingMap() {
|
||||
[mapView mapViewDidFinishLoadingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) {
|
||||
NSString *description;
|
||||
MGLErrorCode code;
|
||||
switch (mapError) {
|
||||
case mbgl::MapLoadError::StyleParseError:
|
||||
code = MGLErrorCodeParseStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::StyleLoadError:
|
||||
code = MGLErrorCodeLoadStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::NotFoundError:
|
||||
code = MGLErrorCodeNotFound;
|
||||
description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
|
||||
break;
|
||||
default:
|
||||
code = MGLErrorCodeUnknown;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
|
||||
}
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
NSLocalizedFailureReasonErrorKey: @(what.c_str()),
|
||||
};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
|
||||
[mapView mapViewDidFailLoadingMapWithError:error];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartRenderingFrame() {
|
||||
[mapView mapViewWillStartRenderingFrame];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[mapView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onWillStartRenderingMap() {
|
||||
[mapView mapViewWillStartRenderingMap];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[mapView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidBecomeIdle() {
|
||||
[mapView mapViewDidBecomeIdle];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onDidFinishLoadingStyle() {
|
||||
[mapView mapViewDidFinishLoadingStyle];
|
||||
}
|
||||
|
||||
void MGLMapViewImpl::onSourceChanged(mbgl::style::Source& source) {
|
||||
NSString *identifier = @(source.getID().c_str());
|
||||
MGLSource * nativeSource = [mapView.style sourceWithIdentifier:identifier];
|
||||
[mapView sourceDidChange:nativeSource];
|
||||
}
|
||||
45
platform/macos/src/MGLMapView+OpenGL.h
Normal file
45
platform/macos/src/MGLMapView+OpenGL.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#import "MGLMapView+Impl.h"
|
||||
#import "MGLMapView_Private.h"
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/gl/renderer_backend.hpp>
|
||||
|
||||
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
|
||||
class MGLMapViewOpenGLImpl final : public MGLMapViewImpl,
|
||||
public mbgl::gl::RendererBackend,
|
||||
public mbgl::gfx::Renderable {
|
||||
public:
|
||||
MGLMapViewOpenGLImpl(MGLMapView*);
|
||||
~MGLMapViewOpenGLImpl() override = default;
|
||||
|
||||
public:
|
||||
void restoreFramebufferBinding();
|
||||
|
||||
// Implementation of mbgl::gfx::RendererBackend
|
||||
public:
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
// End implementation of mbgl::gfx::RendererBackend
|
||||
|
||||
// Implementation of mbgl::gl::RendererBackend
|
||||
public:
|
||||
void updateAssumedState() override;
|
||||
|
||||
private:
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override;
|
||||
// End implementation of mbgl::gl::Rendererbackend
|
||||
|
||||
// Implementation of MGLMapViewImpl
|
||||
public:
|
||||
mbgl::gfx::RendererBackend& getRendererBackend() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
mbgl::PremultipliedImage readStillImage() override;
|
||||
CGLContextObj getCGLContextObj() override;
|
||||
};
|
||||
89
platform/macos/src/MGLMapView+OpenGL.mm
Normal file
89
platform/macos/src/MGLMapView+OpenGL.mm
Normal file
@@ -0,0 +1,89 @@
|
||||
#import "MGLMapView+OpenGL.h"
|
||||
#import "MGLOpenGLLayer.h"
|
||||
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
|
||||
#import <OpenGL/gl.h>
|
||||
|
||||
class MGLMapViewOpenGLRenderableResource final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
MGLMapViewOpenGLRenderableResource(MGLMapViewOpenGLImpl& backend_) : backend(backend_) {
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
backend.restoreFramebufferBinding();
|
||||
}
|
||||
|
||||
private:
|
||||
MGLMapViewOpenGLImpl& backend;
|
||||
|
||||
public:
|
||||
// The current framebuffer of the NSOpenGLLayer we are painting to.
|
||||
GLint fbo = 0;
|
||||
|
||||
// The reference counted count of activation calls
|
||||
NSUInteger activationCount = 0;
|
||||
};
|
||||
|
||||
MGLMapViewOpenGLImpl::MGLMapViewOpenGLImpl(MGLMapView* nativeView_)
|
||||
: MGLMapViewImpl(nativeView_),
|
||||
mbgl::gl::RendererBackend(mbgl::gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable(mapView.framebufferSize,
|
||||
std::make_unique<MGLMapViewOpenGLRenderableResource>(*this)) {
|
||||
|
||||
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
|
||||
// we can’t display a map, so don’t even bother to have a map layer.
|
||||
mapView.layer =
|
||||
mapView.isTargetingInterfaceBuilder ? [CALayer layer] : [MGLOpenGLLayer layer];
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress MGLMapViewOpenGLImpl::getExtensionFunctionPointer(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
return reinterpret_cast<mbgl::gl::ProcAddress>(CFBundleGetFunctionPointerForName(
|
||||
framework, (__bridge CFStringRef)[NSString stringWithUTF8String:name]));
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::activate() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (resource.activationCount++) {
|
||||
return;
|
||||
}
|
||||
|
||||
MGLOpenGLLayer* layer = (MGLOpenGLLayer*)mapView.layer;
|
||||
[layer.openGLContext makeCurrentContext];
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::deactivate() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
if (--resource.activationCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::updateAssumedState() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &resource.fbo);
|
||||
assumeFramebufferBinding(resource.fbo);
|
||||
assumeViewport(0, 0, mapView.framebufferSize);
|
||||
}
|
||||
|
||||
void MGLMapViewOpenGLImpl::restoreFramebufferBinding() {
|
||||
auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
|
||||
setFramebufferBinding(resource.fbo);
|
||||
setViewport(0, 0, mapView.framebufferSize);
|
||||
}
|
||||
|
||||
mbgl::PremultipliedImage MGLMapViewOpenGLImpl::readStillImage() {
|
||||
return readFramebuffer(mapView.framebufferSize);
|
||||
}
|
||||
|
||||
CGLContextObj MGLMapViewOpenGLImpl::getCGLContextObj() {
|
||||
MGLOpenGLLayer* layer = (MGLOpenGLLayer*)mapView.layer;
|
||||
return layer.openGLContext.CGLContextObj;
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#import "MGLAttributionButton.h"
|
||||
#import "MGLCompassCell.h"
|
||||
#import "MGLOpenGLLayer.h"
|
||||
#import "MGLStyle.h"
|
||||
#import "MGLRendererFrontend.h"
|
||||
#import "MGLRendererConfiguration.h"
|
||||
@@ -33,8 +32,6 @@
|
||||
#import <mbgl/storage/reachability.h>
|
||||
#import <mbgl/style/image.hpp>
|
||||
#import <mbgl/renderer/renderer.hpp>
|
||||
#import <mbgl/gl/renderer_backend.hpp>
|
||||
#import <mbgl/gl/renderable_resource.hpp>
|
||||
#import <mbgl/storage/network_status.hpp>
|
||||
#import <mbgl/storage/resource_options.hpp>
|
||||
#import <mbgl/math/wrap.hpp>
|
||||
@@ -49,6 +46,7 @@
|
||||
#import <unordered_map>
|
||||
#import <unordered_set>
|
||||
|
||||
#import "MGLMapView+Impl.h"
|
||||
#import "NSBundle+MGLAdditions.h"
|
||||
#import "NSDate+MGLAdditions.h"
|
||||
#import "NSProcessInfo+MGLAdditions.h"
|
||||
@@ -60,10 +58,6 @@
|
||||
#import "NSPredicate+MGLPrivateAdditions.h"
|
||||
#import "MGLLoggingConfiguration_Private.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <OpenGL/gl.h>
|
||||
|
||||
class MGLMapViewImpl;
|
||||
class MGLAnnotationContext;
|
||||
|
||||
/// Distance from the edge of the view to ornament views (logo, attribution, etc.).
|
||||
@@ -160,7 +154,7 @@ public:
|
||||
@implementation MGLMapView {
|
||||
/// Cross-platform map view controller.
|
||||
mbgl::Map *_mbglMap;
|
||||
MGLMapViewImpl *_mbglView;
|
||||
std::unique_ptr<MGLMapViewImpl> _mbglView;
|
||||
std::unique_ptr<MGLRenderFrontend> _rendererFrontend;
|
||||
|
||||
NSPanGestureRecognizer *_panGestureRecognizer;
|
||||
@@ -267,7 +261,7 @@ public:
|
||||
_isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent;
|
||||
|
||||
// Set up cross-platform controllers and resources.
|
||||
_mbglView = new MGLMapViewImpl(self);
|
||||
_mbglView = MGLMapViewImpl::Create(self);
|
||||
|
||||
// Delete the pre-offline ambient cache at
|
||||
// ~/Library/Caches/com.mapbox.MapboxGL/cache.db.
|
||||
@@ -282,9 +276,9 @@ public:
|
||||
|
||||
MGLRendererConfiguration *config = [MGLRendererConfiguration currentConfiguration];
|
||||
|
||||
auto renderer = std::make_unique<mbgl::Renderer>(*_mbglView, config.scaleFactor, config.cacheDir, config.localFontFamilyName);
|
||||
auto renderer = std::make_unique<mbgl::Renderer>(_mbglView->getRendererBackend(), config.scaleFactor, config.cacheDir, config.localFontFamilyName);
|
||||
BOOL enableCrossSourceCollisions = !config.perSourceCollisions;
|
||||
_rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, *_mbglView, true);
|
||||
_rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, _mbglView->getRendererBackend(), true);
|
||||
|
||||
mbgl::MapOptions mapOptions;
|
||||
mapOptions.withMapMode(mbgl::MapMode::Continuous)
|
||||
@@ -300,10 +294,6 @@ public:
|
||||
|
||||
_mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, mapOptions, resourceOptions);
|
||||
|
||||
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
|
||||
// we can’t display a map, so don’t even bother to have a map layer.
|
||||
self.layer = _isTargetingInterfaceBuilder ? [CALayer layer] : [MGLOpenGLLayer layer];
|
||||
|
||||
// Notify map object when network reachability status changes.
|
||||
_reachability = [MGLReachability reachabilityForInternetConnection];
|
||||
_reachability.reachableBlock = ^(MGLReachability *) {
|
||||
@@ -550,10 +540,7 @@ public:
|
||||
delete _mbglMap;
|
||||
_mbglMap = nullptr;
|
||||
}
|
||||
if (_mbglView) {
|
||||
delete _mbglView;
|
||||
_mbglView = nullptr;
|
||||
}
|
||||
_mbglView.reset();
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(__unused NSDictionary *)change context:(void *)context {
|
||||
@@ -718,8 +705,7 @@ public:
|
||||
}
|
||||
|
||||
- (CGLContextObj)context {
|
||||
MGLOpenGLLayer *layer = _isTargetingInterfaceBuilder ? nil : (MGLOpenGLLayer *)self.layer;
|
||||
return layer.openGLContext.CGLContextObj;
|
||||
return _mbglView->getCGLContextObj();
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frame {
|
||||
@@ -820,7 +806,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setNeedsGLDisplay {
|
||||
- (BOOL)isTargetingInterfaceBuilder {
|
||||
return _isTargetingInterfaceBuilder;
|
||||
}
|
||||
|
||||
- (void)setNeedsRerender {
|
||||
MGLAssertIsMainThread();
|
||||
|
||||
[self.layer setNeedsDisplay];
|
||||
@@ -987,7 +977,7 @@ public:
|
||||
|
||||
- (void)print:(__unused id)sender {
|
||||
_isPrinting = YES;
|
||||
[self setNeedsGLDisplay];
|
||||
[self setNeedsRerender];
|
||||
}
|
||||
|
||||
- (void)printWithImage:(NSImage *)image {
|
||||
@@ -3038,175 +3028,4 @@ public:
|
||||
_mbglMap->setDebug(options);
|
||||
}
|
||||
|
||||
class MGLMapViewImpl;
|
||||
|
||||
class MGLMapViewRenderable final : public mbgl::gl::RenderableResource {
|
||||
public:
|
||||
MGLMapViewRenderable(MGLMapViewImpl& backend_) : backend(backend_) {
|
||||
}
|
||||
|
||||
void bind() override;
|
||||
|
||||
private:
|
||||
MGLMapViewImpl& backend;
|
||||
};
|
||||
|
||||
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
|
||||
class MGLMapViewImpl : public mbgl::gl::RendererBackend,
|
||||
public mbgl::gfx::Renderable,
|
||||
public mbgl::MapObserver {
|
||||
public:
|
||||
MGLMapViewImpl(MGLMapView* nativeView_)
|
||||
: mbgl::gl::RendererBackend(mbgl::gfx::ContextMode::Unique),
|
||||
mbgl::gfx::Renderable(nativeView_.framebufferSize,
|
||||
std::make_unique<MGLMapViewRenderable>(*this)),
|
||||
nativeView(nativeView_) {
|
||||
}
|
||||
|
||||
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[nativeView cameraWillChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void onCameraIsChanging() override {
|
||||
[nativeView cameraIsChanging];
|
||||
}
|
||||
|
||||
void onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) override {
|
||||
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
|
||||
[nativeView cameraDidChangeAnimated:animated];
|
||||
}
|
||||
|
||||
void onWillStartLoadingMap() override {
|
||||
[nativeView mapViewWillStartLoadingMap];
|
||||
}
|
||||
|
||||
void onDidFinishLoadingMap() override {
|
||||
[nativeView mapViewDidFinishLoadingMap];
|
||||
}
|
||||
|
||||
void onDidFailLoadingMap(mbgl::MapLoadError mapError, const std::string& what) override {
|
||||
NSString *description;
|
||||
MGLErrorCode code;
|
||||
switch (mapError) {
|
||||
case mbgl::MapLoadError::StyleParseError:
|
||||
code = MGLErrorCodeParseStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"PARSE_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style is corrupted.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::StyleLoadError:
|
||||
code = MGLErrorCodeLoadStyleFailed;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_STYLE_FAILED_DESC", nil, nil, @"The map failed to load because the style can't be loaded.", @"User-friendly error description");
|
||||
break;
|
||||
case mbgl::MapLoadError::NotFoundError:
|
||||
code = MGLErrorCodeNotFound;
|
||||
description = NSLocalizedStringWithDefaultValue(@"STYLE_NOT_FOUND_DESC", nil, nil, @"The map failed to load because the style can’t be found or is incompatible.", @"User-friendly error description");
|
||||
break;
|
||||
default:
|
||||
code = MGLErrorCodeUnknown;
|
||||
description = NSLocalizedStringWithDefaultValue(@"LOAD_MAP_FAILED_DESC", nil, nil, @"The map failed to load because an unknown error occurred.", @"User-friendly error description");
|
||||
}
|
||||
NSDictionary *userInfo = @{
|
||||
NSLocalizedDescriptionKey: description,
|
||||
NSLocalizedFailureReasonErrorKey: @(what.c_str()),
|
||||
};
|
||||
NSError *error = [NSError errorWithDomain:MGLErrorDomain code:code userInfo:userInfo];
|
||||
[nativeView mapViewDidFailLoadingMapWithError:error];
|
||||
}
|
||||
|
||||
void onWillStartRenderingFrame() override {
|
||||
[nativeView mapViewWillStartRenderingFrame];
|
||||
}
|
||||
|
||||
void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) override {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[nativeView mapViewDidFinishRenderingFrameFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void onWillStartRenderingMap() override {
|
||||
[nativeView mapViewWillStartRenderingMap];
|
||||
}
|
||||
|
||||
void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) override {
|
||||
bool fullyRendered = mode == mbgl::MapObserver::RenderMode::Full;
|
||||
[nativeView mapViewDidFinishRenderingMapFullyRendered:fullyRendered];
|
||||
}
|
||||
|
||||
void onDidBecomeIdle() override {
|
||||
[nativeView mapViewDidBecomeIdle];
|
||||
}
|
||||
|
||||
void onDidFinishLoadingStyle() override {
|
||||
[nativeView mapViewDidFinishLoadingStyle];
|
||||
}
|
||||
|
||||
void onSourceChanged(mbgl::style::Source& source) override {
|
||||
NSString *identifier = @(source.getID().c_str());
|
||||
MGLSource * nativeSource = [nativeView.style sourceWithIdentifier:identifier];
|
||||
[nativeView sourceDidChange:nativeSource];
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void *symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
mbgl::gfx::Renderable& getDefaultRenderable() override {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void activate() override {
|
||||
if (activationCount++) {
|
||||
return;
|
||||
}
|
||||
|
||||
MGLOpenGLLayer *layer = (MGLOpenGLLayer *)nativeView.layer;
|
||||
[layer.openGLContext makeCurrentContext];
|
||||
}
|
||||
|
||||
void deactivate() override {
|
||||
if (--activationCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void updateAssumedState() override {
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
|
||||
assumeFramebufferBinding(fbo);
|
||||
assumeViewport(0, 0, nativeView.framebufferSize);
|
||||
}
|
||||
|
||||
void restoreFramebufferBinding() {
|
||||
setFramebufferBinding(fbo);
|
||||
setViewport(0, 0, nativeView.framebufferSize);
|
||||
}
|
||||
|
||||
mbgl::PremultipliedImage readStillImage() {
|
||||
return readFramebuffer(nativeView.framebufferSize);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Cocoa map view that this adapter bridges to.
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
|
||||
/// The current framebuffer of the NSOpenGLLayer we are painting to.
|
||||
GLint fbo = 0;
|
||||
|
||||
/// The reference counted count of activation calls
|
||||
NSUInteger activationCount = 0;
|
||||
};
|
||||
|
||||
void MGLMapViewRenderable::bind() {
|
||||
backend.restoreFramebufferBinding();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -181,6 +181,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style;
|
||||
|
||||
- (nullable NSImage *)mapView:(MGLMapView *)mapView didFailToLoadImage:(NSString *)imageName;
|
||||
|
||||
#pragma mark Managing the Appearance of Annotations
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#import "MGLMapView.h"
|
||||
|
||||
#include <mbgl/util/size.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
class Map;
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
@class MGLSource;
|
||||
|
||||
@interface MGLMapView (Private)
|
||||
|
||||
/// True if the view or application is in a state where it is not expected to be
|
||||
@@ -22,17 +26,36 @@ namespace mbgl {
|
||||
/// Center longitude set independently of the center latitude in an inspectable.
|
||||
@property (nonatomic) CLLocationDegrees pendingLongitude;
|
||||
|
||||
/// The map view’s OpenGL rendering context.
|
||||
- (CGLContextObj)context;
|
||||
/// The map view’s OpenGL rendering context, if it is backed by an OpenGL based view.
|
||||
@property (readonly, nonatomic, nullable) CGLContextObj context;
|
||||
|
||||
- (mbgl::Size)framebufferSize;
|
||||
|
||||
/// Map observers
|
||||
- (void)cameraWillChangeAnimated:(BOOL)animated;
|
||||
- (void)cameraIsChanging;
|
||||
- (void)cameraDidChangeAnimated:(BOOL)animated;
|
||||
- (void)mapViewWillStartLoadingMap;
|
||||
- (void)mapViewDidFinishLoadingMap;
|
||||
- (void)mapViewDidFailLoadingMapWithError:(nonnull NSError *)error;
|
||||
- (void)mapViewWillStartRenderingFrame;
|
||||
- (void)mapViewDidFinishRenderingFrameFullyRendered:(BOOL)fullyRendered;
|
||||
- (void)mapViewWillStartRenderingMap;
|
||||
- (void)mapViewDidFinishRenderingMapFullyRendered:(BOOL)fullyRendered;
|
||||
- (void)mapViewDidBecomeIdle;
|
||||
- (void)mapViewDidFinishLoadingStyle;
|
||||
- (void)sourceDidChange:(nonnull MGLSource *)source;
|
||||
|
||||
/// Asynchronously render a frame of the map.
|
||||
- (void)setNeedsGLDisplay;
|
||||
- (void)setNeedsRerender;
|
||||
|
||||
/// Synchronously render a frame of the map.
|
||||
- (void)renderSync;
|
||||
|
||||
- (mbgl::Map *)mbglMap;
|
||||
- (BOOL)isTargetingInterfaceBuilder;
|
||||
|
||||
- (mbgl::Renderer *)renderer;
|
||||
- (nonnull mbgl::Map *)mbglMap;
|
||||
|
||||
- (nonnull mbgl::Renderer *)renderer;
|
||||
|
||||
@end
|
||||
|
||||
@@ -28,6 +28,8 @@ extension MGLMapViewDelegateIntegrationTests: MGLMapViewDelegate {
|
||||
func mapViewDidBecomeIdle(_ mapView: MGLMapView) {}
|
||||
|
||||
func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {}
|
||||
|
||||
func mapView(_ mapView: MGLMapView, didFailToLoadImage imageName: String) -> NSImage? { return nil }
|
||||
|
||||
func mapView(_ mapView: MGLMapView, shapeAnnotationIsEnabled annotation: MGLShape) -> Bool { return false }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user