summaryrefslogtreecommitdiff
path: root/platform/osx
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2019-07-29 20:44:14 +0200
committerGitHub <noreply@github.com>2020-02-11 11:57:40 +0100
commit6289e7d1479f6e7c9e55890c8c66d2e5e0a1481a (patch)
tree8223d907b1aa8184295240a7b6f63023da05c02f /platform/osx
parent6ecedd1e6ca7d8b10b13a3dab19074fd51b17bcf (diff)
parentb456bfad5cee3922f55621bf7c133cc67337636a (diff)
Merge pull request #29993 from bruvzg/vulkan
Initial Vulkan support for macOS (MoltenVK) and Windows
Diffstat (limited to 'platform/osx')
-rw-r--r--platform/osx/SCsub2
-rw-r--r--platform/osx/context_gl_osx.h79
-rw-r--r--platform/osx/context_gl_osx.mm216
-rw-r--r--platform/osx/detect.py23
-rw-r--r--platform/osx/godot_main_osx.mm6
-rw-r--r--platform/osx/os_osx.h21
-rw-r--r--platform/osx/os_osx.mm364
-rw-r--r--platform/osx/vulkan_context_osx.h48
-rw-r--r--platform/osx/vulkan_context_osx.mm56
9 files changed, 620 insertions, 195 deletions
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index e15b4339a7..09f213cb0e 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -13,6 +13,8 @@ files = [
'dir_access_osx.mm',
'joypad_osx.cpp',
'power_osx.cpp',
+ 'vulkan_context_osx.mm',
+ 'context_gl_osx.mm'
]
prog = env.add_program('#bin/godot', files)
diff --git a/platform/osx/context_gl_osx.h b/platform/osx/context_gl_osx.h
new file mode 100644
index 0000000000..831a813fe9
--- /dev/null
+++ b/platform/osx/context_gl_osx.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* context_gl_osx.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef CONTEXT_GL_OSX_H
+#define CONTEXT_GL_OSX_H
+
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
+
+#include "core/error_list.h"
+#include "core/os/os.h"
+
+#include <AppKit/AppKit.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <CoreVideo/CoreVideo.h>
+
+class ContextGL_OSX {
+
+ bool opengl_3_context;
+ bool use_vsync;
+
+ void *framework;
+ id window_view;
+ NSOpenGLPixelFormat *pixelFormat;
+ NSOpenGLContext *context;
+
+public:
+ bool waiting_for_vsync;
+ NSCondition *vsync_condition;
+ CVDisplayLinkRef displayLink;
+
+ void release_current();
+
+ void make_current();
+ void update();
+
+ void set_opacity(GLint p_opacity);
+
+ int get_window_width();
+ int get_window_height();
+ void swap_buffers();
+
+ Error initialize();
+
+ void set_use_vsync(bool p_use);
+ bool is_using_vsync() const;
+
+ ContextGL_OSX(id p_view, bool p_opengl_3_context);
+ ~ContextGL_OSX();
+};
+
+#endif
+#endif \ No newline at end of file
diff --git a/platform/osx/context_gl_osx.mm b/platform/osx/context_gl_osx.mm
new file mode 100644
index 0000000000..425c9b0ac4
--- /dev/null
+++ b/platform/osx/context_gl_osx.mm
@@ -0,0 +1,216 @@
+/*************************************************************************/
+/* context_gl_osx.mm */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "context_gl_osx.h"
+
+#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
+
+// DisplayLinkCallback is called from our DisplayLink OS thread informing us right before
+// a screen update is required. We can use it to work around the broken vsync.
+static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
+ ContextGL_OSX *gl_ctx = (ContextGL_OSX *)displayLinkContext;
+
+ // Set flag so we know we can output our next frame and signal our conditional lock
+ // if we're not doing vsync this will be ignored
+ [gl_ctx->vsync_condition lock];
+ gl_ctx->waiting_for_vsync = false;
+ [gl_ctx->vsync_condition signal];
+ [gl_ctx->vsync_condition unlock];
+
+ return kCVReturnSuccess;
+}
+
+void ContextGL_OSX::release_current() {
+
+ [NSOpenGLContext clearCurrentContext];
+}
+
+void ContextGL_OSX::make_current() {
+
+ [context makeCurrentContext];
+}
+
+void ContextGL_OSX::update() {
+
+ [context update];
+}
+
+void ContextGL_OSX::set_opacity(GLint p_opacity) {
+
+ [context setValues:&p_opacity forParameter:NSOpenGLCPSurfaceOpacity];
+}
+
+int ContextGL_OSX::get_window_width() {
+
+ return OS::get_singleton()->get_video_mode().width;
+}
+
+int ContextGL_OSX::get_window_height() {
+
+ return OS::get_singleton()->get_video_mode().height;
+}
+
+void ContextGL_OSX::swap_buffers() {
+
+ if (use_vsync) {
+ // Wait until our DisplayLink callback unsets our flag...
+ [vsync_condition lock];
+ while (waiting_for_vsync)
+ [vsync_condition wait];
+
+ // Make sure we wait again next frame around
+ waiting_for_vsync = true;
+
+ [vsync_condition unlock];
+ }
+
+ [context flushBuffer];
+}
+
+void ContextGL_OSX::set_use_vsync(bool p_use) {
+ // CGLCPSwapInterval broke in OSX 10.14 and it seems Apple is not interested in fixing
+ // it as OpenGL is now deprecated and Metal solves this differently.
+ // Following SDLs example we're working around this using DisplayLink
+ // When vsync is enabled we set a flag "waiting_for_vsync" to true.
+ // This flag is set to false when DisplayLink informs us our display is about to refresh.
+
+ ///TODO Maybe pause/unpause display link?
+ use_vsync = p_use;
+ waiting_for_vsync = p_use;
+}
+
+bool ContextGL_OSX::is_using_vsync() const {
+
+ return use_vsync;
+}
+
+Error ContextGL_OSX::initialize() {
+
+ framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ ERR_FAIL_COND_V(!framework, ERR_CANT_CREATE);
+
+ unsigned int attributeCount = 0;
+
+ // OS X needs non-zero color size, so set reasonable values
+ int colorBits = 32;
+
+ // Fail if a robustness strategy was requested
+
+#define ADD_ATTR(x) \
+ { attributes[attributeCount++] = x; }
+#define ADD_ATTR2(x, y) \
+ { \
+ ADD_ATTR(x); \
+ ADD_ATTR(y); \
+ }
+
+ // Arbitrary array size here
+ NSOpenGLPixelFormatAttribute attributes[40];
+
+ ADD_ATTR(NSOpenGLPFADoubleBuffer);
+ ADD_ATTR(NSOpenGLPFAClosestPolicy);
+
+ if (!opengl_3_context) {
+ ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy);
+ } else {
+ //we now need OpenGL 3 or better, maybe even change this to 3_3Core ?
+ ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+ }
+
+ ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
+
+ /*
+ if (fbconfig->alphaBits > 0)
+ ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
+*/
+
+ ADD_ATTR2(NSOpenGLPFADepthSize, 24);
+
+ ADD_ATTR2(NSOpenGLPFAStencilSize, 8);
+
+ /*
+ if (fbconfig->stereo)
+ ADD_ATTR(NSOpenGLPFAStereo);
+*/
+
+ /*
+ if (fbconfig->samples > 0) {
+ ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
+ ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
+ }
+*/
+
+ // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
+ // framebuffer, so there's no need (and no way) to request it
+
+ ADD_ATTR(0);
+
+#undef ADD_ATTR
+#undef ADD_ATTR2
+
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ ERR_FAIL_COND_V(pixelFormat == nil, ERR_CANT_CREATE);
+
+ context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+
+ ERR_FAIL_COND_V(context == nil, ERR_CANT_CREATE);
+
+ [context setView:window_view];
+
+ [context makeCurrentContext];
+
+ // setup our display link, this will inform us when a refresh is needed
+ CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
+ CVDisplayLinkSetOutputCallback(displayLink, &DisplayLinkCallback, this);
+ CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, context.CGLContextObj, pixelFormat.CGLPixelFormatObj);
+ CVDisplayLinkStart(displayLink);
+
+ // initialise a conditional lock object
+ vsync_condition = [[NSCondition alloc] init];
+
+ return OK;
+}
+
+ContextGL_OSX::ContextGL_OSX(id p_view, bool p_opengl_3_context) {
+
+ opengl_3_context = p_opengl_3_context;
+ window_view = p_view;
+ use_vsync = false;
+}
+
+ContextGL_OSX::~ContextGL_OSX() {
+
+ if (displayLink) {
+ CVDisplayLinkRelease(displayLink);
+ }
+ [vsync_condition release];
+}
+
+#endif
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index fe839199e8..c4e8779523 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,5 +1,6 @@
import os
import sys
+import subprocess
from methods import detect_darwin_sdk_path
@@ -25,6 +26,7 @@ def get_opts():
return [
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
('MACOS_SDK_PATH', 'Path to the macOS SDK', ''),
+ BoolVariable('use_static_mvk', 'Link MoltenVK statically as Level-0 driver (better portability) or use Vulkan ICD loader (enables validation layers)', False),
EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False),
@@ -148,9 +150,20 @@ def configure(env):
## Flags
env.Prepend(CPPPATH=['#platform/osx'])
- env.Append(CPPDEFINES=['OSX_ENABLED', 'UNIX_ENABLED', 'GLES_ENABLED', 'APPLE_STYLE_KEYS', 'COREAUDIO_ENABLED', 'COREMIDI_ENABLED'])
- env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMIDI', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback', '-framework', 'AVFoundation', '-framework', 'CoreMedia', '-framework', 'CoreVideo'])
- env.Append(LIBS=['pthread'])
+ env.Append(CPPDEFINES=['OSX_ENABLED', 'UNIX_ENABLED', 'APPLE_STYLE_KEYS', 'COREAUDIO_ENABLED', 'COREMIDI_ENABLED'])
+ env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMIDI', '-framework', 'IOKit', '-framework', 'ForceFeedback', '-framework', 'CoreVideo', '-framework', 'AVFoundation', '-framework', 'CoreMedia'])
+ env.Append(LIBS=['pthread', 'z'])
- env.Append(CCFLAGS=['-mmacosx-version-min=10.9'])
- env.Append(LINKFLAGS=['-mmacosx-version-min=10.9'])
+ env.Prepend(CPPPATH=['#thirdparty/vulkan/include/', "#thirdparty/vulkan/registry/"])
+ env.Append(CPPDEFINES=['VULKAN_ENABLED'])
+
+ #env.Append(CPPDEFINES=['GLES_ENABLED', 'OPENGL_ENABLED'])
+
+ env.Append(LINKFLAGS=['-framework', 'Metal', '-framework', 'QuartzCore', '-framework', 'IOSurface'])
+ if (env['use_static_mvk']):
+ env.Append(LINKFLAGS=['-framework', 'MoltenVK'])
+ elif not env["builtin_vulkan_loader"]:
+ env.Append(LIBS=['vulkan'])
+
+ env.Append(CCFLAGS=['-mmacosx-version-min=10.11'])
+ env.Append(LINKFLAGS=['-mmacosx-version-min=10.11'])
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index e6f8cbecf1..eacd2b5cc6 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -36,6 +36,12 @@
#include <unistd.h>
int main(int argc, char **argv) {
+
+#if defined(VULKAN_ENABLED)
+ //MoltenVK - enable full component swizzling support
+ setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
+#endif
+
int first_arg = 1;
const char *dbg_arg = "-NSDocumentRevisionsDebugMode";
printf("arguments\n");
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 190dbcf662..00fc56def6 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -46,6 +46,15 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "servers/visual_server.h"
+#if defined(OPENGL_ENABLED)
+#include "context_gl_osx.h"
+#endif
+
+#if defined(VULKAN_ENABLED)
+#include "drivers/vulkan/rendering_device_vulkan.h"
+#include "platform/osx/vulkan_context_osx.h"
+#endif
+
#include <AppKit/AppKit.h>
#include <AppKit/NSCursor.h>
#include <ApplicationServices/ApplicationServices.h>
@@ -93,7 +102,6 @@ public:
void process_events();
void process_key_events();
- void *framework;
// pthread_key_t current;
bool mouse_grab;
Point2 mouse_pos;
@@ -104,8 +112,15 @@ public:
id window_view;
id autoreleasePool;
id cursor;
- NSOpenGLPixelFormat *pixelFormat;
- NSOpenGLContext *context;
+
+#if defined(OPENGL_ENABLED)
+ ContextGL_OSX *context_gles2;
+#endif
+
+#if defined(VULKAN_ENABLED)
+ VulkanContextOSX *context_vulkan;
+ RenderingDeviceVulkan *rendering_device_vulkan;
+#endif
bool layered_window;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 43012220b6..5d2bc5172f 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -34,11 +34,19 @@
#include "core/print_string.h"
#include "core/version_generated.gen.h"
#include "dir_access_osx.h"
+
+#if defined(OPENGL_ENABLED)
#include "drivers/gles2/rasterizer_gles2.h"
-#include "drivers/gles3/rasterizer_gles3.h"
+#endif
+
+#if defined(VULKAN_ENABLED)
+#include "servers/visual/rasterizer_rd/rasterizer_rd.h"
+#endif
+
#include "main/main.h"
#include "semaphore_osx.h"
#include "servers/visual/visual_server_raster.h"
+#include "servers/visual/visual_server_wrap_mt.h"
#include <mach-o/dyld.h>
@@ -52,6 +60,9 @@
#include <os/log.h>
#endif
+#import <QuartzCore/CAMetalLayer.h>
+#include <vulkan/vulkan_metal.h>
+
#include <dlfcn.h>
#include <fcntl.h>
#include <libproc.h>
@@ -260,29 +271,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
return NSTerminateCancel;
}
-- (void)applicationDidHide:(NSNotification *)notification {
- /*
- _Godotwindow* window;
- for (window = _Godot.windowListHead; window; window = window->next)
- _GodotInputWindowVisibility(window, GL_FALSE);
-*/
-}
-
-- (void)applicationDidUnhide:(NSNotification *)notification {
- /*
- _Godotwindow* window;
-
- for (window = _Godot.windowListHead; window; window = window->next) {
- if ([window_object isVisible])
- _GodotInputWindowVisibility(window, GL_TRUE);
- }
-*/
-}
-
-- (void)applicationDidChangeScreenParameters:(NSNotification *)notification {
- //_GodotInputMonitorChange();
-}
-
- (void)showAbout:(id)sender {
if (OS_OSX::singleton->get_main_loop())
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
@@ -336,11 +324,16 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
NSWindow *window = (NSWindow *)[notification object];
CGFloat newBackingScaleFactor = [window backingScaleFactor];
CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
- if (OS_OSX::singleton->is_hidpi_allowed()) {
- [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES];
- } else {
- [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:NO];
+
+#if defined(OPENGL_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) {
+ if (OS_OSX::singleton->is_hidpi_allowed()) {
+ [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES];
+ } else {
+ [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:NO];
+ }
}
+#endif
if (newBackingScaleFactor != oldBackingScaleFactor) {
//Set new display scale and window size
@@ -361,8 +354,12 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidResize:(NSNotification *)notification {
- [OS_OSX::singleton->context update];
+#if defined(OPENGL_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) {
+ OS_OSX::singleton->context_gles2->update();
+ }
+#endif
const NSRect contentRect = [OS_OSX::singleton->window_view frame];
const NSRect fbRect = contentRect;
@@ -370,6 +367,14 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
OS_OSX::singleton->window_size.width = fbRect.size.width * displayScale;
OS_OSX::singleton->window_size.height = fbRect.size.height * displayScale;
+#if defined(VULKAN_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) {
+ CALayer* layer = [OS_OSX::singleton->window_view layer];
+ layer.contentsScale = OS_OSX::singleton->_display_scale();
+ OS_OSX::singleton->context_vulkan->window_resize(0, OS_OSX::singleton->window_size.width, OS_OSX::singleton->window_size.height);
+ }
+#endif
+
if (OS_OSX::singleton->main_loop) {
Main::force_redraw();
//Event retrieval blocks until resize is over. Call Main::iteration() directly.
@@ -377,15 +382,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
Main::iteration();
}
}
-
- /*
- _GodotInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
- _GodotInputWindowSize(window, contentRect.size.width, contentRect.size.height);
- _GodotInputWindowDamage(window);
-
- if (window->cursorMode == Godot_CURSOR_DISABLED)
- centerCursor(window);
-*/
}
- (void)windowDidMove:(NSNotification *)notification {
@@ -393,17 +389,6 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
if (OS_OSX::singleton->get_main_loop()) {
OS_OSX::singleton->input->release_pressed_events();
}
-
- /*
- [window->nsgl.context update];
-
- int x, y;
- _GodotPlatformGetWindowPos(window, &x, &y);
- _GodotInputWindowPos(window, x, y);
-
- if (window->cursorMode == Godot_CURSOR_DISABLED)
- centerCursor(window);
-*/
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
@@ -450,8 +435,12 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
bool imeInputEventInProgress;
}
- (void)cancelComposition;
+
+- (CALayer*)makeBackingLayer;
+
- (BOOL)wantsUpdateLayer;
- (void)updateLayer;
+
@end
@implementation GodotContentView
@@ -462,12 +451,32 @@ static NSCursor *cursorFromSelector(SEL selector, SEL fallback = nil) {
}
}
-- (BOOL)wantsUpdateLayer {
- return YES;
+- (CALayer*)makeBackingLayer {
+#if defined(VULKAN_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) {
+ CALayer* layer = [[CAMetalLayer class] layer];
+ layer.contentsScale = OS_OSX::singleton->_display_scale();
+ return layer;
+ }
+#endif
+ return [super makeBackingLayer];
}
- (void)updateLayer {
- [OS_OSX::singleton->context update];
+#if defined(VULKAN_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_VULKAN) {
+ [super updateLayer];
+ }
+#endif
+#if defined(OPENGL_ENABLED)
+ if (OS_OSX::singleton->video_driver_index == OS::VIDEO_DRIVER_GLES2) {
+ OS_OSX::singleton->context_gles2->update();
+ }
+#endif
+}
+
+- (BOOL)wantsUpdateLayer {
+ return YES;
}
- (id)init {
@@ -1458,6 +1467,14 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
// Register to be notified on displays arrangement changes
CGDisplayRegisterReconfigurationCallback(displays_arrangement_changed, NULL);
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //TODO - do Vulkan and GLES2 support checks, driver selection and fallback
+ video_driver_index = p_video_driver;
+ print_verbose("Driver: " + String(get_video_driver_name(video_driver_index)) + " [" + itos(video_driver_index) + "]");
+ //!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ //Create window
+
window_delegate = [[GodotWindowDelegate alloc] init];
// Don't use accumulation buffer support; it's not accelerated
@@ -1498,14 +1515,16 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
window_size.height = p_desired.height * displayScale;
if (displayScale > 1.0) {
- [window_view setWantsBestResolutionOpenGLSurface:YES];
- //if (current_videomode.resizable)
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ [window_view setWantsBestResolutionOpenGLSurface:YES];
+ }
+#endif
[window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
[window_view setWantsBestResolutionOpenGLSurface:NO];
}
- //[window_object setTitle:[NSString stringWithUTF8String:"GodotEnginies"]];
[window_object setContentView:window_view];
[window_object setDelegate:window_delegate];
[window_object setAcceptsMouseMovedEvents:YES];
@@ -1513,77 +1532,51 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
[window_object setRestorable:NO];
- unsigned int attributeCount = 0;
-
- // OS X needs non-zero color size, so set reasonable values
- int colorBits = 32;
+ // Init context and rendering device
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
- // Fail if a robustness strategy was requested
-
-#define ADD_ATTR(x) \
- { attributes[attributeCount++] = x; }
-#define ADD_ATTR2(x, y) \
- { \
- ADD_ATTR(x); \
- ADD_ATTR(y); \
- }
+ context_gles2 = memnew(ContextGL_OSX(window_view, false));
- // Arbitrary array size here
- NSOpenGLPixelFormatAttribute attributes[40];
+ if (context_gles2->initialize() != OK) {
+ memdelete(context_gles2);
+ context_gles2 = NULL;
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
- ADD_ATTR(NSOpenGLPFADoubleBuffer);
- ADD_ATTR(NSOpenGLPFAClosestPolicy);
+ context_gles2->set_use_vsync(p_desired.use_vsync);
- if (p_video_driver == VIDEO_DRIVER_GLES2) {
- ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy);
- } else {
- //we now need OpenGL 3 or better, maybe even change this to 3_3Core ?
- ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+ if (RasterizerGLES2::is_viable() == OK) {
+ RasterizerGLES2::register_config();
+ RasterizerGLES2::make_current();
+ } else {
+ memdelete(context_gles2);
+ context_gles2 = NULL;
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
}
+#endif
+#if defined(VULKAN_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_VULKAN) {
+
+ context_vulkan = memnew(VulkanContextOSX);
+ if (context_vulkan->initialize() != OK) {
+ memdelete(context_vulkan);
+ context_vulkan = NULL;
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
+ if (context_vulkan->window_create(window_view, get_video_mode().width, get_video_mode().height) == -1) {
+ memdelete(context_vulkan);
+ context_vulkan = NULL;
+ ERR_FAIL_V(ERR_UNAVAILABLE);
+ }
- ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
-
- /*
- if (fbconfig->alphaBits > 0)
- ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
-*/
-
- ADD_ATTR2(NSOpenGLPFADepthSize, 24);
-
- ADD_ATTR2(NSOpenGLPFAStencilSize, 8);
-
- /*
- if (fbconfig->stereo)
- ADD_ATTR(NSOpenGLPFAStereo);
-*/
+ rendering_device_vulkan = memnew(RenderingDeviceVulkan);
+ rendering_device_vulkan->initialize(context_vulkan);
- /*
- if (fbconfig->samples > 0) {
- ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
- ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
+ RasterizerRD::make_current();
}
-*/
-
- // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
- // framebuffer, so there's no need (and no way) to request it
-
- ADD_ATTR(0);
-
-#undef ADD_ATTR
-#undef ADD_ATTR2
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
- ERR_FAIL_COND_V(pixelFormat == nil, ERR_UNAVAILABLE);
-
- context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
-
- ERR_FAIL_COND_V(context == nil, ERR_UNAVAILABLE);
-
- [context setView:window_view];
-
- [context makeCurrentContext];
-
- set_use_vsync(p_desired.use_vsync);
+#endif
[NSApp activateIgnoringOtherApps:YES];
@@ -1594,53 +1587,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
if (p_desired.fullscreen)
zoomed = true;
- /*** END OSX INITIALIZATION ***/
-
- bool gles3 = true;
- if (p_video_driver == VIDEO_DRIVER_GLES2) {
- gles3 = false;
- }
-
- bool editor = Engine::get_singleton()->is_editor_hint();
- bool gl_initialization_error = false;
-
- while (true) {
- if (gles3) {
- if (RasterizerGLES3::is_viable() == OK) {
- RasterizerGLES3::register_config();
- RasterizerGLES3::make_current();
- break;
- } else {
- if (GLOBAL_GET("rendering/quality/driver/fallback_to_gles2") || editor) {
- p_video_driver = VIDEO_DRIVER_GLES2;
- gles3 = false;
- continue;
- } else {
- gl_initialization_error = true;
- break;
- }
- }
- } else {
- if (RasterizerGLES2::is_viable() == OK) {
- RasterizerGLES2::register_config();
- RasterizerGLES2::make_current();
- break;
- } else {
- gl_initialization_error = true;
- break;
- }
- }
- }
-
- if (gl_initialization_error) {
- OS::get_singleton()->alert("Your video card driver does not support any of the supported OpenGL versions.\n"
- "Please update your drivers or if you have a very old or integrated GPU upgrade it.",
- "Unable to initialize Video driver");
- return ERR_UNAVAILABLE;
- }
-
- video_driver_index = p_video_driver;
-
visual_server = memnew(VisualServerRaster);
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
@@ -1673,6 +1619,27 @@ void OS_OSX::finalize() {
midi_driver.close();
#endif
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+
+ if (context_gles2)
+ memdelete(context_gles2);
+ }
+#endif
+#if defined(VULKAN_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_VULKAN) {
+
+ if (rendering_device_vulkan) {
+ rendering_device_vulkan->finalize();
+ memdelete(rendering_device_vulkan);
+ }
+
+ if (context_vulkan)
+ memdelete(context_vulkan);
+
+ }
+#endif
+
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
@@ -1684,7 +1651,6 @@ void OS_OSX::finalize() {
cursors_cache.clear();
visual_server->finish();
memdelete(visual_server);
- //memdelete(rasterizer);
}
void OS_OSX::set_main_loop(MainLoop *p_main_loop) {
@@ -1916,7 +1882,6 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
image->lock();
- /* Premultiply the alpha channel */
for (int i = 0; i < len; i++) {
int row_index = floor(i / texture_size.width) + atlas_rect.position.y;
int column_index = (i % int(texture_size.width)) + atlas_rect.position.x;
@@ -1971,6 +1936,7 @@ void OS_OSX::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, c
cursors_cache.erase(p_shape);
}
+
}
void OS_OSX::set_mouse_show(bool p_show) {
@@ -2228,13 +2194,19 @@ String OS_OSX::get_clipboard() const {
}
void OS_OSX::release_rendering_thread() {
-
- [NSOpenGLContext clearCurrentContext];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->release_current();
+ }
+#endif
}
void OS_OSX::make_rendering_thread() {
-
- [context makeCurrentContext];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->make_current();
+ }
+#endif
}
Error OS_OSX::shell_open(String p_uri) {
@@ -2249,7 +2221,16 @@ String OS_OSX::get_locale() const {
}
void OS_OSX::swap_buffers() {
- [context flushBuffer];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->swap_buffers();
+ }
+#endif
+#if defined(VULKAN_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_VULKAN) {
+ context_vulkan->swap_buffers();
+ }
+#endif
}
void OS_OSX::wm_minimized(bool p_minimized) {
@@ -2659,21 +2640,31 @@ void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) {
if (layered_window != p_enabled) {
if (p_enabled) {
set_borderless_window(true);
- GLint opacity = 0;
[window_object setBackgroundColor:[NSColor clearColor]];
[window_object setOpaque:NO];
[window_object setHasShadow:NO];
- [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->set_opacity(0);
+ }
+#endif
layered_window = true;
} else {
- GLint opacity = 1;
[window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]];
[window_object setOpaque:YES];
[window_object setHasShadow:YES];
- [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->set_opacity(1);
+ }
+#endif
layered_window = false;
}
- [context update];
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ context_gles2->update();
+ }
+#endif
NSRect frame = [window_object frame];
[window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES];
[window_object setFrame:frame display:YES];
@@ -2992,11 +2983,20 @@ Error OS_OSX::move_to_trash(const String &p_path) {
}
void OS_OSX::_set_use_vsync(bool p_enable) {
+ // FIXME: Commented out during rebase of vulkan branch on master.
+ /*
CGLContextObj ctx = CGLGetCurrentContext();
if (ctx) {
GLint swapInterval = p_enable ? 1 : 0;
CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
}
+ */
+#if defined(OPENGL_ENABLED)
+ if (video_driver_index == VIDEO_DRIVER_GLES2) {
+ if (context_gles2)
+ context_gles2->set_use_vsync(p_enable);
+ }
+#endif
}
OS_OSX *OS_OSX::singleton = NULL;
@@ -3018,16 +3018,6 @@ OS_OSX::OS_OSX() {
CGEventSourceSetLocalEventsSuppressionInterval(eventSource, 0.0);
- /*
- if (pthread_key_create(&_Godot.nsgl.current, NULL) != 0) {
- _GodotInputError(Godot_PLATFORM_ERROR, "NSGL: Failed to create context TLS");
- return GL_FALSE;
- }
-*/
-
- framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- ERR_FAIL_COND(!framework);
-
// Implicitly create shared NSApplication instance
[GodotApplication sharedApplication];
diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h
new file mode 100644
index 0000000000..c048de509e
--- /dev/null
+++ b/platform/osx/vulkan_context_osx.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* vulkan_context_osx.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef VULKAN_DEVICE_OSX_H
+#define VULKAN_DEVICE_OSX_H
+
+#include "drivers/vulkan/vulkan_context.h"
+#include <AppKit/AppKit.h>
+
+class VulkanContextOSX : public VulkanContext {
+
+ virtual const char *_get_platform_surface_extension() const;
+
+public:
+ int window_create(id p_window, int p_width, int p_height);
+
+ VulkanContextOSX();
+ ~VulkanContextOSX();
+};
+
+#endif // VULKAN_DEVICE_OSX_H
diff --git a/platform/osx/vulkan_context_osx.mm b/platform/osx/vulkan_context_osx.mm
new file mode 100644
index 0000000000..b4c663062c
--- /dev/null
+++ b/platform/osx/vulkan_context_osx.mm
@@ -0,0 +1,56 @@
+/*************************************************************************/
+/* vulkan_context_osx.mm */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "vulkan_context_osx.h"
+#include <vulkan/vulkan_macos.h>
+
+const char *VulkanContextOSX::_get_platform_surface_extension() const {
+ return VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
+}
+
+int VulkanContextOSX::window_create(id p_window, int p_width, int p_height) {
+
+ VkMacOSSurfaceCreateInfoMVK createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.pView = p_window;
+
+ VkSurfaceKHR surface;
+ VkResult err = vkCreateMacOSSurfaceMVK(_get_instance(), &createInfo, NULL, &surface);
+ ERR_FAIL_COND_V(err, -1);
+ return _window_create(surface, p_width, p_height);
+}
+
+VulkanContextOSX::VulkanContextOSX() {
+}
+
+VulkanContextOSX::~VulkanContextOSX() {
+}