Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomoaki Kawada <i@yvt.jp>2019-05-24 19:38:20 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-06-02 13:54:46 +0300
commit99de160340c7ae08ac5abed12a541017e4846d87 (patch)
tree544bfa7cdd985d112e0ae59e369eb3e672421572 /intern/ghost/intern/GHOST_WindowCocoa.mm
parent1418eee5f5c84d3ec24d326952e57e248e27ef96 (diff)
macOS: fix viewport lagging, by using CAMetalLayer instead of NSOpenGLView
On GPUs that support it, we now present OpenGL contents via CAMetalLayer. This fixes frame skipping issues found in T60043. If the system does not have a Metal capable GPU, NSOpenGLView will continue to be used. Patch by Tomoaki Kawada, with some changes by Brecht Van Lommel. Differential Revision: https://developer.blender.org/D4619
Diffstat (limited to 'intern/ghost/intern/GHOST_WindowCocoa.mm')
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm78
1 files changed, 65 insertions, 13 deletions
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 33d9921cdec..45ea3c85005 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -29,6 +29,8 @@
#endif
#include <Cocoa/Cocoa.h>
+#include <QuartzCore/QuartzCore.h>
+#include <Metal/Metal.h>
#include <sys/sysctl.h>
@@ -263,7 +265,17 @@
@end
/* NSView for handling input and drawing. */
+#define COCOA_VIEW_CLASS CocoaOpenGLView
+#define COCOA_VIEW_BASE_CLASS NSOpenGLView
#include "GHOST_WindowViewCocoa.h"
+#undef COCOA_VIEW_CLASS
+#undef COCOA_VIEW_BASE_CLASS
+
+#define COCOA_VIEW_CLASS CocoaMetalView
+#define COCOA_VIEW_BASE_CLASS NSView
+#include "GHOST_WindowViewCocoa.h"
+#undef COCOA_VIEW_CLASS
+#undef COCOA_VIEW_BASE_CLASS
#pragma mark initialization / finalization
@@ -281,6 +293,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
bool is_debug)
: GHOST_Window(width, height, state, stereoVisual, false),
m_openGLView(nil),
+ m_metalView(nil),
+ m_metalLayer(nil),
m_systemCocoa(systemCocoa),
m_customCursor(0),
m_immediateDraw(false),
@@ -318,21 +332,44 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
minSize.height = 240;
[m_window setContentMinSize:minSize];
- // Creates the OpenGL View inside the window
- m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect];
+ // Create NSView inside the window
+ id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
+ NSView *view;
+
+ if (metalDevice) {
+ // Create metal layer and view if supported
+ m_metalLayer = [[CAMetalLayer alloc] init];
+ [m_metalLayer setEdgeAntialiasingMask:0];
+ [m_metalLayer setMasksToBounds:NO];
+ [m_metalLayer setOpaque:YES];
+ [m_metalLayer setFramebufferOnly:YES];
+ [m_metalLayer setPresentsWithTransaction:NO];
+ [m_metalLayer removeAllAnimations];
+ [m_metalLayer setDevice:metalDevice];
+
+ m_metalView = [[CocoaMetalView alloc] initWithFrame:rect];
+ [m_metalView setWantsLayer:YES];
+ [m_metalView setLayer:m_metalLayer];
+ [m_metalView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
+ view = m_metalView;
+ }
+ else {
+ // Fallback to OpenGL view if there is no Metal support
+ m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect];
+ [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
+ view = m_openGLView;
+ }
if (m_systemCocoa->m_nativePixel) {
// Needs to happen early when building with the 10.14 SDK, otherwise
// has no effect until resizeing the window.
- if ([m_openGLView respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
- [m_openGLView setWantsBestResolutionOpenGLSurface:YES];
+ if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) {
+ [view setWantsBestResolutionOpenGLSurface:YES];
}
}
- [m_openGLView setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
-
- [m_window setContentView:m_openGLView];
- [m_window setInitialFirstResponder:m_openGLView];
+ [m_window setContentView:view];
+ [m_window setInitialFirstResponder:view];
[m_window makeKeyAndOrderFront:nil];
@@ -381,7 +418,18 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
releaseNativeHandles();
- [m_openGLView release];
+ if (m_openGLView) {
+ [m_openGLView release];
+ m_openGLView = nil;
+ }
+ if (m_metalView) {
+ [m_metalView release];
+ m_metalView = nil;
+ }
+ if (m_metalLayer) {
+ [m_metalLayer release];
+ m_metalLayer = nil;
+ }
if (m_window) {
[m_window close];
@@ -405,7 +453,8 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa()
bool GHOST_WindowCocoa::getValid() const
{
- return GHOST_Window::getValid() && m_window != NULL && m_openGLView != NULL;
+ NSView *view = (m_openGLView) ? m_openGLView : m_metalView;
+ return GHOST_Window::getValid() && m_window != NULL && view != NULL;
}
void *GHOST_WindowCocoa::getOSWindow() const
@@ -669,7 +718,8 @@ NSScreen *GHOST_WindowCocoa::getScreen()
/* called for event, when window leaves monitor to another */
void GHOST_WindowCocoa::setNativePixelSize(void)
{
- NSRect backingBounds = [m_openGLView convertRectToBacking:[m_openGLView bounds]];
+ NSView *view = (m_openGLView) ? m_openGLView : m_metalView;
+ NSRect backingBounds = [view convertRectToBacking:[view bounds]];
GHOST_Rect rect;
getClientBounds(rect);
@@ -763,7 +813,8 @@ GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType ty
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
- GHOST_Context *context = new GHOST_ContextCGL(m_wantStereoVisual, m_openGLView);
+ GHOST_Context *context = new GHOST_ContextCGL(
+ m_wantStereoVisual, m_metalView, m_metalLayer, m_openGLView);
if (context->initializeDrawingContext())
return context;
@@ -780,7 +831,8 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate()
{
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [m_openGLView setNeedsDisplay:YES];
+ NSView *view = (m_openGLView) ? m_openGLView : m_metalView;
+ [view setNeedsDisplay:YES];
[pool drain];
return GHOST_kSuccess;
}