summaryrefslogtreecommitdiff
path: root/platform/macos/src/MGLMapView+OpenGL.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/macos/src/MGLMapView+OpenGL.mm')
-rw-r--r--platform/macos/src/MGLMapView+OpenGL.mm89
1 files changed, 89 insertions, 0 deletions
diff --git a/platform/macos/src/MGLMapView+OpenGL.mm b/platform/macos/src/MGLMapView+OpenGL.mm
new file mode 100644
index 0000000000..f6168a4b80
--- /dev/null
+++ b/platform/macos/src/MGLMapView+OpenGL.mm
@@ -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;
+}