Skip to content

Commit

Permalink
Initial upload
Browse files Browse the repository at this point in the history
  • Loading branch information
starkdmi committed Mar 28, 2023
1 parent 6404876 commit 86195df
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 31 deletions.
38 changes: 20 additions & 18 deletions BrightXDR.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
objects = {

/* Begin PBXBuildFile section */
1DCF1F4F29D2FABA005D14C3 /* BrightXDRApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DCF1F4E29D2FABA005D14C3 /* BrightXDRApp.swift */; };
1DCF1F4F29D2FABA005D14C3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DCF1F4E29D2FABA005D14C3 /* App.swift */; };
1DCF1F5129D2FABA005D14C3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DCF1F5029D2FABA005D14C3 /* ContentView.swift */; };
1DCF1F5329D2FABB005D14C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1DCF1F5229D2FABB005D14C3 /* Assets.xcassets */; };
1DCF1F5629D2FABB005D14C3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1DCF1F5529D2FABB005D14C3 /* Preview Assets.xcassets */; };
1DCF1F5E29D2FBB5005D14C3 /* TransparentWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DCF1F5D29D2FBB5005D14C3 /* TransparentWindow.swift */; };
1DCF1F6029D2FBD9005D14C3 /* MetalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DCF1F5F29D2FBD9005D14C3 /* MetalView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
1DCF1F4B29D2FABA005D14C3 /* BrightXDR.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BrightXDR.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DCF1F4E29D2FABA005D14C3 /* BrightXDRApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightXDRApp.swift; sourceTree = "<group>"; };
1DCF1F4E29D2FABA005D14C3 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
1DCF1F5029D2FABA005D14C3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
1DCF1F5229D2FABB005D14C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
1DCF1F5529D2FABB005D14C3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
1DCF1F5729D2FABB005D14C3 /* BrightXDR.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BrightXDR.entitlements; sourceTree = "<group>"; };
1DCF1F5D29D2FBB5005D14C3 /* TransparentWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransparentWindow.swift; sourceTree = "<group>"; };
1DCF1F5F29D2FBD9005D14C3 /* MetalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetalView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -52,23 +54,16 @@
1DCF1F4D29D2FABA005D14C3 /* BrightXDR */ = {
isa = PBXGroup;
children = (
1DCF1F4E29D2FABA005D14C3 /* BrightXDRApp.swift */,
1DCF1F4E29D2FABA005D14C3 /* App.swift */,
1DCF1F5029D2FABA005D14C3 /* ContentView.swift */,
1DCF1F5F29D2FBD9005D14C3 /* MetalView.swift */,
1DCF1F5D29D2FBB5005D14C3 /* TransparentWindow.swift */,
1DCF1F5229D2FABB005D14C3 /* Assets.xcassets */,
1DCF1F5729D2FABB005D14C3 /* BrightXDR.entitlements */,
1DCF1F5429D2FABB005D14C3 /* Preview Content */,
);
path = BrightXDR;
sourceTree = "<group>";
};
1DCF1F5429D2FABB005D14C3 /* Preview Content */ = {
isa = PBXGroup;
children = (
1DCF1F5529D2FABB005D14C3 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -127,7 +122,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1DCF1F5629D2FABB005D14C3 /* Preview Assets.xcassets in Resources */,
1DCF1F5329D2FABB005D14C3 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -139,8 +133,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1DCF1F6029D2FBD9005D14C3 /* MetalView.swift in Sources */,
1DCF1F5E29D2FBB5005D14C3 /* TransparentWindow.swift in Sources */,
1DCF1F5129D2FABA005D14C3 /* ContentView.swift in Sources */,
1DCF1F4F29D2FABA005D14C3 /* BrightXDRApp.swift in Sources */,
1DCF1F4F29D2FABA005D14C3 /* App.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -269,16 +265,19 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"BrightXDR/Preview Content\"";
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = JV88U38946;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Bright XDR";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.starkdmi.BrightXDR;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -296,16 +295,19 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"BrightXDR/Preview Content\"";
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = JV88U38946;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = "Bright XDR";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.starkdmi.BrightXDR;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
2 changes: 1 addition & 1 deletion BrightXDR/BrightXDRApp.swift → BrightXDR/App.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// BrightXDRApp.swift
// App.swift
// BrightXDR
//
// Created by Dmitry Starkov on 28/03/2023.
Expand Down
43 changes: 37 additions & 6 deletions BrightXDR/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,45 @@
import SwiftUI

struct ContentView: View {
@State var maxEDR: CGFloat = 0.0
@State var maxPotentialEDR: CGFloat = 0.0

var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
ZStack {
TransparentWindow()

HStack {
VStack {
// Current maximum color component value for the screen
// If no content on screen provides extended dynamic range (EDR) values, the value of this property is 1.0.
// If any content onscreen has requested EDR, the value may be greater than 1.0, depending on the capabilities of the display hardware and other conditions.
// Only rendering contexts that support EDR can use values greater than 1.0.
Text("Max EDR: \(String(format: "%.2f", maxEDR))").padding(.top, 8)
Rectangle().fill(.clear).border(Color.white)
}

VStack {
// EDR Headroom ~= Display Peak Brightness / Current SDR Brightness
// SDR equals 100 nit, and peak brightness is 1600 nit --> 16.0x is EDR headroom
// If this property is greater than 1.0, the screen supports EDR values.
// If the screen doesn't support EDR values, the value is 1.0.
Text("Max Potential EDR: \(String(format: "%.2f", maxPotentialEDR))").padding(.top, 8)
MetalView()
//.blendMode(BlendMode.multiply) // implemented via compositingFilter of CAMetalLayer
.border(Color.white)
}
}
.onAppear(perform: reloadStats)
.onReceive(NotificationCenter.default.publisher(for: NSApplication.didChangeScreenParametersNotification), perform: { _ in
reloadStats()
})
}
.padding()
}

private func reloadStats() {
guard let mainScreen = NSScreen.main else { return }
self.maxEDR = mainScreen.maximumExtendedDynamicRangeColorComponentValue
self.maxPotentialEDR = mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue
}
}

Expand Down
93 changes: 93 additions & 0 deletions BrightXDR/MetalView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// MetalView.swift
// BrightXDR
//
// Created by Dmitry Starkov on 28/03/2023.
//

import SwiftUI
import MetalKit

// SwiftUI view displaying static semi-transparent HDR content to enable EDR display mode
struct MetalView: NSViewRepresentable {
func makeNSView(context: Context) -> MTKView {
let view = MTKView(frame: .zero, device: context.coordinator.device)

// Allow the view to display its contents outside of the framebuffer and bind the delegate to the coordinator
view.framebufferOnly = false
view.preferredFramesPerSecond = 1
view.delegate = context.coordinator

// Enable EDR
view.colorPixelFormat = MTLPixelFormat.rgba16Float
view.colorspace = CGColorSpace(name: CGColorSpace.extendedLinearSRGB)
if let layer = view.layer as? CAMetalLayer {
layer.wantsExtendedDynamicRangeContent = true
layer.isOpaque = false

// Blend EDR layer with background
layer.compositingFilter = "multiplyBlendMode" // multiplyBlendMode, overlayBlendMode
}

return view
}

func updateNSView(_ view: MTKView, context: Context) { }

func makeCoordinator() -> Coordinator {
Coordinator()
}

class Coordinator: NSObject, MTKViewDelegate {
let device: MTLDevice? = MTLCreateSystemDefaultDevice()
var rendered: Bool = false

func draw(in view: MTKView) {
guard !rendered else { return }

// Create a command queue
guard let commandQueue = self.device?.makeCommandQueue() else { return }

// Create a new command buffer and get the drawable object to render into
guard let commandBuffer = commandQueue.makeCommandBuffer(), let drawable = view.currentDrawable else { return }

// Get the EDR Headroom ~= Display Peak Brightness / Current SDR Brightness
// If this property is greater than 1.0, the screen supports EDR values
let headroom = NSScreen.main?.maximumPotentialExtendedDynamicRangeColorComponentValue ?? 1.0

// Create a color and an image with EDR support
guard let colorSpace = CGColorSpace(name: CGColorSpace.extendedLinearSRGB),
let color = CIColor(red: headroom, green: headroom, blue: headroom, alpha: 0.5, colorSpace: colorSpace) else {
return
}
let image = CIImage(color: color)

// Create a CIContext for rendering a CIImage to a destination using Metal
let renderContext = CIContext(mtlCommandQueue: commandQueue, options: [
.workingColorSpace: colorSpace,
.workingFormat: CIFormat.RGBAf,
.cacheIntermediates: true,
.allowLowPower: false,
])

// Render the CIImage
renderContext.render(image, to: drawable.texture, commandBuffer: commandBuffer, bounds: CGRect(origin: CGPoint.zero, size: view.drawableSize), colorSpace: colorSpace)

// Present the drawable to the screen
commandBuffer.present(drawable)
// Commit the command buffer for execution on the GPU
commandBuffer.commit()
// Render an image only once
self.rendered = true
}

func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { }
}
}


struct MetalView_Previews: PreviewProvider {
static var previews: some View {
MetalView()
}
}

This file was deleted.

31 changes: 31 additions & 0 deletions BrightXDR/TransparentWindow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// TransparentWindow.swift
// BrightXDR
//
// Created by Dmitry Starkov on 28/03/2023.
//

import SwiftUI

/// AppKit implementation
class TransparentWindowView: NSView {
override func viewDidMoveToWindow() {
window?.backgroundColor = .clear
super.viewDidMoveToWindow()
}
}

/// Transparent view allow overlaying UI elements on top of other windows or the desktop background
struct TransparentWindow: NSViewRepresentable {
func makeNSView(context: Self.Context) -> NSView {
return TransparentWindowView()
}

func updateNSView(_ nsView: NSView, context: Context) { }
}

struct TransparentWindow_Previews: PreviewProvider {
static var previews: some View {
TransparentWindow()
}
}

0 comments on commit 86195df

Please sign in to comment.