winemac.drv: Set the surface contents directly to the layer.
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. Signed-off-by: Chip Davis <cdavis@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cad2a7c8e1
commit
9e599a89e3
|
@ -491,6 +491,54 @@ - (BOOL) isFlipped
|
||||||
return YES;
|
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
|
- (void) viewWillDraw
|
||||||
{
|
{
|
||||||
[super viewWillDraw];
|
[super viewWillDraw];
|
||||||
|
@ -521,12 +569,17 @@ - (void) drawRect:(NSRect)rect
|
||||||
const CGRect* rects;
|
const CGRect* rects;
|
||||||
int count;
|
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));
|
CGRect dirtyRect = cgrect_win_from_mac(NSRectToCGRect(rect));
|
||||||
|
NSAffineTransform* xform = [NSAffineTransform transform];
|
||||||
CGContextRef context;
|
CGContextRef context;
|
||||||
int i;
|
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];
|
context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
||||||
CGContextSetBlendMode(context, kCGBlendModeCopy);
|
CGContextSetBlendMode(context, kCGBlendModeCopy);
|
||||||
CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
|
CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
|
||||||
|
@ -537,25 +590,15 @@ - (void) drawRect:(NSRect)rect
|
||||||
CGImageRef image;
|
CGImageRef image;
|
||||||
|
|
||||||
imageRect = CGRectIntersection(rects[i], dirtyRect);
|
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 (image)
|
||||||
{
|
{
|
||||||
if (window.colorKeyed)
|
// Account for the flipped coordinate system.
|
||||||
{
|
imageRect = cgrect_mac_from_win(imageRect);
|
||||||
CGImageRef maskedImage;
|
imageRect.origin.y = self.bounds.size.height - imageRect.origin.y - imageRect.size.height;
|
||||||
CGFloat components[] = { window.colorKeyRed - 0.5, window.colorKeyRed + 0.5,
|
CGContextDrawImage(context, imageRect, image);
|
||||||
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);
|
|
||||||
|
|
||||||
CGImageRelease(image);
|
CGImageRelease(image);
|
||||||
}
|
}
|
||||||
|
@ -708,6 +751,9 @@ - (void) setRetinaMode:(int)mode
|
||||||
[self updateGLContexts];
|
[self updateGLContexts];
|
||||||
|
|
||||||
_retinaMode = !!mode;
|
_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];
|
[super setRetinaMode:mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,6 +1074,9 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
||||||
if (!contentView)
|
if (!contentView)
|
||||||
return nil;
|
return nil;
|
||||||
[contentView setWantsLayer:YES];
|
[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];
|
[contentView setAutoresizesSubviews:NO];
|
||||||
|
|
||||||
/* We use tracking areas in addition to setAcceptsMouseMovedEvents:YES
|
/* We use tracking areas in addition to setAcceptsMouseMovedEvents:YES
|
||||||
|
@ -3597,6 +3646,9 @@ macdrv_view macdrv_create_view(CGRect rect)
|
||||||
|
|
||||||
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
|
view = [[WineContentView alloc] initWithFrame:NSRectFromCGRect(cgrect_mac_from_win(rect))];
|
||||||
[view setWantsLayer:YES];
|
[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 setAutoresizesSubviews:NO];
|
||||||
[view setAutoresizingMask:NSViewNotSizable];
|
[view setAutoresizingMask:NSViewNotSizable];
|
||||||
[view setHidden:YES];
|
[view setHidden:YES];
|
||||||
|
|
|
@ -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_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_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 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 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_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;
|
extern void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -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.biSize = sizeof(surface->info.bmiHeader);
|
||||||
surface->info.bmiHeader.biWidth = width;
|
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.biPlanes = 1;
|
||||||
surface->info.bmiHeader.biBitCount = 32;
|
surface->info.bmiHeader.biBitCount = 32;
|
||||||
surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info);
|
surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info);
|
||||||
|
@ -342,6 +342,8 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun
|
||||||
{
|
{
|
||||||
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
|
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
|
||||||
|
|
||||||
|
if (rects && count)
|
||||||
|
{
|
||||||
if (surface->blit_data)
|
if (surface->blit_data)
|
||||||
{
|
{
|
||||||
*rects = (const CGRect*)surface->blit_data->Buffer;
|
*rects = (const CGRect*)surface->blit_data->Buffer;
|
||||||
|
@ -352,8 +354,9 @@ int get_surface_blit_rects(void *window_surface, const CGRect **rects, int *coun
|
||||||
*rects = NULL;
|
*rects = NULL;
|
||||||
*count = 0;
|
*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
|
* must not use Win32 or Wine functions, including debug
|
||||||
* logging.
|
* 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;
|
CGImageRef cgimage = NULL;
|
||||||
struct macdrv_window_surface *surface = get_mac_surface(window_surface);
|
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);
|
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
|
||||||
bytes_per_row = get_dib_stride(width, 32);
|
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,
|
size = min(CGRectGetHeight(visrect) * bytes_per_row,
|
||||||
surface->info.bmiHeader.biSizeImage - offset);
|
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);
|
provider, NULL, retina_on, kCGRenderingIntentDefault);
|
||||||
CGDataProviderRelease(provider);
|
CGDataProviderRelease(provider);
|
||||||
CGColorSpaceRelease(colorspace);
|
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;
|
return cgimage;
|
||||||
|
|
Loading…
Reference in New Issue