Instead of accessing the surface with macdrv_get_surface_display_image.
-- v6: winemac: Clip the surface rectangles to the virtual screen rect. winemac: Remove unnecessary surface_clip_to_visible_rect. winemac: Remove now unnecessary cocoa window surface pointer. winemac: Push window surface image updates to the main thread. winemac: Create window surface CGImageRef on surface flush. winemac: Create a provider for the surface and a HBITMAP wrapping it. winemac: Remove unused macdrv_get_surface_display_image copy_data parameter.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 2 +- dlls/winemac.drv/macdrv_cocoa.h | 2 +- dlls/winemac.drv/surface.c | 12 ++---------- 3 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 61a6ab2cd4e..34c39bb3d76 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -532,7 +532,7 @@ - (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, FALSE, window.colorKeyed, + image = macdrv_get_surface_display_image(window.surface, &imageRect, window.colorKeyed, window.colorKeyRed, window.colorKeyGreen, window.colorKeyBlue);
if (image) diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index ba5803f88dc..bdc7d9980e1 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -553,7 +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 copy_data, int color_keyed, +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_set_window_shape(macdrv_window w, const CGRect *rects, int count); diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 37e2c466926..4e8b3c4824f 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -191,7 +191,7 @@ void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha * must not use Win32 or Wine functions, including debug * logging. */ -CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surface, CGRect *rect, int copy_data, int color_keyed, +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; @@ -220,15 +220,7 @@ CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surfac offset = CGRectGetMinX(visrect) * 4 + CGRectGetMinY(visrect) * bytes_per_row; size = min(CGRectGetHeight(visrect) * bytes_per_row, surface->info.bmiHeader.biSizeImage - offset); - - if (copy_data) - { - CFDataRef data = CFDataCreate(NULL, (UInt8 *)window_surface->color_bits + offset, size); - provider = CGDataProviderCreateWithCFData(data); - CFRelease(data); - } - else - provider = CGDataProviderCreateWithData(NULL, (UInt8 *)window_surface->color_bits + offset, size, NULL); + provider = CGDataProviderCreateWithData(NULL, (UInt8 *)window_surface->color_bits + offset, size, NULL);
alphaInfo = surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect),
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/surface.c | 51 ++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 4e8b3c4824f..634bab369fe 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -65,11 +65,27 @@ struct macdrv_window_surface struct window_surface header; macdrv_window window; BOOL use_alpha; + CGDataProviderRef provider; BITMAPINFO info; /* variable size, must be last */ };
static struct macdrv_window_surface *get_mac_surface(struct window_surface *surface);
+static CGDataProviderRef data_provider_create(size_t size, void **bits) +{ + CGDataProviderRef provider; + CFMutableDataRef data; + + if (!(data = CFDataCreateMutable(kCFAllocatorDefault, size))) return NULL; + CFDataSetLength(data, size); + + if ((provider = CGDataProviderCreateWithCFData(data))) + *bits = CFDataGetMutableBytePtr(data); + CFRelease(data); + + return provider; +} + /*********************************************************************** * macdrv_surface_get_bitmap_info */ @@ -107,6 +123,7 @@ 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); + CGDataProviderRelease(surface->provider); free(surface); }
@@ -130,11 +147,16 @@ static struct macdrv_window_surface *get_mac_surface(struct window_surface *surf struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha) { - struct macdrv_window_surface *surface; + struct macdrv_window_surface *surface = NULL; int width = rect->right - rect->left, height = rect->bottom - rect->top; DWORD window_background; + D3DKMT_CREATEDCFROMMEMORY desc = {.Format = D3DDDIFMT_A8R8G8B8}; char buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; BITMAPINFO *info = (BITMAPINFO *)buffer; + CGDataProviderRef provider; + HBITMAP bitmap = 0; + UINT status; + void *bits;
memset(info, 0, sizeof(*info)); info->bmiHeader.biSize = sizeof(info->bmiHeader); @@ -145,14 +167,31 @@ struct window_surface *create_surface(HWND hwnd, macdrv_window window, const REC info->bmiHeader.biSizeImage = get_dib_image_size(info); info->bmiHeader.biCompression = BI_RGB;
- surface = calloc(1, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])); - if (!surface) return NULL; - if (!window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, rect, info, 0)) goto failed; + if (!(provider = data_provider_create(info->bmiHeader.biSizeImage, &bits))) return NULL; + + /* wrap the data in a HBITMAP so we can write to the surface pixels directly */ + desc.Width = info->bmiHeader.biWidth; + desc.Height = abs(info->bmiHeader.biHeight); + desc.Pitch = info->bmiHeader.biSizeImage / abs(info->bmiHeader.biHeight); + desc.pMemory = bits; + desc.hDeviceDc = NtUserGetDCEx(hwnd, 0, DCX_CACHE | DCX_WINDOW); + if ((status = NtGdiDdDDICreateDCFromMemory(&desc))) + ERR("Failed to create HBITMAP, status %#x\n", status); + else + { + bitmap = desc.hBitmap; + NtGdiDeleteObjectApp(desc.hDc); + } + if (desc.hDeviceDc) NtUserReleaseDC(hwnd, desc.hDeviceDc); + + if (!(surface = calloc(1, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])))) goto failed; + if (!window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, rect, info, bitmap)) goto failed; memcpy(&surface->info, info, offsetof(BITMAPINFO, bmiColors[3]));
surface->window = window; if (old_surface) surface->header.bounds = old_surface->bounds; surface->use_alpha = use_alpha; + surface->provider = provider;
window_background = macdrv_window_background_color(); memset_pattern4(surface->header.color_bits, &window_background, info->bmiHeader.biSizeImage); @@ -163,7 +202,9 @@ struct window_surface *create_surface(HWND hwnd, macdrv_window window, const REC return &surface->header;
failed: - window_surface_release(&surface->header); + if (surface) window_surface_release(&surface->header); + if (bitmap) NtGdiDeleteObjectApp(bitmap); + CGDataProviderRelease(provider); return NULL; }
From: Rémi Bernon rbernon@codeweavers.com
Avoid accessing the surface color bits field from macdrv_get_surface_display_image. --- dlls/winemac.drv/surface.c | 47 +++++++++++++------------------------- 1 file changed, 16 insertions(+), 31 deletions(-)
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 634bab369fe..4a20778761f 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -66,6 +66,7 @@ struct macdrv_window_surface macdrv_window window; BOOL use_alpha; CGDataProviderRef provider; + CGImageRef color_image; BITMAPINFO info; /* variable size, must be last */ };
@@ -111,6 +112,18 @@ static void macdrv_surface_set_clip(struct window_surface *window_surface, const static BOOL macdrv_surface_flush(struct window_surface *window_surface, const RECT *rect, const RECT *dirty) { struct macdrv_window_surface *surface = get_mac_surface(window_surface); + CGImageAlphaInfo alpha_info = (surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst); + BITMAPINFO *color_info = &surface->info; + CGColorSpaceRef colorspace; + + if (surface->color_image) CGImageRelease(surface->color_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); + CGColorSpaceRelease(colorspace); + macdrv_window_needs_display(surface->window, cgrect_from_rect(*dirty)); return FALSE; /* bounds are reset asynchronously, from macdrv_get_surface_display_image */ } @@ -123,6 +136,7 @@ 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); } @@ -237,39 +251,11 @@ CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surfac { CGImageRef cgimage = NULL; struct macdrv_window_surface *surface = get_mac_surface(window_surface); - RECT surface_rect = window_surface->rect; - int width, height;
pthread_mutex_lock(&window_surface->mutex); - if (IsRectEmpty(&window_surface->bounds)) goto done; - - width = surface_rect.right - surface_rect.left; - height = surface_rect.bottom - surface_rect.top; - *rect = CGRectIntersection(cgrect_from_rect(surface_rect), *rect); - if (!CGRectIsEmpty(*rect)) + if (surface->color_image && !IsRectEmpty(&window_surface->bounds)) { - CGRect visrect; - CGColorSpaceRef colorspace; - CGDataProviderRef provider; - int bytes_per_row, offset, size; - CGImageAlphaInfo alphaInfo; - - visrect = CGRectOffset(*rect, -surface_rect.left, -surface_rect.top); - - colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - bytes_per_row = get_dib_stride(width, 32); - offset = CGRectGetMinX(visrect) * 4 + CGRectGetMinY(visrect) * bytes_per_row; - size = min(CGRectGetHeight(visrect) * bytes_per_row, - surface->info.bmiHeader.biSizeImage - offset); - provider = CGDataProviderCreateWithData(NULL, (UInt8 *)window_surface->color_bits + offset, size, NULL); - - alphaInfo = surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; - cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), - 8, 32, bytes_per_row, colorspace, - alphaInfo | kCGBitmapByteOrder32Little, - provider, NULL, retina_on, kCGRenderingIntentDefault); - CGDataProviderRelease(provider); - CGColorSpaceRelease(colorspace); + cgimage = CGImageCreateWithImageInRect(surface->color_image, *rect);
if (color_keyed) { @@ -286,7 +272,6 @@ CGImageRef macdrv_get_surface_display_image(struct window_surface *window_surfac } }
-done: reset_bounds(&window_surface->bounds); pthread_mutex_unlock(&window_surface->mutex); return cgimage;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 44 +++++++++++++++++---- dlls/winemac.drv/macdrv_cocoa.h | 4 +- dlls/winemac.drv/surface.c | 69 ++++----------------------------- 3 files changed, 46 insertions(+), 71 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 34c39bb3d76..d211823cd1d 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 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); + CGImageRetain((colorImage = 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); }); } } diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index bdc7d9980e1..31159ab060d 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_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, diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 4a20778761f..b9287b6ec1b 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 */ };
@@ -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 *
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/cocoa_window.h | 3 --- dlls/winemac.drv/cocoa_window.m | 19 +------------------ dlls/winemac.drv/macdrv_cocoa.h | 1 - dlls/winemac.drv/window.c | 2 -- 4 files changed, 1 insertion(+), 24 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 9539e4ebdd7..b5168d0c128 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -44,9 +44,6 @@ @interface WineWindow : NSPanel <NSWindowDelegate> void* hwnd; WineEventQueue* queue;
- void* surface; - pthread_mutex_t* surface_mutex; - CGDirectDisplayID _lastDisplayID; NSTimeInterval _lastDisplayTime;
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index d211823cd1d..b209324c7c7 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -410,8 +410,6 @@ @interface WineWindow () @property (nonatomic) void* hwnd; @property (retain, readwrite, nonatomic) WineEventQueue* queue;
-@property (nonatomic) void* surface; - @property (nonatomic) BOOL shapeChangedSinceLastDraw; @property (readonly, nonatomic) BOOL needsTransparency;
@@ -527,7 +525,7 @@ - (void) updateLayer if ([window contentView] != self) return;
- if (window.closing || !window.surface) + if (window.closing) return;
imageRect = layer.bounds; @@ -1021,7 +1019,6 @@ @implementation WineWindow
@synthesize disabled, noForeground, preventsAppActivation, floating, fullscreen, fakingClose, closing, latentParentWindow, hwnd, queue; @synthesize drawnSinceShown; - @synthesize surface; @synthesize shapeChangedSinceLastDraw; @synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue; @synthesize usePerPixelAlpha; @@ -3500,20 +3497,6 @@ void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent) }); }
-/*********************************************************************** - * macdrv_set_window_surface - */ -void macdrv_set_window_surface(macdrv_window w, struct window_surface *window_surface) -{ -@autoreleasepool -{ - WineWindow* window = (WineWindow*)w; - - OnMainThread(^{ - window.surface = window_surface; - }); -} -}
/*********************************************************************** * macdrv_window_set_color_image diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 31159ab060d..30ab06c3662 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -552,7 +552,6 @@ extern void macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, extern void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame); 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 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); diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 012189249a4..f3de7f13333 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1912,7 +1912,6 @@ BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *window_rect, COLORREF col if (!surface || !EqualRect(&surface->rect, &rect)) { data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE); - macdrv_set_window_surface(data->cocoa_window, data->surface); if (surface) window_surface_release(surface); surface = data->surface; if (data->unminimized_surface) @@ -2102,7 +2101,6 @@ void macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, } else { - macdrv_set_window_surface(data->cocoa_window, surface); if (data->unminimized_surface) { window_surface_release(data->unminimized_surface);
From: Rémi Bernon rbernon@codeweavers.com
The surface bounds aren't used anyway and surface images are cropped to the UI layer extends, regardless of the dirty area. --- dlls/winemac.drv/macdrv.h | 1 - dlls/winemac.drv/surface.c | 19 ------------------- dlls/winemac.drv/window.c | 1 - 3 files changed, 21 deletions(-)
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 31835164e71..39f48f85ee2 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -210,7 +210,6 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p extern struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha); extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha); -extern void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect);
extern void macdrv_handle_event(const macdrv_event *event);
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index b9287b6ec1b..db4392b69c1 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -223,22 +223,3 @@ void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha struct macdrv_window_surface *surface = get_mac_surface(window_surface); if (surface) surface->use_alpha = use_alpha; } - -/*********************************************************************** - * surface_clip_to_visible_rect - * - * Intersect the accumulated drawn region with a new visible rect, - * effectively discarding stale drawing in the surface slack area. - */ -void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect) -{ - struct macdrv_window_surface *surface = get_mac_surface(window_surface); - RECT rect = *visible_rect; - OffsetRect(&rect, -rect.left, -rect.top); - - if (!surface) return; - - window_surface_lock(window_surface); - intersect_rect(&window_surface->bounds, &window_surface->bounds, &rect); - window_surface_unlock(window_surface); -} diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index f3de7f13333..8fb207a8684 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -2049,7 +2049,6 @@ BOOL macdrv_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_r if (EqualRect(&data->surface->rect, &surface_rect)) { /* existing surface is good enough */ - surface_clip_to_visible_rect(data->surface, visible_rect); window_surface_add_ref(data->surface); *surface = data->surface; goto done;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/cocoa_window.m | 9 +++++++++ dlls/winemac.drv/window.c | 22 +++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index b209324c7c7..8967a94521d 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -365,6 +365,7 @@ - (id) initWithFrame:(NSRect)frame device:(id<MTLDevice>)device;
@interface WineContentView : WineBaseView <NSTextInputClient, NSViewLayerContentScaleDelegate> { + CGRect surfaceRect; CGImageRef colorImage;
NSMutableArray* glContexts; @@ -489,6 +490,7 @@ - (instancetype) initWithFrame:(NSRect)frame self = [super initWithFrame:frame]; if (self) { + [self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft]; [self setWantsLayer:YES]; [self setLayerRetinaProperties:retina_on]; [self setAutoresizesSubviews:NO]; @@ -552,6 +554,7 @@ - (void) updateLayer
if (image) { + layer.position = surfaceRect.origin; layer.contents = (id)image; CFRelease(image); [window windowDidDrawContent]; @@ -567,6 +570,11 @@ - (void) updateLayer } }
+ - (void) setSurfaceRect:(CGRect)rect + { + surfaceRect = rect; + } + - (void) setColorImage:(CGImageRef)image { CGImageRelease(colorImage); @@ -3516,6 +3524,7 @@ void macdrv_window_set_color_image(macdrv_window w, CGImageRef image, CGRect rec WineContentView *view = [window contentView];
[view setColorImage:image]; + [view setSurfaceRect:cgrect_mac_from_win(rect)]; [view setNeedsDisplayInRect:NSRectFromCGRect(cgrect_mac_from_win(dirty))];
CGImageRelease(image); diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 8fb207a8684..fc7a6ac2fc1 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1983,16 +1983,18 @@ LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) }
-static inline RECT get_surface_rect(const RECT *visible_rect) +static BOOL get_surface_rect( const RECT *visible_rect, RECT *surface_rect ) { - RECT rect = *visible_rect; + *surface_rect = NtUserGetVirtualScreenRect();
- OffsetRect(&rect, -visible_rect->left, -visible_rect->top); - rect.left &= ~127; - rect.top &= ~127; - rect.right = max(rect.left + 128, (rect.right + 127) & ~127); - rect.bottom = max(rect.top + 128, (rect.bottom + 127) & ~127); - return rect; + if (!intersect_rect( surface_rect, surface_rect, visible_rect )) return FALSE; + OffsetRect( surface_rect, -visible_rect->left, -visible_rect->top ); + surface_rect->left &= ~127; + surface_rect->top &= ~127; + surface_rect->right = max( surface_rect->left + 128, (surface_rect->right + 127) & ~127 ); + surface_rect->bottom = max( surface_rect->top + 128, (surface_rect->bottom + 127) & ~127 ); + + return TRUE; }
@@ -2003,6 +2005,7 @@ BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect { struct macdrv_win_data *data = get_win_data(hwnd); DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE); + RECT surface_rect; BOOL ret = FALSE;
TRACE("%p swp %04x window %s client %s visible %s\n", hwnd, @@ -2018,6 +2021,7 @@ BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect if (!data->cocoa_window) goto done; /* use default surface */ if (swp_flags & SWP_HIDEWINDOW) goto done; /* use default surface */ if (data->ulw_layered) goto done; /* use default surface */ + if (!get_surface_rect( visible_rect, &surface_rect )) goto done; /* use default surface */
ret = TRUE;
@@ -2043,7 +2047,7 @@ BOOL macdrv_CreateWindowSurface(HWND hwnd, UINT swp_flags, const RECT *visible_r if (*surface) window_surface_release(*surface); *surface = NULL;
- surface_rect = get_surface_rect(visible_rect); + if (!get_surface_rect(visible_rect, &surface_rect)) goto done; if (data->surface) { if (EqualRect(&data->surface->rect, &surface_rect))
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146417
Your paranoid android.
=== debian11b (64 bit WoW report) ===
kernel32: comm.c:1574: Test failed: AbortWaitCts hComPortEvent failed comm.c:1586: Test failed: Unexpected time 1001, expected around 500
Rebased and added a change to clip the surface to the virtual screen rectangle, similar to what winex11 and wineandroid are doing. Some applications can create very large windows, and we only need the surface for the visible area. This will make it possible to factor out this behavior in win32u.
Brendan Shanks (@bshanks) commented about dlls/winemac.drv/cocoa_window.m:
} }
- (void) setColorImage:(CGImageRef)image
- {
CGImageRelease(colorImage);
CGImageRetain((colorImage = image));
I think `colorImage = CGImageRetain(image)` or separate statements would be a bit less awkward
On Wed Jun 19 17:37:57 2024 +0000, Rémi Bernon wrote:
Rebased and added a change to clip the surface to the virtual screen rectangle, similar to what winex11 and wineandroid are doing. Some applications can create very large windows, and we only need the surface for the visible area. This will make it possible to factor out this behavior in win32u.
There are various ways that "offscreen" windows are still visible on macOS, and with this they don't display correctly.
If you move a Wine window partially offscreen and then: - use Exposé/Mission Control to view all windows or application windows (ctrl-up/down arrow) - or take a screenshot of the window (cmd-shift-4, then push space and click on the window)
the offscreen part of the window is blank.
!2453 fixed this previously, and `constrain_window_frame()` should be enforcing some sane limits on window sizes