From 61fd8827e17fb22190e260c2091c0460fbecfb05 Mon Sep 17 00:00:00 2001 From: Tom Poole Date: Thu, 4 Aug 2022 11:07:44 +0100 Subject: [PATCH] macOS/iOS: Fix a scaled multiple-rects drawing issue --- .../native/juce_ios_UIViewComponentPeer.mm | 4 +--- .../native/juce_mac_CGMetalLayerRenderer.h | 22 ++++++++----------- .../native/juce_mac_NSViewComponentPeer.mm | 16 ++++++++------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm index 73c1384ded..5336269156 100644 --- a/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm @@ -1391,7 +1391,7 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, int windowStyleFlags, #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS if (@available (iOS 13, *)) - metalRenderer = std::make_unique> (view, comp); + metalRenderer = std::make_unique> (view, comp.isOpaque()); #endif if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0) @@ -1857,8 +1857,6 @@ void UIViewComponentPeer::displayLinkCallback() if (metalRenderer != nullptr) return metalRenderer->drawRectangleList (view, (float) view.contentScaleFactor, - view.frame, - component, [this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); }, deferredRepaints); diff --git a/modules/juce_gui_basics/native/juce_mac_CGMetalLayerRenderer.h b/modules/juce_gui_basics/native/juce_mac_CGMetalLayerRenderer.h index f09f293117..791379c771 100644 --- a/modules/juce_gui_basics/native/juce_mac_CGMetalLayerRenderer.h +++ b/modules/juce_gui_basics/native/juce_mac_CGMetalLayerRenderer.h @@ -35,12 +35,12 @@ class CoreGraphicsMetalLayerRenderer { public: //============================================================================== - CoreGraphicsMetalLayerRenderer (ViewType* view, const Component& comp) + CoreGraphicsMetalLayerRenderer (ViewType* view, bool isOpaque) { device.reset (MTLCreateSystemDefaultDevice()); commandQueue.reset ([device.get() newCommandQueue]); - attach (view, comp); + attach (view, isOpaque); } ~CoreGraphicsMetalLayerRenderer() @@ -52,7 +52,7 @@ public: } } - void attach (ViewType* view, const Component& comp) + void attach (ViewType* view, bool isOpaque) { #if JUCE_MAC view.wantsLayer = YES; @@ -65,7 +65,7 @@ public: layer.device = device.get(); layer.framebufferOnly = NO; layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; - layer.opaque = comp.isOpaque(); + layer.opaque = isOpaque; layer.allowsNextDrawableTimeout = NO; attachedView = view; @@ -90,8 +90,6 @@ public: template bool drawRectangleList (ViewType* view, float scaleFactor, - CGRect viewFrame, - const Component& comp, Callback&& drawRectWithContext, const RectangleList& dirtyRegions) { @@ -117,14 +115,12 @@ public: layer.contentsScale = scaleFactor; const auto drawableSizeTansform = CGAffineTransformMakeScale (layer.contentsScale, layer.contentsScale); - const auto transformedFrameSize = CGSizeApplyAffineTransform (viewFrame.size, drawableSizeTansform); - - const auto componentHeight = comp.getHeight(); + const auto transformedFrameSize = CGSizeApplyAffineTransform (view.frame.size, drawableSizeTansform); if (resources == nullptr || ! CGSizeEqualToSize (layer.drawableSize, transformedFrameSize)) { layer.drawableSize = transformedFrameSize; - resources = std::make_unique (device.get(), layer, componentHeight); + resources = std::make_unique (device.get(), layer); } auto gpuTexture = resources->getGpuTexture(); @@ -261,7 +257,7 @@ private: class Resources { public: - Resources (id metalDevice, CAMetalLayer* layer, int componentHeight) + Resources (id metalDevice, CAMetalLayer* layer) { const auto bytesPerRow = alignTo ((size_t) layer.drawableSize.width * 4, 256); @@ -301,8 +297,8 @@ private: CGColorSpaceCreateWithName (kCGColorSpaceSRGB), (uint32_t) kCGImageAlphaPremultipliedFirst | (uint32_t) kCGBitmapByteOrder32Host)); - CGContextScaleCTM (cgContext.get(), layer.contentsScale, layer.contentsScale); - CGContextConcatCTM (cgContext.get(), CGAffineTransformMake (1, 0, 0, -1, 0, componentHeight)); + CGContextTranslateCTM (cgContext.get(), 0, layer.drawableSize.height); + CGContextScaleCTM (cgContext.get(), layer.contentsScale, -layer.contentsScale); textureDesc.storageMode = MTLStorageModePrivate; gpuTexturePool = std::make_unique (metalDevice, textureDesc); diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index a075cccc7d..2047f6f91b 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -151,7 +151,7 @@ public: #if USE_COREGRAPHICS_RENDERING #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS if (@available (macOS 10.14, *)) - metalRenderer = std::make_unique> (view, getComponent()); + metalRenderer = std::make_unique> (view, getComponent().isOpaque()); #endif if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0) { @@ -1047,7 +1047,11 @@ public: if (metalRenderer != nullptr) { - const auto compBounds = getComponent().getLocalBounds().toFloat(); + auto setDeferredRepaintsToWholeFrame = [this] + { + const auto frameSize = view.frame.size; + deferredRepaints = Rectangle { (float) frameSize.width, (float) frameSize.height }; + }; // If we are resizing we need to fall back to synchronous drawing to avoid artefacts if ([window inLiveResize] || numFramesToSkipMetalRenderer > 0) @@ -1055,7 +1059,7 @@ public: if (metalRenderer->isAttachedToView (view)) { metalRenderer->detach(); - deferredRepaints = compBounds; + setDeferredRepaintsToWholeFrame(); } if (numFramesToSkipMetalRenderer > 0) @@ -1065,8 +1069,8 @@ public: { if (! metalRenderer->isAttachedToView (view)) { - metalRenderer->attach (view, getComponent()); - deferredRepaints = compBounds; + metalRenderer->attach (view, getComponent().isOpaque()); + setDeferredRepaintsToWholeFrame(); } } } @@ -1076,8 +1080,6 @@ public: if (metalRenderer != nullptr && metalRenderer->isAttachedToView (view)) return metalRenderer->drawRectangleList (view, (float) [[view window] backingScaleFactor], - view.frame, - getComponent(), [this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); }, deferredRepaints);