--- /dev/null 2023-01-25 09:20:55.000000000 -0500 +++ skia.org/tools/window/mac/WindowContextFactory_mac.mm 2023-01-25 09:21:22.000000000 -0500 @@ -0,0 +1,57 @@ +/* + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "tools/window/mac/MacWindowInfo.h" + +namespace skwindow { + +static bool bWindowScaling = false; +static float fWindowScale = 1.0f; + +CGFloat GetBackingScaleFactor(NSView* view) { + #ifdef SK_BUILD_FOR_IOS + UIScreen* screen = view.window.screen ?: [UIScreen mainScreen]; + return screen.nativeScale; + #else + // Related: tdf#147342 This should always be an exact copy of the + // sal::aqua::getWindowScaling() function in the following file: + // vcl/osx/salgdiutils.cxx + (void)view; + + if (!bWindowScaling) + { + NSArray *aScreens = [NSScreen screens]; + if (aScreens) + { + for (NSScreen *aScreen : aScreens) + { + float fScale = [aScreen backingScaleFactor]; + if (fScale > fWindowScale) + fWindowScale = fScale; + } + bWindowScaling = true; + } + if( const char* env = getenv("SAL_FORCE_HIDPI_SCALING")) + { + fWindowScale = atof(env); + bWindowScaling = true; + } + } + return fWindowScale; + #endif +} + +void ResetBackingScaleFactor() { + #ifndef SK_BUILD_FOR_IOS + // Related: tdf#147342 Force recalculation of the window scaling but keep + // the previous window scaling as the minimum so that we don't lose the + // resolution in cached images if a HiDPI monitor is disconnected and + // then reconnected. + bWindowScaling = false; + GetBackingScaleFactor(nil); + #endif +} + +} // namespace sk_app diff -ur skia.org/tools/window/mac/GaneshMetalWindowContext_mac.mm skia/tools/window/mac/GaneshMetalWindowContext_mac.mm --- skia.org/tools/window/mac/GaneshMetalWindowContext_mac.mm 2024-10-10 13:50:06.102852791 +0200 +++ skia/tools/window/mac/GaneshMetalWindowContext_mac.mm 2024-10-10 13:53:34.821323595 +0200 @@ -11,6 +11,8 @@ #include "tools/window/MetalWindowContext.h" #include "tools/window/mac/MacWindowInfo.h" +#include + #import #import @@ -52,7 +54,23 @@ SkASSERT(nil != fMainView); - fMetalLayer = [CAMetalLayer layer]; + // Related: tdf#152703 Reuse existing CAMetalLayer to stop flicker + // When live resizing a window, replacing the CAMetalLayer with each + // resize event repaints the window's background which causes a + // noticeable flicker. So reuse any existing CAMetalLayer already + // assigned to the native view. + BOOL reuseMetalLayer = NO; + if (fMainView.wantsLayer) + { + CALayer *pLayer = fMainView.layer; + if (pLayer && [pLayer isKindOfClass:[CAMetalLayer class]]) + { + fMetalLayer = (__bridge CAMetalLayer*)pLayer; + reuseMetalLayer = YES; + } + } + if (!reuseMetalLayer) + fMetalLayer = [CAMetalLayer layer]; fMetalLayer.device = fShared->fDevice.get(); fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; @@ -65,10 +83,10 @@ fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable; fMetalLayer.contentsGravity = kCAGravityTopLeft; fMetalLayer.magnificationFilter = kCAFilterNearest; - NSColorSpace* cs = fMainView.window.colorSpace; - fMetalLayer.colorspace = cs.CGColorSpace; + fMetalLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - fMainView.layer = fMetalLayer; + if (!reuseMetalLayer) + fMainView.layer = fMetalLayer; fMainView.wantsLayer = YES; return true; @@ -85,6 +103,18 @@ fMetalLayer.drawableSize = backingSize; fMetalLayer.contentsScale = backingScaleFactor; + // Related: tdf#147342 Copy layer's colorspace to window's colorspace + // This method is now called when the window's backing properties have + // changed so copy any colorspace changes. + fMetalLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + + // Related tdf#145988 Reset layer's pixel format to MTLPixelFormatBGRA8Unorm + // Skia initally sets the layer's pixel format to be BGRA8888 but macOS + // may change the layer's pixel format when a window has moved to a screen + // with 30-bit color depth so reset it back to BGRA8888. + SAL_WARN_IF(fMetalLayer.pixelFormat != MTLPixelFormatBGRA8Unorm, "vcl.skia.metal", "CAMetalLayer pixel format is " << fMetalLayer.pixelFormat << " but should be " << MTLPixelFormatBGRA8Unorm << " (MTLPixelFormatBGRA8Unorm)"); + fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; + fWidth = backingSize.width; fHeight = backingSize.height; } diff -ur skia.org/tools/window/mac/MacWindowInfo.h skia/tools/window/mac/MacWindowInfo.h --- skia.org/tools/window/mac/MacWindowInfo.h 2024-10-10 13:50:06.102852791 +0200 +++ skia/tools/window/mac/MacWindowInfo.h 2024-10-10 13:51:30.227006251 +0200 @@ -22,10 +22,8 @@ NSView* fMainView; }; -static inline CGFloat GetBackingScaleFactor(NSView* view) { - NSScreen* screen = view.window.screen ?: [NSScreen mainScreen]; - return screen.backingScaleFactor; -} +SK_API CGFloat GetBackingScaleFactor(NSView* view); +SK_API void ResetBackingScaleFactor(); } // namespace skwindow