This fixes two issues: - since WineContentView became layer-backed in Wine 6.17, windows do not display correctly on a non-retina monitor when high-res/retina mode is enabled. (The needed downscaling was not being done). - additionally on macOS 10.13 and earlier, the desired minification/downscaling filter was being ignored, causing poor image quality. Enabling rasterization for the layer seems to work around this and uses the correct filter.
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 67e178c8ad3..ad0c97fb6b2 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -685,7 +685,20 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (BOOL) layer:(CALayer*)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow*)window { - return (_retinaMode || newScale == 1.0); + /* This method is invoked when the contentsScale of the layer is not + * equal to the contentsScale of the window. + * (Initially when the layer is first created, and later if the window + * contentsScale changes, i.e. moved between retina/non-retina monitors). + * + * We usually want to return YES, so the "moving windows between + * retina/non-retina monitors" case works right. + * But return NO when we need an intentional mismatch between the + * window and layer contentsScale + * (non-retina mode with a retina monitor, and vice-versa). + */ + if (layer.contentsScale != window.backingScaleFactor) + return NO; + return YES; }
- (void) viewDidHide
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index ad0c97fb6b2..daa7b7e976c 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -359,7 +359,6 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi NSMutableAttributedString* markedText; NSRange markedTextSelection;
- BOOL _retinaMode; int backingSize[2];
WineMetalView *_metalView; @@ -676,7 +675,6 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi [self setWantsBestResolutionOpenGLSurface:mode]; [self updateGLContexts];
- _retinaMode = !!mode; [self layer].contentsScale = mode ? 2.0 : 1.0; [self layer].minificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; [self layer].magnificationFilter = mode ? kCAFilterLinear : kCAFilterNearest;
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index daa7b7e976c..ab9a66f4be2 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -469,6 +469,20 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
@synthesize everHadGLContext = _everHadGLContext;
+ - (instancetype) initWithFrame:(NSRect)frame + { + self = [super initWithFrame:frame]; + if (self) + { + [self setWantsLayer:YES]; + [self layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; + [self layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; + [self layer].contentsScale = retina_on ? 2.0 : 1.0; + [self setAutoresizesSubviews:NO]; + } + return self; + } + - (void) dealloc { [markedText release]; @@ -1006,11 +1020,6 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi contentView = [[[WineContentView alloc] initWithFrame:NSZeroRect] autorelease]; if (!contentView) return nil; - [contentView setWantsLayer:YES]; - [contentView layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [contentView layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [contentView layer].contentsScale = retina_on ? 2.0 : 1.0; - [contentView setAutoresizesSubviews:NO];
/* We use tracking areas in addition to setAcceptsMouseMovedEvents:YES because they give us mouse moves in the background. */ @@ -3600,11 +3609,6 @@ macdrv_view macdrv_create_view(CGRect rect) NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))]; - [view setWantsLayer:YES]; - [view layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [view layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [view layer].contentsScale = retina_on ? 2.0 : 1.0; - [view setAutoresizesSubviews:NO]; [view setAutoresizingMask:NSViewNotSizable]; [view setHidden:YES]; [view setWantsBestResolutionOpenGLSurface:retina_on];
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index ab9a66f4be2..23ac8ca21e4 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -475,9 +475,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi if (self) { [self setWantsLayer:YES]; - [self layer].minificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [self layer].magnificationFilter = retina_on ? kCAFilterLinear : kCAFilterNearest; - [self layer].contentsScale = retina_on ? 2.0 : 1.0; + [self setLayerRetinaProperties:retina_on]; [self setAutoresizesSubviews:NO]; } return self; @@ -677,6 +675,13 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi return _metalView; }
+ - (void) setLayerRetinaProperties:(int)mode + { + [self layer].contentsScale = mode ? 2.0 : 1.0; + [self layer].minificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; + [self layer].magnificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; + } + - (void) setRetinaMode:(int)mode { double scale = mode ? 0.5 : 2.0; @@ -688,10 +693,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi [self setFrame:frame]; [self setWantsBestResolutionOpenGLSurface:mode]; [self updateGLContexts]; + [self setLayerRetinaProperties:mode];
- [self layer].contentsScale = mode ? 2.0 : 1.0; - [self layer].minificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; - [self layer].magnificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; [super setRetinaMode:mode]; }
From: Brendan Shanks bshanks@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 23ac8ca21e4..ac4cc214239 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -680,6 +680,22 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi [self layer].contentsScale = mode ? 2.0 : 1.0; [self layer].minificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; [self layer].magnificationFilter = mode ? kCAFilterLinear : kCAFilterNearest; + + /* On macOS 10.13 and earlier, the desired minificationFilter seems to be + * ignored and "nearest" filtering is used, which looks terrible. + * Enabling rasterization seems to work around this, only enable + * it when there may be down-scaling (retina mode enabled). + */ + if (floor(NSAppKitVersionNumber) < 1671 /*NSAppKitVersionNumber10_14*/) + { + if (mode) + { + [self layer].shouldRasterize = YES; + [self layer].rasterizationScale = 2.0; + } + else + [self layer].shouldRasterize = NO; + } }
- (void) setRetinaMode:(int)mode