Skip to content

Commit

Permalink
[map] Expose presentsWithTransaction inside RenderOptions (#94)
Browse files Browse the repository at this point in the history
* Expose presentsWithTransaction inside RenderOptions

* add test

* Call setNeedsDisplay instead of draw

* Honor updates to preferredFramesPerSecond
  • Loading branch information
nishant-karajgikar committed Feb 11, 2021
1 parent 511e58d commit 25a55fc
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 39 deletions.
4 changes: 4 additions & 0 deletions Mapbox/MapboxMaps.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@
0CC6EF2C25C3263400BFB153 /* RasterLayerIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CC6EF0725C3263400BFB153 /* RasterLayerIntegrationTests.swift */; };
0CC8BD30242405AA00288A9B /* GestureManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8BD2C242405AA00288A9B /* GestureManager.swift */; };
0CC8BD31242405AA00288A9B /* GestureHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CC8BD2D242405AA00288A9B /* GestureHandlerDelegate.swift */; };
0CC9937E25D46B7100650CC1 /* RenderOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9937D25D46B7100650CC1 /* RenderOptions.swift */; };
0CD34FD7242AADDB00943687 /* MapboxMaps.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CD34FCE242AADDB00943687 /* MapboxMaps.framework */; };
0CD34FDE242AADDB00943687 /* MapboxMaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CD34FD0242AADDB00943687 /* MapboxMaps.h */; settings = {ATTRIBUTES = (Public, ); }; };
0CD34FE8242AAE0900943687 /* MapView+Managers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD34FE6242AAE0900943687 /* MapView+Managers.swift */; };
Expand Down Expand Up @@ -975,6 +976,7 @@
0CC8BD2B242405AA00288A9B /* TapGestureHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TapGestureHandler.swift; sourceTree = "<group>"; };
0CC8BD2C242405AA00288A9B /* GestureManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GestureManager.swift; sourceTree = "<group>"; };
0CC8BD2D242405AA00288A9B /* GestureHandlerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GestureHandlerDelegate.swift; sourceTree = "<group>"; };
0CC9937D25D46B7100650CC1 /* RenderOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderOptions.swift; sourceTree = "<group>"; };
0CD34FCE242AADDB00943687 /* MapboxMaps.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MapboxMaps.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0CD34FD0242AADDB00943687 /* MapboxMaps.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MapboxMaps.h; sourceTree = "<group>"; };
0CD34FD1242AADDB00943687 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1482,6 +1484,7 @@
5A3593B5247FD9AC00E67344 /* LayoutVisibility.swift */,
5A3593B8247FDA4800E67344 /* LayoutPosition.swift */,
0CAC3CC22534E90500D031E7 /* MapSnapshotOptions.swift */,
0CC9937D25D46B7100650CC1 /* RenderOptions.swift */,
);
path = Configuration;
sourceTree = "<group>";
Expand Down Expand Up @@ -3413,6 +3416,7 @@
0C708F2924EB1EE2003CE791 /* LocationIndicatorLayer.swift in Sources */,
0C708F6024EC70DD003CE791 /* Color.swift in Sources */,
0C708F2D24EB1EE2003CE791 /* HeatmapLayer.swift in Sources */,
0CC9937E25D46B7100650CC1 /* RenderOptions.swift in Sources */,
0C3B1E9024DDADD000CC29E8 /* EventsManager.swift in Sources */,
0C708F4B24EB23C7003CE791 /* ImageSource.swift in Sources */,
C64994AF258D5ADE0052C21C /* PuckLocationIndicatorLayer.swift in Sources */,
Expand Down
33 changes: 1 addition & 32 deletions Mapbox/MapboxMaps/Configuration/MapOptions.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
import Foundation

/// Options for frame rate
public enum PreferredFramesPerSecond: Int, Equatable {
/// The default frame rate. This can be either 30 FPS or 60 FPS, depending on
/// device capabilities.
case normal = -1

/// A conservative frame rate; typically 30 FPS.
case lowPower = 30

/// The maximum supported frame rate; typically 60 FPS.
case maximum = 0
}

/// `MapOptions` is the structure used to configure the map with a set of capabilities
public struct MapOptions: Equatable {
/// Used to configure the gestures on the map
Expand All @@ -27,23 +14,5 @@ public struct MapOptions: Equatable {
/// Used to configure the location provider
public var location: LocationOptions = LocationOptions()

/// The preferred frame rate at which the map view is rendered.
///
/// The default value for this property is
/// `MGLMapViewPreferredFramesPerSecondDefault`, which will adaptively set the
/// preferred frame rate based on the capability of the user’s device to maintain
/// a smooth experience.
///
/// See Also `CADisplayLink.preferredFramesPerSecond`
public var preferredFramesPerSecond: PreferredFramesPerSecond = .normal

/// A Boolean value indicating whether the map should prefetch tiles.
///
/// When this property is set to `YES`, the map view prefetches tiles designed for
/// a low zoom level and displays them until receiving more detailed tiles for the
/// current zoom level. The prefetched tiles typically contain simplified versions
/// of each shape, improving the map view’s perceived performance.
///
/// The default value of this property is `YES`.
public var prefetchesTiles: Bool = true
public var render: RenderOptions = RenderOptions()
}
36 changes: 36 additions & 0 deletions Mapbox/MapboxMaps/Configuration/RenderOptions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation

/// Used to configure rendering-specific capabilities of the `MapView`
public struct RenderOptions: Equatable {

/// The preferred frame rate at which the map view is rendered.
///
/// The default value for this property is
/// `.normal`, which will adaptively set the
/// preferred frame rate based on the capability of the user’s device to maintain
/// a smooth experience.
///
/// See Also `CADisplayLink.preferredFramesPerSecond`
public var preferredFramesPerSecond: PreferredFPS = .normal

/// A Boolean value indicating whether the map should prefetch tiles.
///
/// When this property is set to `true`, the map view prefetches tiles designed for
/// a low zoom level and displays them until receiving more detailed tiles for the
/// current zoom level. The prefetched tiles typically contain simplified versions
/// of each shape, improving the map view’s perceived performance.
///
/// The default value of this property is `true`.
public var prefetchesTiles: Bool = true

/// A Boolean value that indicates whether the underlying `CAMetalLayer` of the `MapView`
/// presents its content using a CoreAnimation transaction
///
/// By default, this is `false` resulting in the output of a rendering pass being displayed on
/// the `CAMetalLayer` as quickly as possible (and asynchronously). This typically results
/// in the fastest rendering performance.
///
/// If, however, the `MapView` is overlaid with a `UIKit` element which must be pinned to a
/// particular lat-long, then setting this to `true` will result in better synchronization and less jitter.
public var presentsWithTransaction: Bool = false
}
15 changes: 10 additions & 5 deletions Mapbox/MapboxMaps/MapView+Managers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extension MapView {
internal func setupManagers() {

// Initialize/configure the map if needed
setupMapView()
setupMapView(with: mapOptions.render)

// Initialize/Configure camera manager first since Gestures needs it as dependency
setupCamera(for: self, options: mapOptions.camera)
Expand All @@ -35,23 +35,28 @@ extension MapView {
updateMapOptions(&self.mapOptions) // This mutates the map options

// Update the managers in order
updateMapView(with: mapOptions)
updateMapView(with: mapOptions.render)
updateCamera(with: mapOptions.camera)
updateGestures(with: mapOptions.gestures)
updateOrnaments(with: mapOptions.ornaments)
updateUserLocationManager(with: mapOptions.location)
}

internal func setupMapView() {
internal func setupMapView(with renderOptions: RenderOptions) {

// Set prefetch zoom delta
let defaultPrefetchZoomDelta: UInt8 = 4
try! self.__map.setPrefetchZoomDeltaForDelta(self.mapOptions.prefetchesTiles ? defaultPrefetchZoomDelta : 0)
try! self.__map.setPrefetchZoomDeltaForDelta(renderOptions.prefetchesTiles ? defaultPrefetchZoomDelta : 0)
self.metalView?.presentsWithTransaction = renderOptions.presentsWithTransaction
self.preferredFPS = renderOptions.preferredFramesPerSecond
}

internal func updateMapView(with newOptions: MapOptions) {
internal func updateMapView(with newOptions: RenderOptions) {
// Set prefetch zoom delta
let defaultPrefetchZoomDelta: UInt8 = 4
try! self.__map.setPrefetchZoomDeltaForDelta(newOptions.prefetchesTiles ? defaultPrefetchZoomDelta : 0)
self.metalView?.presentsWithTransaction = newOptions.presentsWithTransaction
self.preferredFPS = newOptions.preferredFramesPerSecond
}

internal func setupGestures(with view: UIView, options: GestureOptions, cameraManager: CameraManager) {
Expand Down
9 changes: 7 additions & 2 deletions Mapbox/MapboxMapsFoundation/BaseMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ open class ObserverConcrete: Observer {

open class BaseMapView: UIView, MapClient, MBMMetalViewProvider {

/// The underlying renderer object responsible for rendering the map
public var __map: Map!

/// The underlying metal view that is used to render the map
internal var metalView: MTKView?

/// Resource options for this map view
internal var resourceOptions: ResourceOptions?

Expand Down Expand Up @@ -291,7 +295,7 @@ open class BaseMapView: UIView, MapClient, MBMMetalViewProvider {

let metalView = MTKView(frame: self.frame, device: metalDevice)
self.displayCallback = {
metalView.draw()
metalView.setNeedsDisplay()
}

metalView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
Expand All @@ -301,10 +305,11 @@ open class BaseMapView: UIView, MapClient, MBMMetalViewProvider {
metalView.isOpaque = self.isOpaque
metalView.layer.isOpaque = self.isOpaque
metalView.isPaused = true
metalView.enableSetNeedsDisplay = false
metalView.enableSetNeedsDisplay = true
metalView.presentsWithTransaction = false

self.insertSubview(metalView, at: 0)
self.metalView = metalView

return metalView
}
Expand Down
2 changes: 2 additions & 0 deletions Mapbox/MapboxMapsTests/OptionsIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal class OptionsIntegrationTest: MapViewIntegrationTestCase {
newOptions.gestures.scrollEnabled = false
newOptions.ornaments.showsScale = false
newOptions.ornaments.showsCompass = false
newOptions.render.presentsWithTransaction = true

mapView.update { (options) in
options = newOptions
Expand All @@ -29,5 +30,6 @@ internal class OptionsIntegrationTest: MapViewIntegrationTestCase {
$0.type == .compass || $0.type == .mapboxScaleBar
}
)
XCTAssertEqual(mapView.metalView?.presentsWithTransaction, true)
}
}

0 comments on commit 25a55fc

Please sign in to comment.