1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

winemac: Push window surface image updates to the main thread.

This commit is contained in:
Rémi Bernon 2024-06-06 08:36:07 +02:00 committed by Alexandre Julliard
parent e7a82cc24b
commit 66051c2aa1
3 changed files with 46 additions and 71 deletions

View File

@ -365,6 +365,8 @@ - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device;
@interface WineContentView : WineBaseView <NSTextInputClient, NSViewLayerContentScaleDelegate>
{
CGImageRef colorImage;
NSMutableArray* glContexts;
NSMutableArray* pendingGlContexts;
BOOL _everHadGLContext;
@ -501,6 +503,7 @@ - (void) dealloc
[markedText release];
[glContexts release];
[pendingGlContexts release];
CGImageRelease(colorImage);
[super dealloc];
}
@ -517,7 +520,7 @@ - (BOOL) wantsUpdateLayer
- (void) updateLayer
{
WineWindow* window = (WineWindow*)[self window];
CGImageRef image = NULL;
CGImageRef image;
CGRect imageRect;
CALayer* layer = [self layer];
@ -532,8 +535,22 @@ - (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);
image = CGImageCreateWithImageInRect(colorImage, 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 +569,12 @@ - (void) updateLayer
}
}
- (void) setColorImage:(CGImageRef)image
{
CGImageRelease(colorImage);
colorImage = CGImageRetain(image);
}
- (void) viewWillDraw
{
[super viewWillDraw];
@ -3493,19 +3516,26 @@ void macdrv_set_window_surface(macdrv_window w, struct window_surface *window_su
}
/***********************************************************************
* macdrv_window_needs_display
* macdrv_window_set_color_image
*
* Mark a window as needing display in a specified rect (in non-client
* Push a window surface color pixel update in a specified rect (in non-client
* area coordinates).
*/
void macdrv_window_needs_display(macdrv_window w, CGRect rect)
void macdrv_window_set_color_image(macdrv_window w, CGImageRef image, CGRect rect, CGRect dirty)
{
@autoreleasepool
{
WineWindow* window = (WineWindow*)w;
CGImageRetain(image);
OnMainThreadAsync(^{
[[window contentView] setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(rect))];
WineContentView *view = [window contentView];
[view setColorImage:image];
[view setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(dirty))];
CGImageRelease(image);
});
}
}

View File

@ -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_set_color_image(macdrv_window w, CGImageRef image, CGRect rect, CGRect dirty);
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,

View File

@ -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 */
};
@ -115,17 +108,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_set_color_image(surface->window, image, cgrect_from_rect(*rect), cgrect_from_rect(*dirty));
CGImageRelease(image);
return TRUE;
}
/***********************************************************************
@ -136,7 +130,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);
}
@ -231,52 +224,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
*