From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 40 +++++++++++++++++-- dlls/winemac.drv/macdrv_cocoa.h | 4 +- dlls/winemac.drv/surface.c | 69 ++++----------------------------- 3 files changed, 45 insertions(+), 68 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 34c39bb3d76..513ceca576d 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -365,6 +365,8 @@ - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device;
@interface WineContentView : WineBaseView <NSTextInputClient, NSViewLayerContentScaleDelegate> { + CGImageRef _surfaceContents; + NSMutableArray* glContexts; NSMutableArray* pendingGlContexts; BOOL _everHadGLContext; @@ -380,6 +382,7 @@ @interface WineContentView : WineBaseView <NSTextInputClient, NSViewLayerContent WineMetalView *_metalView; }
+@property (retain, nonatomic) CGImageRef surfaceContents __attribute__((NSObject)); @property (readonly, nonatomic) BOOL everHadGLContext;
- (void) addGLContext:(WineOpenGLContext*)context; @@ -391,6 +394,7 @@ - (void) wine_setBackingSize:(const int*)newBackingSize;
- (WineMetalView*) newMetalViewWithDevice:(id<MTLDevice>)device;
+ - (void) updateSurfaceContents:(CGRect)frame contents:(CGImageRef)contents; @end
@@ -483,6 +487,7 @@ - (NSFocusRingType) focusRingType @implementation WineContentView
@synthesize everHadGLContext = _everHadGLContext; +@synthesize surfaceContents = _surfaceContents;
- (instancetype) initWithFrame:(NSRect)frame { @@ -498,6 +503,7 @@ - (instancetype) initWithFrame:(NSRect)frame
- (void) dealloc { + self.surfaceContents = nil; [markedText release]; [glContexts release]; [pendingGlContexts release]; @@ -532,8 +538,25 @@ - (void) updateLayer imageRect.origin.y *= layer.contentsScale; imageRect.size.width *= layer.contentsScale; imageRect.size.height *= layer.contentsScale; - image = macdrv_get_surface_display_image(window.surface, &imageRect, window.colorKeyed, - window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue); + + if (self.surfaceContents) + { + image = CGImageCreateWithImageInRect(self.surfaceContents, imageRect); + + 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; + } + } + }
if (image) { @@ -552,6 +575,12 @@ - (void) updateLayer } }
+ - (void) updateSurfaceContents:(CGRect)frame contents:(CGImageRef)contents + { + self.surfaceContents = contents; + [self setNeedsDisplayInRect:NSRectFromCGRect(frame)]; + } + - (void) viewWillDraw { [super viewWillDraw]; @@ -3498,14 +3527,17 @@ void macdrv_set_window_surface(macdrv_window w, struct window_surface *window_su * Mark a window as needing display in a specified rect (in non-client * area coordinates). */ -void macdrv_window_needs_display(macdrv_window w, CGRect rect) +void macdrv_window_display_image(macdrv_window w, CGRect rect, CGImageRef image) { @autoreleasepool { WineWindow* window = (WineWindow*)w;
+ CGImageRetain(image); + OnMainThreadAsync(^{ - [[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(rect))]; + [[window contentView] updateSurfaceContents:cgrect_mac_from_win(rect) contents:image]; + CGImageRelease(image); }); } } diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index bdc7d9980e1..4e1901a5185 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -553,9 +553,7 @@ 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); extern void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent); extern void macdrv_set_window_surface(macdrv_window w, struct window_surface *window_surface); -extern CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surface, CGRect *rect, int color_keyed, - CGFloat key_red, CGFloat key_green, CGFloat key_blue); -extern void macdrv_window_needs_display(macdrv_window w, CGRect rect); +extern void macdrv_window_display_image(macdrv_window w, CGRect rect, CGImageRef image); extern void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count); extern void macdrv_set_window_alpha(macdrv_window w, CGFloat alpha); extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat keyGreen, diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index edaf8b6ea62..7070d4654af 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -53,12 +53,6 @@ static inline int get_dib_image_size(const BITMAPINFO *info) * abs(info->bmiHeader.biHeight); }
-static inline void reset_bounds(RECT *bounds) -{ - bounds->left = bounds->top = INT_MAX; - bounds->right = bounds->bottom = INT_MIN; -} -
struct macdrv_window_surface { @@ -66,7 +60,6 @@ struct macdrv_window_surface macdrv_window window; BOOL use_alpha; CGDataProviderRef provider; - CGImageRef color_image; BITMAPINFO info; /* variable size, must be last */ };
@@ -119,17 +112,18 @@ static BOOL macdrv_surface_flush(struct window_surface *window_surface, const RE CGImageAlphaInfo alpha_info = (surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst); BITMAPINFO *color_info = &surface->info; CGColorSpaceRef colorspace; - - if (surface->color_image) CGImageRelease(surface->color_image); + CGImageRef image;
colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - surface->color_image = CGImageCreate(color_info->bmiHeader.biWidth, abs(color_info->bmiHeader.biHeight), 8, 32, - color_info->bmiHeader.biSizeImage / abs(color_info->bmiHeader.biHeight), colorspace, - alpha_info | kCGBitmapByteOrder32Little, surface->provider, NULL, retina_on, kCGRenderingIntentDefault); + image = CGImageCreate(color_info->bmiHeader.biWidth, abs(color_info->bmiHeader.biHeight), 8, 32, + color_info->bmiHeader.biSizeImage / abs(color_info->bmiHeader.biHeight), colorspace, + alpha_info | kCGBitmapByteOrder32Little, surface->provider, NULL, retina_on, kCGRenderingIntentDefault); CGColorSpaceRelease(colorspace);
- macdrv_window_needs_display(surface->window, cgrect_from_rect(*dirty)); - return FALSE; /* bounds are reset asynchronously, from macdrv_get_surface_display_image */ + macdrv_window_display_image(surface->window, cgrect_from_rect(*dirty), image); + CGImageRelease(image); + + return TRUE; }
/*********************************************************************** @@ -140,7 +134,6 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) struct macdrv_window_surface *surface = get_mac_surface(window_surface);
TRACE("freeing %p\n", surface); - if (surface->color_image) CGImageRelease(surface->color_image); CGDataProviderRelease(surface->provider); free(surface); } @@ -232,52 +225,6 @@ void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha if (surface) surface->use_alpha = use_alpha; }
-/*********************************************************************** - * create_surface_image - * - * Caller must hold the surface lock. On input, *rect is the requested - * image rect, relative to the window whole_rect, a.k.a. visible_rect. - * On output, it's been intersected with that part backed by the surface - * and is the actual size of the returned image. copy_data indicates if - * the caller will keep the returned image beyond the point where the - * surface bits can be guaranteed to remain valid and unchanged. If so, - * the bits are copied instead of merely referenced by the image. - * - * IMPORTANT: This function is called from non-Wine threads, so it - * must not use Win32 or Wine functions, including debug - * logging. - */ -CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surface, CGRect *rect, 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); - - pthread_mutex_lock(&window_surface->mutex); - if (surface->color_image && !IsRectEmpty(&window_surface->bounds)) - { - cgimage = CGImageCreateWithImageInRect(surface->color_image, *rect); - - 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; - } - } - } - - reset_bounds(&window_surface->bounds); - pthread_mutex_unlock(&window_surface->mutex); - return cgimage; -} - /*********************************************************************** * surface_clip_to_visible_rect *