Metal window resize fixes

This commit is contained in:
Jack Andersen 2015-12-09 12:23:22 -10:00
parent 9baff7a2bc
commit 2983262173
3 changed files with 74 additions and 23 deletions

View File

@ -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<std::mutex> lk(w.m_resizeLock);
if (w.m_needsResize)
{
w.m_metalLayer.drawableSize = w.m_size;
w.m_needsResize = NO;
return;
}
}
id<CAMetalDrawable> drawable = [w.m_metalLayer nextDrawable];
if (drawable)
{
id<MTLTexture> dest = drawable.texture;
id<MTLBlitCommandEncoder> 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<MTLBlitCommandEncoder> 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<MTLCommandBuffer> 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];
}
}
};

View File

@ -28,6 +28,7 @@ public:
#include <Metal/Metal.h>
#include <QuartzCore/CAMetalLayer.h>
#include <unordered_map>
#include <mutex>
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<IWindow*, Window> m_windows;
};

View File

@ -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<std::mutex> 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)];
});
}