-
Notifications
You must be signed in to change notification settings - Fork 58
Update PlatformDrawable API #673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
e908143
d9da712
58ed491
662b5fd
7685c81
f2f84d3
3cd6e73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| // | ||
| // PlatformViewDefinition.swift | ||
| // DisplayListViewPlatform.swift | ||
| // OpenSwiftUICore | ||
| // | ||
| // Audited for 6.0.87 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| // | ||
| // PlatformDrawable.swift | ||
| // OpenSwiftUICore | ||
| // | ||
| // Audited for 6.5.4 | ||
| // Status: WIP | ||
|
|
||
| public import CoreGraphics | ||
| public import QuartzCore | ||
| import OpenAttributeGraphShims | ||
| import OpenRenderBoxShims | ||
| import CoreAnimation_Private | ||
|
|
||
| // MARK: - PlatformDrawable | ||
|
|
||
| @_spi(DisplayList_ViewSystem) | ||
| @available(OpenSwiftUI_v6_0, *) | ||
| public protocol PlatformDrawable: AnyObject { | ||
| var options: PlatformDrawableOptions { get set } | ||
|
|
||
| static var allowsContentsMultiplyColor: Bool { get } | ||
|
|
||
| func update(content: PlatformDrawableContent?, required: Bool) -> Bool | ||
|
|
||
| func makeAsyncUpdate( | ||
| content: PlatformDrawableContent, | ||
| required: Bool, | ||
| layer: CALayer, | ||
| bounds: CGRect | ||
| ) -> (() -> Void)? | ||
|
|
||
| func setContentsScale(_ scale: CGFloat) | ||
|
|
||
| func drawForTesting(in: RBDisplayList) -> () | ||
| } | ||
|
|
||
| // MARK: - PlatformDrawableContent [WIP] | ||
|
|
||
| @_spi(DisplayList_ViewSystem) | ||
| @available(OpenSwiftUI_v6_0, *) | ||
| public struct PlatformDrawableContent: @unchecked Sendable { | ||
| enum Storage { | ||
| case graphicsCallback((inout GraphicsContext, CGSize) -> ()) | ||
| case platformCallback((CGSize) -> ()) | ||
| case displayList(DisplayList, CGPoint, Time) | ||
| case rbDisplayList(RBDisplayListContents, CGPoint) | ||
| case rbInterpolator(RBDisplayListInterpolator, Float, CGPoint) | ||
| case empty | ||
| } | ||
|
|
||
| private var storage: Storage = .empty | ||
|
|
||
| public struct State { | ||
| package var mode: DisplayList.GraphicsRenderer.PlatformViewMode | ||
|
|
||
| package var _renderer: DisplayList.GraphicsRenderer? | ||
|
|
||
| package init() { | ||
| mode = .unsupported | ||
| _renderer = nil | ||
| } | ||
|
|
||
| package init(platformViewMode: DisplayList.GraphicsRenderer.PlatformViewMode) { | ||
| mode = platformViewMode | ||
| _renderer = nil | ||
| } | ||
|
|
||
| package mutating func renderer() -> DisplayList.GraphicsRenderer { | ||
| guard let _renderer else { | ||
| let render = DisplayList.GraphicsRenderer(platformViewMode: mode) | ||
| _renderer = render | ||
| return render | ||
| } | ||
| return _renderer | ||
| } | ||
| } | ||
|
|
||
| public init() { | ||
| _openSwiftUIEmptyStub() | ||
| } | ||
|
|
||
| public func draw( | ||
| in ctx: CGContext, | ||
| size: CGSize, | ||
| contentsScale: CGFloat, | ||
| state: inout PlatformDrawableContent.State | ||
| ) { | ||
| _openSwiftUIUnimplementedFailure() | ||
| } | ||
|
|
||
| public func draw( | ||
| in list: RBDisplayList, | ||
| size: CGSize, | ||
| state: inout PlatformDrawableContent.State | ||
| ) { | ||
| _openSwiftUIUnimplementedFailure() | ||
| } | ||
| } | ||
|
|
||
| @_spi(DisplayList_ViewSystem) | ||
| @available(*, unavailable) | ||
| extension PlatformDrawableContent.State: Sendable {} | ||
|
|
||
| // MARK: - PlatformDrawableOptions [Blocked by RBLayer] | ||
|
|
||
| @_spi(DisplayList_ViewSystem) | ||
| @available(OpenSwiftUI_v6_0, *) | ||
| public struct PlatformDrawableOptions: Equatable, Sendable { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Was this useful? React with 👍 or 👎 |
||
| var base: RasterizationOptions | ||
|
|
||
| public var isAccelerated: Bool { | ||
| base.isAccelerated | ||
| } | ||
|
|
||
| public var isOpaque: Bool { | ||
| base.isOpaque | ||
| } | ||
|
|
||
| public var rendersAsynchronously: Bool { | ||
| base.rendersAsynchronously | ||
| } | ||
|
|
||
| public var rendersFirstFrameAsynchronously: Bool { | ||
| base.rendersFirstFrameAsynchronously | ||
| } | ||
|
|
||
| public var caLayerContentsFormat: CALayerContentsFormat { | ||
| var format = CALayerContentsFormat.automatic | ||
| if base.flags.contains(.rgbaContext) { | ||
| format = .RGBA8Uint | ||
| } | ||
| if base.flags.contains(.alphaOnly) { | ||
| format = .A8 | ||
| } | ||
| return format | ||
| } | ||
|
|
||
| public func update(rbLayer: AnyObject) { | ||
| // TODO: RBLayer | ||
| _openSwiftUIUnimplementedFailure() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| // | ||
| // RasterizationOptions.swift | ||
| // OpenSwiftUICore | ||
| // | ||
| // Audited for 6.5.4 | ||
| // Status: WIP | ||
|
|
||
| // MARK: - ColorRenderingMode | ||
|
|
||
| /// The set of possible working color spaces for color-compositing operations. | ||
| /// | ||
| /// Each color space guarantees the preservation of a particular range of color | ||
| /// values. | ||
| public enum ColorRenderingMode: Sendable { | ||
|
|
||
| /// The non-linear sRGB working color space. | ||
| /// | ||
| /// Color component values outside the range `[0, 1]` produce undefined | ||
| /// results. This color space is gamma corrected. | ||
| case nonLinear | ||
|
|
||
| /// The linear sRGB working color space. | ||
| /// | ||
| /// Color component values outside the range `[0, 1]` produce undefined | ||
| /// results. This color space isn't gamma corrected. | ||
| case linear | ||
|
|
||
| /// The extended linear sRGB working color space. | ||
| /// | ||
| /// Color component values outside the range `[0, 1]` are preserved. | ||
| /// This color space isn't gamma corrected. | ||
| case extendedLinear | ||
| } | ||
|
|
||
| extension ColorRenderingMode: ProtobufEnum { | ||
| package var protobufValue: UInt { | ||
| switch self { | ||
| case .nonLinear: return 0 | ||
| case .linear: return 1 | ||
| case .extendedLinear: return 2 | ||
| } | ||
| } | ||
|
|
||
| package init?(protobufValue value: UInt) { | ||
| switch value { | ||
| case 0: self = .nonLinear | ||
| case 1: self = .linear | ||
| case 2: self = .extendedLinear | ||
| default: return nil | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // MARK: - RasterizationOptions [WIP] | ||
|
|
||
| package struct RasterizationOptions: Equatable { | ||
| package struct Flags: OptionSet { | ||
| package let rawValue: UInt32 | ||
|
|
||
| package init(rawValue: UInt32) { | ||
| self.rawValue = rawValue | ||
| } | ||
|
|
||
| package static let isAccelerated: RasterizationOptions.Flags = .init(rawValue: 1 << 0) | ||
|
|
||
| package static let isOpaque: RasterizationOptions.Flags = .init(rawValue: 1 << 1) | ||
|
|
||
| package static let rendersAsynchronously: RasterizationOptions.Flags = .init(rawValue: 1 << 2) | ||
|
|
||
| package static let prefersDisplayCompositing: RasterizationOptions.Flags = .init(rawValue: 1 << 3) | ||
|
|
||
| package static let rendersFirstFrameAsync: RasterizationOptions.Flags = .init(rawValue: 1 << 4) | ||
|
|
||
| package static let allowsPackedDrawable: RasterizationOptions.Flags = .init(rawValue: 1 << 5) | ||
|
|
||
| package static let alphaOnly: RasterizationOptions.Flags = .init(rawValue: 1 << 6) | ||
|
|
||
| package static let requiresLayer: RasterizationOptions.Flags = .init(rawValue: 1 << 7) | ||
|
|
||
| package static let rgbaContext: RasterizationOptions.Flags = .init(rawValue: 1 << 8) | ||
|
|
||
| package static let highRes: RasterizationOptions.Flags = .init(rawValue: 1 << 9) | ||
|
|
||
| package static let defaultFlags: RasterizationOptions.Flags = [.allowsPackedDrawable, .requiresLayer] | ||
| } | ||
|
|
||
| package var colorMode: ColorRenderingMode | ||
|
|
||
| package var rbColorMode: Int32? | ||
|
|
||
| package var flags: RasterizationOptions.Flags | ||
|
|
||
| package var maxDrawableCount: Int8 | ||
|
|
||
| package init( | ||
| colorMode: ColorRenderingMode = .nonLinear, | ||
| rbColorMode: Int32? = nil, | ||
| flags: RasterizationOptions.Flags = .defaultFlags, | ||
| maxDrawableCount: Int8 = 3 | ||
| ) { | ||
| self.colorMode = colorMode | ||
| self.rbColorMode = rbColorMode | ||
| self.flags = flags | ||
| self.maxDrawableCount = maxDrawableCount | ||
| } | ||
|
|
||
| package var isAccelerated: Bool { | ||
| get { flags.contains(.isAccelerated) } | ||
| set { flags.setValue(newValue, for: .isAccelerated) } | ||
| } | ||
|
|
||
| package var isOpaque: Bool { | ||
| get { flags.contains(.isOpaque) } | ||
| set { flags.setValue(newValue, for: .isOpaque) } | ||
| } | ||
|
|
||
| package var rendersAsynchronously: Bool { | ||
| get { flags.contains(.rendersAsynchronously) } | ||
| set { flags.setValue(newValue, for: .rendersAsynchronously) } | ||
| } | ||
|
|
||
| package var rendersFirstFrameAsynchronously: Bool { | ||
| get { flags.contains(.rendersFirstFrameAsync) } | ||
| set { flags.setValue(newValue, for: .rendersFirstFrameAsync) } | ||
| } | ||
|
|
||
| package var prefersDisplayCompositing: Bool { | ||
| get { flags.contains(.prefersDisplayCompositing) } | ||
| set { flags.setValue(newValue, for: .prefersDisplayCompositing) } | ||
| } | ||
|
|
||
| package var allowsPackedDrawable: Bool { | ||
| get { flags.contains(.allowsPackedDrawable) } | ||
| set { flags.setValue(newValue, for: .allowsPackedDrawable) } | ||
| } | ||
|
|
||
| package var resolvedColorMode: RBColorMode { | ||
| _openSwiftUIUnimplementedFailure() | ||
| } | ||
|
|
||
| package var colorSpace: RBColorSpace { | ||
| _openSwiftUIUnimplementedFailure() | ||
| } | ||
|
|
||
| package var alphaOnly: Bool { | ||
| get { flags.contains(.alphaOnly) } | ||
| set { flags.setValue(newValue, for: .alphaOnly) } | ||
| } | ||
|
|
||
| package var requiresLayer: Bool { | ||
| get { flags.contains(.requiresLayer) } | ||
| set { flags.setValue(newValue, for: .requiresLayer) } | ||
| } | ||
| } | ||
|
|
||
| extension RasterizationOptions: ProtobufMessage { | ||
| package func encode(to encoder: inout ProtobufEncoder) { | ||
| encoder.enumField(1, colorMode, defaultValue: .nonLinear) | ||
| if let rbColorMode { | ||
| encoder.intField(2, Int(rbColorMode)) | ||
| } | ||
| encoder.intField(3, Int(flags.rawValue)) | ||
| encoder.intField(4, Int(maxDrawableCount)) | ||
| } | ||
|
|
||
| package init(from decoder: inout ProtobufDecoder) throws { | ||
| var options = RasterizationOptions() | ||
| while let field = try decoder.nextField() { | ||
| switch field.tag { | ||
| case 1: options.colorMode = try decoder.enumField(field) ?? .nonLinear | ||
| case 2: options.rbColorMode = Int32(try decoder.intField(field)) | ||
| case 3: options.flags = Flags(rawValue: UInt32(try decoder.intField(field))) | ||
| case 4: options.maxDrawableCount = Int8(try decoder.intField(field)) | ||
|
Comment on lines
+171
to
+173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 🤖 Was this useful? React with 👍 or 👎 |
||
| default: try decoder.skipField(field) | ||
| } | ||
| } | ||
| self = options | ||
| } | ||
| } | ||
|
|
||
| // TODO: DrawingGroupEffect | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PlatformDrawableContent.Stateispublicbut its initializers arepackage, andPlatformDrawableContent.draw(...)requires an inoutState; SPI clients outside this package may have no way to create/retain aState. Ifdrawis intended for externalPlatformDrawableimplementers, it likely needs a constructible state type.🤖 Was this useful? React with 👍 or 👎