diff options
author | Nils Petter Skålerud <[email protected]> | 2025-05-28 15:45:03 +0200 |
---|---|---|
committer | Nils Petter Skålerud <[email protected]> | 2025-06-04 02:37:47 +0200 |
commit | cb09be1512e5f932af1744773a7638f23ebd57f9 (patch) | |
tree | ad493468fe7310bc65d76e237bb85f0e339bf895 | |
parent | e67c4c986ffaeb98c1ccb52b689e7a8b37eb6672 (diff) |
Currently the QIOSScreen::grabWindow implementaton relies on
UIGraphicsBeginImageContextWithOptions to do a screenshot. This API
is deprecated and produces a few warnings logs that we can't silence
even when we handle the errors. The current approach also has a memory
leak when taking screenshots in rapid succession (i.e 60 FPS).
This patch modifies grabWindow() to use UIGraphicsImageRenderer, which
replaces the deprecated API. This no longer produces warning logs when
errors are handled. This API can be used in the future to let us take
HDR screenshots once Qt has support for this. This patch solves the
mentioned memory leak.
Pick-to: 6.10 6.9 6.8
Change-Id: Ifbc8503482886246ce9611d0b7a19462fc830ecd
Reviewed-by: Tim Blechmann <[email protected]>
-rw-r--r-- | src/plugins/platforms/ios/qiosscreen.mm | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 1e0d074330a..ad735266e03 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -428,19 +428,33 @@ QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height) CGRect captureRect = [view.window convertRect:CGRectMake(x, y, width, height) fromView:view]; captureRect = CGRectIntersection(captureRect, view.window.bounds); - UIGraphicsBeginImageContextWithOptions(captureRect.size, NO, 0.0); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); - - // Draws the complete view hierarchy of view.window into the given rect, which - // needs to be the same aspect ratio as the view.window's size. Since we've - // translated the graphics context, and are potentially drawing into a smaller - // context than the full window, the resulting image will be a subsection of the - // full screen. - [view.window drawViewHierarchyInRect:view.window.bounds afterScreenUpdates:NO]; - - UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); + QMacAutoReleasePool autoReleasePool; + + UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat]; + format.opaque = NO; + format.scale = devicePixelRatio(); + // Could be adjusted to support HDR in the future. + format.preferredRange = UIGraphicsImageRendererFormatRangeStandard; + + UIGraphicsImageRenderer *renderer = [[[UIGraphicsImageRenderer alloc] + initWithSize:captureRect.size format:format] + autorelease]; + + UIImage *screenshot = [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) { + CGContextRef context = rendererContext.CGContext; + CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y); + + // Draws the complete view hierarchy of view.window into the given rect, which + // needs to be the same aspect ratio as the view.window's size. Since we've + // translated the graphics context, and are potentially drawing into a smaller + // context than the full window, the resulting image will be a subsection of the + // full screen. + // + // TODO: Should only be run on the UI thread in the future. At + // the time of writing, QScreen::grabWindow doesn't include any + // requirements as to which thread it can be called from. + [view.window drawViewHierarchyInRect:view.window.bounds afterScreenUpdates:NO]; + }]; return QPixmap::fromImage(qt_mac_toQImage(screenshot.CGImage)); } |