1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

CGMetalRenderer: Avoid glitching when resizing views

This commit is contained in:
reuk 2023-04-03 17:40:35 +01:00
parent fe09902e83
commit 9d50ab6c59
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C
3 changed files with 215 additions and 122 deletions

View file

@ -295,7 +295,7 @@ struct CADisplayLinkDeleter
@end
@interface JuceUIView : UIView
@interface JuceUIView : UIView<CALayerDelegate>
{
@public
UIViewComponentPeer* owner;
@ -520,6 +520,12 @@ public:
return UIKeyboardTypeDefault;
}
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
std::unique_ptr<CoreGraphicsMetalLayerRenderer> metalRenderer;
#endif
RectangleList<float> deferredRepaints;
private:
void appStyleChanged() override
{
@ -545,9 +551,6 @@ private:
}
};
std::unique_ptr<CoreGraphicsMetalLayerRenderer<UIView>> metalRenderer;
RectangleList<float> deferredRepaints;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIViewComponentPeer)
};
@ -698,6 +701,26 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
[super initWithFrame: frame];
owner = peer;
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
if (@available (iOS 13.0, *))
{
auto* layer = (CAMetalLayer*) [self layer];
layer.device = MTLCreateSystemDefaultDevice();
layer.framebufferOnly = NO;
layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
if (owner != nullptr)
layer.opaque = owner->getComponent().isOpaque();
layer.presentsWithTransaction = YES;
layer.needsDisplayOnBoundsChange = true;
layer.presentsWithTransaction = true;
layer.delegate = self;
layer.allowsNextDrawableTimeout = NO;
}
#endif
displayLink.reset ([CADisplayLink displayLinkWithTarget: self
selector: @selector (displayLinkCallback:)]);
[displayLink.get() addToRunLoop: [NSRunLoop mainRunLoop]
@ -750,6 +773,41 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
owner->displayLinkCallback();
}
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
- (CALayer*) makeBackingLayer
{
auto* layer = [CAMetalLayer layer];
layer.device = MTLCreateSystemDefaultDevice();
layer.framebufferOnly = NO;
layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
if (owner != nullptr)
layer.opaque = owner->getComponent().isOpaque();
layer.presentsWithTransaction = YES;
layer.needsDisplayOnBoundsChange = true;
layer.presentsWithTransaction = true;
layer.delegate = self;
layer.allowsNextDrawableTimeout = NO;
return layer;
}
- (void) displayLayer: (CALayer*) layer
{
if (owner != nullptr)
{
owner->deferredRepaints = owner->metalRenderer->drawRectangleList (static_cast<CAMetalLayer*> (layer),
(float) [self contentScaleFactor],
[self] (auto&&... args) { owner->drawRectWithContext (args...); },
std::move (owner->deferredRepaints),
false);
}
}
#endif
//==============================================================================
- (void) drawRect: (CGRect) r
{
@ -1680,7 +1738,7 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, int windowStyleFlags,
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
if (@available (iOS 13, *))
{
metalRenderer = CoreGraphicsMetalLayerRenderer<UIView>::create (view, comp.isOpaque());
metalRenderer = CoreGraphicsMetalLayerRenderer::create();
jassert (metalRenderer != nullptr);
}
#endif
@ -2138,22 +2196,8 @@ void UIViewComponentPeer::displayLinkCallback()
if (deferredRepaints.isEmpty())
return;
auto dispatchRectangles = [this] ()
{
if (metalRenderer != nullptr)
return metalRenderer->drawRectangleList (view,
(float) view.contentScaleFactor,
[this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); },
deferredRepaints);
for (const auto& r : deferredRepaints)
[view setNeedsDisplayInRect: convertToCGRect (r)];
return true;
};
if (dispatchRectangles())
deferredRepaints.clear();
for (const auto& r : deferredRepaints)
[view setNeedsDisplayInRect: convertToCGRect (r)];
}
//==============================================================================