--- /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 <sal/log.hxx>
+
 #import <Cocoa/Cocoa.h>
 #import <QuartzCore/CAConstraintLayoutManager.h>
 
@@ -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
