summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Rex <julian.rex@mapbox.com>2018-03-27 09:54:57 -0400
committerJulian Rex <julian.rex@mapbox.com>2018-03-27 10:10:13 -0400
commitf23c700c29876566376a13b651e54718f3f1e74c (patch)
tree72729e0eefc8a5f7284e742a0f08bc6812ad5631
parent4f196d48ddfc3bb05dee1cdd032af170a6c53d67 (diff)
downloadqtlocation-mapboxgl-upstream/jrex-11275-render-display-link-test.tar.gz
Add CVDisplayLink update, similar to CADisplayLink Refs #11275upstream/jrex-11275-render-display-link-test
-rw-r--r--platform/macos/src/MGLMapView.mm79
1 files changed, 74 insertions, 5 deletions
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 9cab9a76da..9a96e0928b 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -131,6 +131,9 @@ mbgl::util::UnitBezier MGLUnitBezierForMediaTimingFunction(CAMediaTimingFunction
return { p1[0], p1[1], p2[0], p2[1] };
}
+/// Forward declaration of render callback function called via CVDisplayLink
+static CVReturn MGLMapViewRenderCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext);
+
/// Lightweight container for metadata about an annotation, including the annotation itself.
class MGLAnnotationContext {
public:
@@ -207,6 +210,10 @@ public:
/// reachability instance
MGLReachability *_reachability;
+
+ // Display update
+ CVDisplayLinkRef _displayLink;
+ BOOL _needsDisplayRefresh;
}
#pragma mark Lifecycle
@@ -513,10 +520,10 @@ public:
}
- (void)dealloc {
+ [self validateDisplayLink];
[_reachability stopNotifier];
-
[self.window removeObserver:self forKeyPath:@"contentLayoutRect"];
[self.window removeObserver:self forKeyPath:@"titlebarAppearsTransparent"];
@@ -663,19 +670,56 @@ public:
self.dormant = YES;
}
+ [self validateDisplayLink];
+
[self.window removeObserver:self forKeyPath:@"contentLayoutRect"];
[self.window removeObserver:self forKeyPath:@"titlebarAppearsTransparent"];
}
+- (void)validateDisplayLink
+{
+ BOOL isVisible = self.superview && self.window;
+ if (isVisible && !_displayLink)
+ {
+ if (_mbglMap->getConstrainMode() == mbgl::ConstrainMode::None)
+ {
+ _mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
+ }
+
+ CVReturn error = CVDisplayLinkCreateWithCGDisplay(CGMainDisplayID(), &_displayLink);
+
+ if (error)
+ {
+ throw std::runtime_error("Failed to create display callback.");
+ _displayLink = NULL;
+ }
+ else
+ {
+ CVDisplayLinkSetOutputCallback(_displayLink, MGLMapViewRenderCallback, (__bridge void *)self);
+ _needsDisplayRefresh = YES;
+ CVDisplayLinkStart(_displayLink);
+ }
+ }
+ else if ( ! isVisible && _displayLink)
+ {
+ CVDisplayLinkStop(_displayLink);
+ CVDisplayLinkRelease(_displayLink);
+ _displayLink = nil;
+ }
+}
+
+
- (void)viewDidMoveToWindow {
NSWindow *window = self.window;
if (self.dormant && window) {
self.dormant = NO;
}
- if (window && _mbglMap->getConstrainMode() == mbgl::ConstrainMode::None) {
- _mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
- }
+ [self validateDisplayLink];
+
+// if (window && _mbglMap->getConstrainMode() == mbgl::ConstrainMode::None) {
+// _mbglMap->setConstrainMode(mbgl::ConstrainMode::HeightOnly);
+// }
[window addObserver:self
forKeyPath:@"contentLayoutRect"
@@ -795,10 +839,21 @@ public:
}
}
+- (void)updateFromDisplayLink
+{
+ MGLAssertIsMainThread();
+
+ if (_needsDisplayRefresh)
+ {
+ _needsDisplayRefresh = NO;
+ [self.layer setNeedsDisplay];
+ }
+}
+
- (void)setNeedsGLDisplay {
MGLAssertIsMainThread();
- [self.layer setNeedsDisplay];
+ _needsDisplayRefresh = YES;
}
- (void)cameraWillChangeAnimated:(BOOL)animated {
@@ -3024,3 +3079,17 @@ private:
};
@end
+
+CVReturn MGLMapViewRenderCallback(CVDisplayLinkRef displayLink,
+ const CVTimeStamp *inNow,
+ const CVTimeStamp *inOutputTime,
+ CVOptionFlags flagsIn,
+ CVOptionFlags *flagsOut,
+ void *displayLinkContext) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [(__bridge MGLMapView *)displayLinkContext updateFromDisplayLink];
+ });
+
+ return kCVReturnSuccess;
+}
+