Use a top-down DIB for the surface instead of a bottom-up DIB. This seems to match better with how Core Graphics expects to receive image data, and allows us to avoid a transform to flip the surface image. Unfortunately, it requires us to use a transform to flip the image in the -drawRect: path. We'll be getting rid of that in the next patch, though.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/winemac.drv/cocoa_window.m | 86 ++++++++++++++++++++++++++------- dlls/winemac.drv/macdrv_cocoa.h | 3 +- dlls/winemac.drv/surface.c | 42 +++++++++++----- 3 files changed, 101 insertions(+), 30 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 3eb8ec20877..75fc26bbcf8 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -491,6 +491,54 @@ - (BOOL) isFlipped return YES; }
+ - (BOOL) wantsUpdateLayer + { + return YES /*!_everHadGLContext*/; + } + + - (void) updateLayer + { + WineWindow* window = (WineWindow*)[self window]; + CGImageRef image = NULL; + CGRect imageRect; + CALayer* layer = [self layer]; + + if ([window contentView] != self) + return; + + if (!window.surface || !window.surface_mutex) + return; + + pthread_mutex_lock(window.surface_mutex); + if (get_surface_blit_rects(window.surface, NULL, NULL)) + { + imageRect = layer.bounds; + imageRect.origin.x *= layer.contentsScale; + imageRect.origin.y *= layer.contentsScale; + imageRect.size.width *= layer.contentsScale; + imageRect.size.height *= layer.contentsScale; + image = create_surface_image(window.surface, &imageRect, FALSE, window.colorKeyed, + window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue); + } + pthread_mutex_unlock(window.surface_mutex); + + if (image) + { + layer.contents = (id)image; + CFRelease(image); + [window windowDidDrawContent]; + + // If the window may be transparent, then we have to invalidate the + // shadow every time we draw. Also, if this is the first time we've + // drawn since changing from transparent to opaque. + if (window.colorKeyed || window.usePerPixelAlpha || window.shapeChangedSinceLastDraw) + { + window.shapeChangedSinceLastDraw = FALSE; + [window invalidateShadow]; + } + } + } + - (void) viewWillDraw { [super viewWillDraw]; @@ -521,12 +569,17 @@ - (void) drawRect:(NSRect)rect const CGRect* rects; int count;
- if (get_surface_blit_rects(window.surface, &rects, &count) && count) + if (get_surface_blit_rects(window.surface, &rects, &count)) { CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect)); + NSAffineTransform* xform = [NSAffineTransform transform]; CGContextRef context; int i;
+ [xform translateXBy:0.0 yBy:self.bounds.size.height]; + [xform scaleXBy:1.0 yBy:-1.0]; + [xform concat]; + context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextSetBlendMode(context, kCGBlendModeCopy); CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone); @@ -537,25 +590,15 @@ - (void) drawRect:(NSRect)rect CGImageRef image;
imageRect = CGRectIntersection(rects[i], dirtyRect); - image = create_surface_image(window.surface, &imageRect, FALSE); + image = create_surface_image(window.surface, &imageRect, FALSE, window.colorKeyed, + window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue);
if (image) { - if (window.colorKeyed) - { - CGImageRef maskedImage; - CGFloat components[] = { window.colorKeyRed - 0.5, window.colorKeyRed + 0.5, - window.colorKeyGreen - 0.5, window.colorKeyGreen + 0.5, - window.colorKeyBlue - 0.5, window.colorKeyBlue + 0.5 }; - maskedImage = CGImageCreateWithMaskingColors(image, components); - if (maskedImage) - { - CGImageRelease(image); - image = maskedImage; - } - } - - CGContextDrawImage(context, cgrect_mac_from_win(imageRect), image); + // Account for the flipped coordinate system. + imageRect = cgrect_mac_from_win(imageRect); + imageRect.origin.y = self.bounds.size.height - imageRect.origin.y - imageRect.size.height; + CGContextDrawImage(context, imageRect, image);
CGImageRelease(image); } @@ -708,6 +751,9 @@ - (void) setRetinaMode:(int)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; [super setRetinaMode:mode]; }
@@ -1028,6 +1074,9 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w 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 @@ -3599,6 +3648,9 @@ macdrv_view macdrv_create_view(CGRect rect)
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]; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index b02ad79f025..47ae6627b9f 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -566,7 +566,8 @@ extern void macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, extern void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame) DECLSPEC_HIDDEN; extern void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent) DECLSPEC_HIDDEN; extern void macdrv_set_window_surface(macdrv_window w, void *surface, pthread_mutex_t *mutex) DECLSPEC_HIDDEN; -extern CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) DECLSPEC_HIDDEN; +extern CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data, int color_keyed, + CGFloat key_red, CGFloat key_green, CGFloat key_blue) DECLSPEC_HIDDEN; extern int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *count) DECLSPEC_HIDDEN; extern void macdrv_window_needs_display(macdrv_window w, CGRect rect) DECLSPEC_HIDDEN; extern void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 7be1b6850e0..6a5cd535923 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -264,7 +264,7 @@ struct window_surface *create_surface(macdrv_window window, const RECT *rect,
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; - surface->info.bmiHeader.biHeight = height; /* bottom-up */ + surface->info.bmiHeader.biHeight = -height; /* top-down */ surface->info.bmiHeader.biPlanes = 1; surface->info.bmiHeader.biBitCount = 32; surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info); @@ -342,18 +342,21 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun { struct macdrv_window_surface *surface = get_mac_surface(window_surface);
- if (surface->blit_data) + if (rects && count) { - *rects = (const CGRect*)surface->blit_data->Buffer; - *count = surface->blit_data->rdh.nCount; - } - else - { - *rects = NULL; - *count = 0; + if (surface->blit_data) + { + *rects = (const CGRect*)surface->blit_data->Buffer; + *count = surface->blit_data->rdh.nCount; + } + else + { + *rects = NULL; + *count = 0; + } }
- return (surface->blit_data != NULL); + return (surface->blit_data != NULL && surface->blit_data->rdh.nCount > 0); }
/*********************************************************************** @@ -371,7 +374,8 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun * must not use Win32 or Wine functions, including debug * logging. */ -CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) +CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data, int color_keyed, + CGFloat key_red, CGFloat key_green, CGFloat key_blue) { CGImageRef cgimage = NULL; struct macdrv_window_surface *surface = get_mac_surface(window_surface); @@ -392,7 +396,7 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); bytes_per_row = get_dib_stride(width, 32); - offset = CGRectGetMinX(visrect) * 4 + (height - CGRectGetMaxY(visrect)) * bytes_per_row; + offset = CGRectGetMinX(visrect) * 4 + CGRectGetMinY(visrect) * bytes_per_row; size = min(CGRectGetHeight(visrect) * bytes_per_row, surface->info.bmiHeader.biSizeImage - offset);
@@ -412,6 +416,20 @@ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_dat provider, NULL, retina_on, kCGRenderingIntentDefault); CGDataProviderRelease(provider); CGColorSpaceRelease(colorspace); + + if (color_keyed) + { + CGImageRef maskedImage; + CGFloat components[] = { key_red - 0.5, key_red + 0.5, + key_green - 0.5, key_green + 0.5, + key_blue - 0.5, key_blue + 0.5 }; + maskedImage = CGImageCreateWithMaskingColors(cgimage, components); + if (maskedImage) + { + CGImageRelease(cgimage); + cgimage = maskedImage; + } + } }
return cgimage;