From 2983262173418b58a8d3bfcedf1213bd6b6c218b Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Wed, 9 Dec 2015 12:23:22 -1000 Subject: [PATCH] Metal window resize fixes --- lib/graphicsdev/Metal.mm | 45 +++++++++++++++++++++++-------------- lib/mac/CocoaCommon.hpp | 4 ++++ lib/mac/WindowCocoa.mm | 48 ++++++++++++++++++++++++++++++++++------ 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 0dab6b2..f73cfcb 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -554,7 +554,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue { @autoreleasepool { - m_cmdBuf = [[ctx->m_q.get() commandBufferWithUnretainedReferences] retain]; + m_cmdBuf = [[ctx->m_q.get() commandBuffer] retain]; } } @@ -676,22 +676,35 @@ struct MetalCommandQueue : IGraphicsCommandQueue m_enc.reset(); @autoreleasepool { + { + std::unique_lock lk(w.m_resizeLock); + if (w.m_needsResize) + { + w.m_metalLayer.drawableSize = w.m_size; + w.m_needsResize = NO; + return; + } + } id drawable = [w.m_metalLayer nextDrawable]; if (drawable) { id dest = drawable.texture; - id blitEnc = [m_cmdBuf.get() blitCommandEncoder]; - [blitEnc copyFromTexture:csource->m_tex.get() - sourceSlice:0 - sourceLevel:0 - sourceOrigin:MTLOriginMake(0, 0, 0) - sourceSize:MTLSizeMake(dest.width, dest.height, 1) - toTexture:dest - destinationSlice:0 - destinationLevel:0 - destinationOrigin:MTLOriginMake(0, 0, 0)]; - [blitEnc endEncoding]; - [m_cmdBuf.get() presentDrawable:drawable]; + if (csource->m_tex.get().width == dest.width && + csource->m_tex.get().height == dest.height) + { + id blitEnc = [m_cmdBuf.get() blitCommandEncoder]; + [blitEnc copyFromTexture:csource->m_tex.get() + sourceSlice:0 + sourceLevel:0 + sourceOrigin:MTLOriginMake(0, 0, 0) + sourceSize:MTLSizeMake(dest.width, dest.height, 1) + toTexture:dest + destinationSlice:0 + destinationLevel:0 + destinationOrigin:MTLOriginMake(0, 0, 0)]; + [blitEnc endEncoding]; + [m_cmdBuf.get() presentDrawable:drawable]; + } } } } @@ -721,7 +734,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue /* Abandon if in progress (renderer too slow) */ if (m_inProgress) { - m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain]; + m_cmdBuf = [[m_ctx->m_q.get() commandBuffer] retain]; return; } @@ -731,7 +744,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue for (const auto& resize : m_texResizes) resize.first->resize(m_ctx, resize.second.first, resize.second.second); m_texResizes.clear(); - m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain]; + m_cmdBuf = [[m_ctx->m_q.get() commandBuffer] retain]; return; } @@ -741,7 +754,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue [m_cmdBuf.get() addCompletedHandler:^(id buf) {m_inProgress = false;}]; m_inProgress = true; [m_cmdBuf.get() commit]; - m_cmdBuf = [[m_ctx->m_q.get() commandBufferWithUnretainedReferences] retain]; + m_cmdBuf = [[m_ctx->m_q.get() commandBuffer] retain]; } } }; diff --git a/lib/mac/CocoaCommon.hpp b/lib/mac/CocoaCommon.hpp index 55c5ba2..8d2c8b4 100644 --- a/lib/mac/CocoaCommon.hpp +++ b/lib/mac/CocoaCommon.hpp @@ -28,6 +28,7 @@ public: #include #include #include +#include namespace boo { @@ -39,6 +40,9 @@ struct MetalContext struct Window { CAMetalLayer* m_metalLayer = nullptr; + std::mutex m_resizeLock; + bool m_needsResize; + CGSize m_size; }; std::unordered_map m_windows; }; diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index 441a953..828b39e 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -144,8 +144,10 @@ class GraphicsContextCocoaMetal; { BooCocoaResponder* resp; boo::MetalContext* m_ctx; + boo::IWindow* m_window; } - (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx; +- (void)reshapeHandler; @end namespace boo @@ -317,12 +319,13 @@ class GraphicsContextCocoaMetal : public GraphicsContextCocoa IGraphicsDataFactory* m_dataFactory = nullptr; public: + IWindow* m_parentWindow; MetalContext* m_metalCtx; GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow, MetalContext* metalCtx) : GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow), - m_metalCtx(metalCtx) + m_parentWindow(parentWindow), m_metalCtx(metalCtx) { m_dataFactory = new MetalDataFactory(this, metalCtx); } @@ -909,6 +912,7 @@ static boo::ESpecialKey translateKeycode(short code) - (id)initWithBooContext:(boo::GraphicsContextCocoaMetal*)bctx { m_ctx = bctx->m_metalCtx; + m_window = bctx->m_parentWindow; self = [self initWithFrame:NSMakeRect(0, 0, 100, 100)]; [self setWantsLayer:YES]; resp = [[BooCocoaResponder alloc] initWithBooContext:bctx View:self]; @@ -945,6 +949,36 @@ static boo::ESpecialKey translateKeycode(short code) return resp; } +- (void)reshapeHandler +{ + boo::SWindowRect rect = {{int(self.frame.origin.x), int(self.frame.origin.y)}, + {int(self.frame.size.width), int(self.frame.size.height)}}; + boo::MetalContext::Window& w = m_ctx->m_windows[m_window]; + std::unique_lock lk(w.m_resizeLock); + if (resp->booContext->m_callback) + resp->booContext->m_callback->resized(rect); + w.m_size = CGSizeMake(rect.size[0], rect.size[1]); + w.m_needsResize = YES; +} + +- (void)setFrameSize:(NSSize)newSize +{ + [super setFrameSize:newSize]; + [self reshapeHandler]; +} + +- (void)setBoundsSize:(NSSize)newSize +{ + [super setBoundsSize:newSize]; + [self reshapeHandler]; +} + +- (void)viewDidChangeBackingProperties +{ + [super viewDidChangeBackingProperties]; + [self reshapeHandler]; +} + @end #endif @@ -1061,7 +1095,7 @@ public: void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { - NSRect wFrame = m_nsWindow.frame; + NSRect wFrame = m_nsWindow.contentView.frame; xOut = wFrame.origin.x; yOut = wFrame.origin.y; wOut = wFrame.size.width; @@ -1070,7 +1104,7 @@ public: void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { - NSRect wFrame = m_nsWindow.frame; + NSRect wFrame = m_nsWindow.contentView.frame; xOut = wFrame.origin.x; yOut = wFrame.origin.y; wOut = wFrame.size.width; @@ -1081,8 +1115,8 @@ public: { dispatch_sync(dispatch_get_main_queue(), ^{ - NSRect wFrame = NSMakeRect(x, y, w, h); - [m_nsWindow setFrame:wFrame display:NO]; + [m_nsWindow setContentSize:NSMakeSize(w, h)]; + [m_nsWindow setFrameOrigin:NSMakePoint(x, y)]; }); } @@ -1090,8 +1124,8 @@ public: { dispatch_sync(dispatch_get_main_queue(), ^{ - NSRect wFrame = NSMakeRect(x, y, w, h); - [m_nsWindow setFrame:wFrame display:NO]; + [m_nsWindow setContentSize:NSMakeSize(w, h)]; + [m_nsWindow setFrameOrigin:NSMakePoint(x, y)]; }); }