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

macOS/iOS: Fix a scaled multiple-rects drawing issue

This commit is contained in:
Tom Poole 2022-08-04 11:07:44 +01:00
parent fc376eab3b
commit 61fd8827e1
3 changed files with 19 additions and 23 deletions

View file

@ -1391,7 +1391,7 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, int windowStyleFlags,
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
if (@available (iOS 13, *)) if (@available (iOS 13, *))
metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<UIView>> (view, comp); metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<UIView>> (view, comp.isOpaque());
#endif #endif
if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0) if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0)
@ -1857,8 +1857,6 @@ void UIViewComponentPeer::displayLinkCallback()
if (metalRenderer != nullptr) if (metalRenderer != nullptr)
return metalRenderer->drawRectangleList (view, return metalRenderer->drawRectangleList (view,
(float) view.contentScaleFactor, (float) view.contentScaleFactor,
view.frame,
component,
[this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); }, [this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); },
deferredRepaints); deferredRepaints);

View file

@ -35,12 +35,12 @@ class CoreGraphicsMetalLayerRenderer
{ {
public: public:
//============================================================================== //==============================================================================
CoreGraphicsMetalLayerRenderer (ViewType* view, const Component& comp) CoreGraphicsMetalLayerRenderer (ViewType* view, bool isOpaque)
{ {
device.reset (MTLCreateSystemDefaultDevice()); device.reset (MTLCreateSystemDefaultDevice());
commandQueue.reset ([device.get() newCommandQueue]); commandQueue.reset ([device.get() newCommandQueue]);
attach (view, comp); attach (view, isOpaque);
} }
~CoreGraphicsMetalLayerRenderer() ~CoreGraphicsMetalLayerRenderer()
@ -52,7 +52,7 @@ public:
} }
} }
void attach (ViewType* view, const Component& comp) void attach (ViewType* view, bool isOpaque)
{ {
#if JUCE_MAC #if JUCE_MAC
view.wantsLayer = YES; view.wantsLayer = YES;
@ -65,7 +65,7 @@ public:
layer.device = device.get(); layer.device = device.get();
layer.framebufferOnly = NO; layer.framebufferOnly = NO;
layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB; layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
layer.opaque = comp.isOpaque(); layer.opaque = isOpaque;
layer.allowsNextDrawableTimeout = NO; layer.allowsNextDrawableTimeout = NO;
attachedView = view; attachedView = view;
@ -90,8 +90,6 @@ public:
template <typename Callback> template <typename Callback>
bool drawRectangleList (ViewType* view, bool drawRectangleList (ViewType* view,
float scaleFactor, float scaleFactor,
CGRect viewFrame,
const Component& comp,
Callback&& drawRectWithContext, Callback&& drawRectWithContext,
const RectangleList<float>& dirtyRegions) const RectangleList<float>& dirtyRegions)
{ {
@ -117,14 +115,12 @@ public:
layer.contentsScale = scaleFactor; layer.contentsScale = scaleFactor;
const auto drawableSizeTansform = CGAffineTransformMakeScale (layer.contentsScale, const auto drawableSizeTansform = CGAffineTransformMakeScale (layer.contentsScale,
layer.contentsScale); layer.contentsScale);
const auto transformedFrameSize = CGSizeApplyAffineTransform (viewFrame.size, drawableSizeTansform); const auto transformedFrameSize = CGSizeApplyAffineTransform (view.frame.size, drawableSizeTansform);
const auto componentHeight = comp.getHeight();
if (resources == nullptr || ! CGSizeEqualToSize (layer.drawableSize, transformedFrameSize)) if (resources == nullptr || ! CGSizeEqualToSize (layer.drawableSize, transformedFrameSize))
{ {
layer.drawableSize = transformedFrameSize; layer.drawableSize = transformedFrameSize;
resources = std::make_unique<Resources> (device.get(), layer, componentHeight); resources = std::make_unique<Resources> (device.get(), layer);
} }
auto gpuTexture = resources->getGpuTexture(); auto gpuTexture = resources->getGpuTexture();
@ -261,7 +257,7 @@ private:
class Resources class Resources
{ {
public: public:
Resources (id<MTLDevice> metalDevice, CAMetalLayer* layer, int componentHeight) Resources (id<MTLDevice> metalDevice, CAMetalLayer* layer)
{ {
const auto bytesPerRow = alignTo ((size_t) layer.drawableSize.width * 4, 256); const auto bytesPerRow = alignTo ((size_t) layer.drawableSize.width * 4, 256);
@ -301,8 +297,8 @@ private:
CGColorSpaceCreateWithName (kCGColorSpaceSRGB), CGColorSpaceCreateWithName (kCGColorSpaceSRGB),
(uint32_t) kCGImageAlphaPremultipliedFirst | (uint32_t) kCGBitmapByteOrder32Host)); (uint32_t) kCGImageAlphaPremultipliedFirst | (uint32_t) kCGBitmapByteOrder32Host));
CGContextScaleCTM (cgContext.get(), layer.contentsScale, layer.contentsScale); CGContextTranslateCTM (cgContext.get(), 0, layer.drawableSize.height);
CGContextConcatCTM (cgContext.get(), CGAffineTransformMake (1, 0, 0, -1, 0, componentHeight)); CGContextScaleCTM (cgContext.get(), layer.contentsScale, -layer.contentsScale);
textureDesc.storageMode = MTLStorageModePrivate; textureDesc.storageMode = MTLStorageModePrivate;
gpuTexturePool = std::make_unique<GpuTexturePool> (metalDevice, textureDesc); gpuTexturePool = std::make_unique<GpuTexturePool> (metalDevice, textureDesc);

View file

@ -151,7 +151,7 @@ public:
#if USE_COREGRAPHICS_RENDERING #if USE_COREGRAPHICS_RENDERING
#if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS
if (@available (macOS 10.14, *)) if (@available (macOS 10.14, *))
metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<NSView>> (view, getComponent()); metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<NSView>> (view, getComponent().isOpaque());
#endif #endif
if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0) if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0)
{ {
@ -1047,7 +1047,11 @@ public:
if (metalRenderer != nullptr) if (metalRenderer != nullptr)
{ {
const auto compBounds = getComponent().getLocalBounds().toFloat(); auto setDeferredRepaintsToWholeFrame = [this]
{
const auto frameSize = view.frame.size;
deferredRepaints = Rectangle<float> { (float) frameSize.width, (float) frameSize.height };
};
// If we are resizing we need to fall back to synchronous drawing to avoid artefacts // If we are resizing we need to fall back to synchronous drawing to avoid artefacts
if ([window inLiveResize] || numFramesToSkipMetalRenderer > 0) if ([window inLiveResize] || numFramesToSkipMetalRenderer > 0)
@ -1055,7 +1059,7 @@ public:
if (metalRenderer->isAttachedToView (view)) if (metalRenderer->isAttachedToView (view))
{ {
metalRenderer->detach(); metalRenderer->detach();
deferredRepaints = compBounds; setDeferredRepaintsToWholeFrame();
} }
if (numFramesToSkipMetalRenderer > 0) if (numFramesToSkipMetalRenderer > 0)
@ -1065,8 +1069,8 @@ public:
{ {
if (! metalRenderer->isAttachedToView (view)) if (! metalRenderer->isAttachedToView (view))
{ {
metalRenderer->attach (view, getComponent()); metalRenderer->attach (view, getComponent().isOpaque());
deferredRepaints = compBounds; setDeferredRepaintsToWholeFrame();
} }
} }
} }
@ -1076,8 +1080,6 @@ public:
if (metalRenderer != nullptr && metalRenderer->isAttachedToView (view)) if (metalRenderer != nullptr && metalRenderer->isAttachedToView (view))
return metalRenderer->drawRectangleList (view, return metalRenderer->drawRectangleList (view,
(float) [[view window] backingScaleFactor], (float) [[view window] backingScaleFactor],
view.frame,
getComponent(),
[this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); }, [this] (CGContextRef ctx, CGRect r) { drawRectWithContext (ctx, r); },
deferredRepaints); deferredRepaints);