summaryrefslogtreecommitdiff
path: root/platform/ios/src/MGLMapView+OpenGL.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ios/src/MGLMapView+OpenGL.mm')
-rw-r--r--platform/ios/src/MGLMapView+OpenGL.mm277
1 files changed, 0 insertions, 277 deletions
diff --git a/platform/ios/src/MGLMapView+OpenGL.mm b/platform/ios/src/MGLMapView+OpenGL.mm
deleted file mode 100644
index ad30b608e5..0000000000
--- a/platform/ios/src/MGLMapView+OpenGL.mm
+++ /dev/null
@@ -1,277 +0,0 @@
-#import "MGLFoundation_Private.h"
-#import "MGLLoggingConfiguration_Private.h"
-#import "MGLMapView+OpenGL.h"
-
-#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
-#import "MMEConstants.h"
-#import "MGLMapboxEvents.h"
-#endif
-
-#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
-
-namespace {
-CGFloat contentScaleFactor() {
- return [UIScreen instancesRespondToSelector:@selector(nativeScale)]
- ? [[UIScreen mainScreen] nativeScale]
- : [[UIScreen mainScreen] scale];
-}
-} // namespace
-
-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>();
-
- // 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) {
-#ifdef MGL_RECREATE_GL_IN_AN_EMERGENCY
- dispatch_async(dispatch_get_main_queue(), ^{
- emergencyRecreateGL();
- });
-#else
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- NSError *error = [NSError errorWithDomain:MGLErrorDomain
- code:MGLErrorCodeRenderingError
- userInfo:@{ NSLocalizedFailureReasonErrorKey :
- @"https://github.com/mapbox/mapbox-gl-native/issues/14232" }];
- [[MMEEventsManager sharedManager] reportError:error];
- });
-#endif
- }
- } else {
- [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 = contentScaleFactor();
- 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];
-}
-
-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;
-}
-
-void MGLMapViewOpenGLImpl::layoutChanged() {
- const auto scaleFactor = contentScaleFactor();
- size = { static_cast<uint32_t>(mapView.bounds.size.width * scaleFactor),
- static_cast<uint32_t>(mapView.bounds.size.height * scaleFactor) };
-}
-
-EAGLContext* MGLMapViewOpenGLImpl::getEAGLContext() {
- auto& resource = getResource<MGLMapViewOpenGLRenderableResource>();
- return resource.context;
-}