cd983f0af4
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. Change-Id: I03bda5f0d40b84606b6602961e5f0d3b0dfcc6ba Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177921 Tested-by: Jenkins Reviewed-by: Patrick Luby <guibomacdev@gmail.com>
145 lines
5.3 KiB
Groff
145 lines
5.3 KiB
Groff
--- /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
|