Browse Source

[macOS] Add support for OpenGLES3 video driver.

bruvzg 3 years ago
parent
commit
1ad14eb14b

+ 1 - 0
SConstruct

@@ -132,6 +132,7 @@ opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
 opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
 opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
 opts.Add(BoolVariable("vulkan", "Enable the vulkan video driver", True))
+opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 video driver", True))
 opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
 opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
 opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))

+ 1 - 1
platform/osx/SCsub

@@ -13,7 +13,7 @@ files = [
     "dir_access_osx.mm",
     "joypad_osx.cpp",
     "vulkan_context_osx.mm",
-    "context_gl_osx.mm",
+    "gl_manager_osx.mm",
 ]
 
 prog = env.add_program("#bin/godot", files)

+ 0 - 161
platform/osx/context_gl_osx.mm

@@ -1,161 +0,0 @@
-/*************************************************************************/
-/*  context_gl_osx.mm                                                    */
-/*************************************************************************/
-/*                       This file is part of:                           */
-/*                           GODOT ENGINE                                */
-/*                      https://godotengine.org                          */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
-/* Copyright (c) 2014-2021 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(GLES3_ENABLED) || defined(GLES_ENABLED)
-
-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() {
-	[context flushBuffer];
-}
-
-void ContextGL_OSX::set_use_vsync(bool p_use) {
-	CGLContextObj ctx = CGLGetCurrentContext();
-	if (ctx) {
-		GLint swapInterval = p_use ? 1 : 0;
-		CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
-		use_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 (!gles3_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];
-
-	return OK;
-}
-
-ContextGL_OSX::ContextGL_OSX(id p_view, bool p_gles3_context) {
-	gles3_context = p_gles3_context;
-	window_view = p_view;
-	use_vsync = false;
-}
-
-ContextGL_OSX::~ContextGL_OSX() {}
-
-#endif

+ 5 - 2
platform/osx/detect.py

@@ -183,10 +183,13 @@ def configure(env):
     )
     env.Append(LIBS=["pthread", "z"])
 
+    if env["opengl3"]:
+        env.Append(CPPDEFINES=["GLES_ENABLED", "GLES3_ENABLED"])
+        env.Append(CCFLAGS=["-Wno-deprecated-declarations"])  # Disable deprecation warnings
+        env.Append(LINKFLAGS=["-framework", "OpenGL"])
+
     if env["vulkan"]:
         env.Append(CPPDEFINES=["VULKAN_ENABLED"])
         env.Append(LINKFLAGS=["-framework", "Metal", "-framework", "QuartzCore", "-framework", "IOSurface"])
         if not env["use_volk"]:
             env.Append(LINKFLAGS=["-L$VULKAN_SDK_PATH/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/", "-lMoltenVK"])
-
-    # env.Append(CPPDEFINES=['GLES_ENABLED', 'GLES3_ENABLED'])

+ 5 - 8
platform/osx/display_server_osx.h

@@ -37,8 +37,7 @@
 #include "servers/display_server.h"
 
 #if defined(GLES3_ENABLED)
-#include "context_gl_osx.h"
-//TODO - reimplement OpenGLES
+#include "gl_manager_osx.h"
 #endif
 
 #if defined(VULKAN_ENABLED)
@@ -65,11 +64,11 @@ public:
 	void _menu_callback(id p_sender);
 
 #if defined(GLES3_ENABLED)
-	ContextGL_OSX *context_gles2;
+	GLManager_OSX *gl_manager = nullptr;
 #endif
 #if defined(VULKAN_ENABLED)
-	VulkanContextOSX *context_vulkan;
-	RenderingDeviceVulkan *rendering_device_vulkan;
+	VulkanContextOSX *context_vulkan = nullptr;
+	RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
 #endif
 
 	const NSMenu *_get_menu_root(const String &p_menu_root) const;
@@ -109,9 +108,6 @@ public:
 
 		Vector<Vector2> mpath;
 
-#if defined(GLES3_ENABLED)
-		ContextGL_OSX *context_gles2 = nullptr;
-#endif
 		Point2i mouse_pos;
 
 		Size2i min_size;
@@ -287,6 +283,7 @@ public:
 
 	virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
 	virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
+	virtual void gl_window_make_current(DisplayServer::WindowID p_window_id) override;
 
 	virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
 	virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;

+ 73 - 49
platform/osx/display_server_osx.mm

@@ -46,7 +46,7 @@
 #include <IOKit/hid/IOHIDLib.h>
 
 #if defined(GLES3_ENABLED)
-//TODO - reimplement OpenGLES
+#include "drivers/gles3/rasterizer_gles3.h"
 
 #import <AppKit/NSOpenGLView.h>
 #endif
@@ -167,8 +167,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
 	}
 
 #if defined(GLES3_ENABLED)
-	if (DS_OSX->rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (DS_OSX->rendering_driver == "opengl3") {
+		DS_OSX->gl_manager->window_destroy(window_id);
 	}
 #endif
 #ifdef VULKAN_ENABLED
@@ -272,8 +272,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
 	}
 
 #if defined(GLES3_ENABLED)
-	if (DS_OSX->rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (DS_OSX->rendering_driver == "opengl3") {
+		DS_OSX->gl_manager->window_resize(window_id, wd.size.width, wd.size.height);
 	}
 #endif
 #if defined(VULKAN_ENABLED)
@@ -377,7 +377,12 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
 /* GodotContentView                                                      */
 /*************************************************************************/
 
+#if defined(GLES3_ENABLED)
+@interface GodotContentView : NSOpenGLView <NSTextInputClient> {
+#else
 @interface GodotContentView : NSView <NSTextInputClient> {
+#endif
+
 	DisplayServerOSX::WindowID window_id;
 	NSTrackingArea *trackingArea;
 	NSMutableAttributedString *markedText;
@@ -405,12 +410,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
 }
 
 - (CALayer *)makeBackingLayer {
-#if defined(GLES3_ENABLED)
-	if (DS_OSX->rendering_driver == "opengl_es") {
-		CALayer *layer = [[NSOpenGLLayer class] layer];
-		return layer;
-	}
-#endif
 #if defined(VULKAN_ENABLED)
 	if (DS_OSX->rendering_driver == "vulkan") {
 		CALayer *layer = [[CAMetalLayer class] layer];
@@ -422,9 +421,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
 
 - (void)updateLayer {
 #if defined(GLES3_ENABLED)
-	if (DS_OSX->rendering_driver == "opengl_es") {
-		[super updateLayer];
-		//TODO - reimplement OpenGLES
+	if (DS_OSX->rendering_driver == "opengl3") {
+		DS_OSX->gl_manager->window_update(window_id);
 	}
 #endif
 #if defined(VULKAN_ENABLED)
@@ -2587,7 +2585,7 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
 			}
 #endif
 #if defined(GLES3_ENABLED)
-			if (rendering_driver == "opengl_es") {
+			if (rendering_driver == "opengl3") {
 				//TODO - reimplement OpenGLES
 			}
 #endif
@@ -2606,14 +2604,14 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
 			}
 #endif
 #if defined(GLES3_ENABLED)
-			if (rendering_driver == "opengl_es") {
+			if (rendering_driver == "opengl3") {
 				//TODO - reimplement OpenGLES
 			}
 #endif
 			wd.layered_window = false;
 		}
 #if defined(GLES3_ENABLED)
-		if (rendering_driver == "opengl_es") {
+		if (rendering_driver == "opengl3") {
 			//TODO - reimplement OpenGLES
 		}
 #endif
@@ -3455,18 +3453,31 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
 
 void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
 	_THREAD_SAFE_METHOD_
+#if defined(GLES3_ENABLED)
+	if (rendering_driver == "opengl3") {
+		gl_manager->swap_buffers();
+	}
+#endif
 #if defined(VULKAN_ENABLED)
-	context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+	if (rendering_driver == "vulkan") {
+		context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+	}
 #endif
 }
 
 DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const {
 	_THREAD_SAFE_METHOD_
+#if defined(GLES3_ENABLED)
+	if (rendering_driver == "opengl3") {
+		return (gl_manager->is_using_vsync() ? DisplayServer::VSyncMode::VSYNC_ENABLED : DisplayServer::VSyncMode::VSYNC_DISABLED);
+	}
+#endif
 #if defined(VULKAN_ENABLED)
-	return context_vulkan->get_vsync_mode(p_window);
-#else
-	return DisplayServer::VSYNC_ENABLED;
+	if (rendering_driver == "vulkan") {
+		return context_vulkan->get_vsync_mode(p_window);
+	}
 #endif
+	return DisplayServer::VSYNC_ENABLED;
 }
 
 Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
@@ -3476,12 +3487,18 @@ Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
 	drivers.push_back("vulkan");
 #endif
 #if defined(GLES3_ENABLED)
-	drivers.push_back("opengl_es");
+	drivers.push_back("opengl3");
 #endif
 
 	return drivers;
 }
 
+void DisplayServerOSX::gl_window_make_current(DisplayServer::WindowID p_window_id) {
+#if defined(GLES3_ENABLED)
+	gl_manager->window_make_current(p_window_id);
+#endif
+}
+
 Point2i DisplayServerOSX::ime_get_selection() const {
 	return im_selection;
 }
@@ -3522,7 +3539,7 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
 DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
 	DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
 	if (r_error != OK) {
-		OS::get_singleton()->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
+		OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.", "Unable to initialize Video driver");
 	}
 	return ds;
 }
@@ -3580,8 +3597,11 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V
 		}
 #endif
 #if defined(GLES3_ENABLED)
-		if (rendering_driver == "opengl_es") {
-			//TODO - reimplement OpenGLES
+		if (rendering_driver == "opengl3") {
+			if (gl_manager) {
+				Error err = gl_manager->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
+				ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context");
+			}
 		}
 #endif
 		id = window_id_counter++;
@@ -3601,8 +3621,8 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V
 	}
 
 #if defined(GLES3_ENABLED)
-	if (rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (rendering_driver == "opengl3") {
+		gl_manager->window_resize(id, wd.size.width, wd.size.height);
 	}
 #endif
 #if defined(VULKAN_ENABLED)
@@ -3654,15 +3674,15 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
 }
 
 void DisplayServerOSX::release_rendering_thread() {
-	//TODO - reimplement OpenGLES
 }
 
 void DisplayServerOSX::make_rendering_thread() {
-	//TODO - reimplement OpenGLES
 }
 
 void DisplayServerOSX::swap_buffers() {
-	//TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+	gl_manager->swap_buffers();
+#endif
 }
 
 void DisplayServerOSX::console_set_visible(bool p_enabled) {
@@ -3753,14 +3773,17 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
 	//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
 	rendering_driver = p_rendering_driver;
 
-#ifndef _MSC_VER
-#warning Forcing vulkan rendering driver because OpenGL not implemented yet
-#endif
-	rendering_driver = "vulkan";
-
 #if defined(GLES3_ENABLED)
-	if (rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (rendering_driver == "opengl3") {
+		GLManager_OSX::ContextType opengl_api_type = GLManager_OSX::GLES_3_0_COMPATIBLE;
+		gl_manager = memnew(GLManager_OSX(opengl_api_type));
+		if (gl_manager->initialize() != OK) {
+			memdelete(gl_manager);
+			gl_manager = nullptr;
+			r_error = ERR_UNAVAILABLE;
+			ERR_FAIL_MSG("Could not initialize OpenGL");
+			return;
+		}
 	}
 #endif
 #if defined(VULKAN_ENABLED)
@@ -3788,8 +3811,8 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
 	show_window(MAIN_WINDOW_ID);
 
 #if defined(GLES3_ENABLED)
-	if (rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (rendering_driver == "opengl3") {
+		RasterizerGLES3::make_current();
 	}
 #endif
 #if defined(VULKAN_ENABLED)
@@ -3821,20 +3844,21 @@ DisplayServerOSX::~DisplayServerOSX() {
 
 	//destroy drivers
 #if defined(GLES3_ENABLED)
-	if (rendering_driver == "opengl_es") {
-		//TODO - reimplement OpenGLES
+	if (gl_manager) {
+		memdelete(gl_manager);
+		gl_manager = nullptr;
 	}
 #endif
 #if defined(VULKAN_ENABLED)
-	if (rendering_driver == "vulkan") {
-		if (rendering_device_vulkan) {
-			rendering_device_vulkan->finalize();
-			memdelete(rendering_device_vulkan);
-		}
+	if (rendering_device_vulkan) {
+		rendering_device_vulkan->finalize();
+		memdelete(rendering_device_vulkan);
+		rendering_device_vulkan = nullptr;
+	}
 
-		if (context_vulkan) {
-			memdelete(context_vulkan);
-		}
+	if (context_vulkan) {
+		memdelete(context_vulkan);
+		context_vulkan = nullptr;
 	}
 #endif
 

+ 53 - 21
platform/osx/context_gl_osx.h → platform/osx/gl_manager_osx.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  context_gl_osx.h                                                     */
+/*  gl_manager_osx.h                                                     */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,47 +28,79 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef CONTEXT_GL_OSX_H
-#define CONTEXT_GL_OSX_H
+#ifndef GL_MANAGER_OSX_H
+#define GL_MANAGER_OSX_H
 
-#if defined(GLES3_ENABLED) || defined(GLES_ENABLED)
+#if defined(OSX_ENABLED) && defined(GLES3_ENABLED)
 
 #include "core/error/error_list.h"
 #include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "servers/display_server.h"
 
 #include <AppKit/AppKit.h>
 #include <ApplicationServices/ApplicationServices.h>
 #include <CoreVideo/CoreVideo.h>
 
-class ContextGL_OSX {
-	bool gles3_context;
-	bool use_vsync;
+class GLManager_OSX {
+public:
+	enum ContextType {
+		GLES_3_0_COMPATIBLE,
+	};
+
+private:
+	struct GLWindow {
+		GLWindow() { in_use = false; }
+		bool in_use;
+
+		DisplayServer::WindowID window_id;
+		int width;
+		int height;
+
+		id window_view;
+		NSOpenGLContext *context;
+	};
+
+	LocalVector<GLWindow> _windows;
+
+	NSOpenGLContext *_shared_context = nullptr;
+	GLWindow *_current_window;
+
+	Error _create_context(GLWindow &win);
+	void _internal_set_current_window(GLWindow *p_win);
 
-	void *framework;
-	id window_view;
-	NSOpenGLPixelFormat *pixelFormat;
-	NSOpenGLContext *context;
+	GLWindow &get_window(unsigned int id) { return _windows[id]; }
+	const GLWindow &get_window(unsigned int id) const { return _windows[id]; }
+
+	bool use_vsync;
+	ContextType context_type;
 
 public:
-	void release_current();
+	Error window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height);
+	void window_destroy(DisplayServer::WindowID p_window_id);
+	void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
+
+	// get directly from the cached GLWindow
+	int window_get_width(DisplayServer::WindowID p_window_id = 0);
+	int window_get_height(DisplayServer::WindowID p_window_id = 0);
 
+	void release_current();
 	void make_current();
-	void update();
+	void swap_buffers();
 
-	void set_opacity(GLint p_opacity);
+	void window_make_current(DisplayServer::WindowID p_window_id);
 
-	int get_window_width();
-	int get_window_height();
-	void swap_buffers();
+	void window_update(DisplayServer::WindowID p_window_id);
 
 	Error initialize();
 
 	void set_use_vsync(bool p_use);
 	bool is_using_vsync() const;
 
-	ContextGL_OSX(id p_view, bool p_gles3_context);
-	~ContextGL_OSX();
+	GLManager_OSX(ContextType p_context_type);
+	~GLManager_OSX();
 };
 
-#endif
-#endif
+#endif // defined(OSX_ENABLED) && defined(GLES3_ENABLED)
+
+#endif // GL_MANAGER_OSX_H

+ 233 - 0
platform/osx/gl_manager_osx.mm

@@ -0,0 +1,233 @@
+/*************************************************************************/
+/*  gl_manager_osx.mm                                                    */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 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 "gl_manager_osx.h"
+
+#ifdef OSX_ENABLED
+#ifdef GLES3_ENABLED
+
+#include <stdio.h>
+#include <stdlib.h>
+
+Error GLManager_OSX::_create_context(GLWindow &win) {
+	NSOpenGLPixelFormatAttribute attributes[] = {
+		NSOpenGLPFADoubleBuffer,
+		NSOpenGLPFAClosestPolicy,
+		NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+		NSOpenGLPFAColorSize, 32,
+		NSOpenGLPFADepthSize, 24,
+		NSOpenGLPFAStencilSize, 8,
+		0
+	};
+
+	NSOpenGLPixelFormat *pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+	ERR_FAIL_COND_V(pixel_format == nil, ERR_CANT_CREATE);
+
+	win.context = [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:_shared_context];
+	ERR_FAIL_COND_V(win.context == nil, ERR_CANT_CREATE);
+	if (_shared_context == nullptr) {
+		_shared_context = win.context;
+	}
+
+	[win.context setView:win.window_view];
+	[win.context makeCurrentContext];
+
+	return OK;
+}
+
+Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
+	if (p_window_id >= (int)_windows.size()) {
+		_windows.resize(p_window_id + 1);
+	}
+
+	GLWindow &win = _windows[p_window_id];
+	win.in_use = true;
+	win.window_id = p_window_id;
+	win.width = p_width;
+	win.height = p_height;
+	win.window_view = p_view;
+
+	if (_create_context(win) != OK) {
+		_windows.remove(_windows.size() - 1);
+		return FAILED;
+	}
+
+	window_make_current(_windows.size() - 1);
+
+	return OK;
+}
+
+void GLManager_OSX::_internal_set_current_window(GLWindow *p_win) {
+	_current_window = p_win;
+}
+
+void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
+	if (p_window_id == -1) {
+		return;
+	}
+
+	GLWindow &win = _windows[p_window_id];
+	if (!win.in_use) {
+		return;
+	}
+
+	win.width = p_width;
+	win.height = p_height;
+
+	GLint dim[2];
+	dim[0] = p_width;
+	dim[1] = p_height;
+	CGLSetParameter((CGLContextObj)[win.context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]);
+	CGLEnable((CGLContextObj)[win.context CGLContextObj], kCGLCESurfaceBackingSize);
+	if (OS::get_singleton()->is_hidpi_allowed()) {
+		[win.window_view setWantsBestResolutionOpenGLSurface:YES];
+	} else {
+		[win.window_view setWantsBestResolutionOpenGLSurface:NO];
+	}
+
+	[win.context update];
+}
+
+int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) {
+	return get_window(p_window_id).width;
+}
+
+int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) {
+	return get_window(p_window_id).height;
+}
+
+void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) {
+	GLWindow &win = get_window(p_window_id);
+	win.in_use = false;
+
+	if (_current_window == &win) {
+		_current_window = nullptr;
+	}
+}
+
+void GLManager_OSX::release_current() {
+	if (!_current_window) {
+		return;
+	}
+
+	[NSOpenGLContext clearCurrentContext];
+}
+
+void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) {
+	if (p_window_id == -1) {
+		return;
+	}
+
+	GLWindow &win = _windows[p_window_id];
+	if (!win.in_use) {
+		return;
+	}
+
+	if (&win == _current_window) {
+		return;
+	}
+
+	[win.context makeCurrentContext];
+
+	_internal_set_current_window(&win);
+}
+
+void GLManager_OSX::make_current() {
+	if (!_current_window) {
+		return;
+	}
+	if (!_current_window->in_use) {
+		WARN_PRINT("current window not in use!");
+		return;
+	}
+	[_current_window->context makeCurrentContext];
+}
+
+void GLManager_OSX::swap_buffers() {
+	// NO NEED TO CALL SWAP BUFFERS for each window...
+	// see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml
+
+	if (!_current_window) {
+		return;
+	}
+	if (!_current_window->in_use) {
+		WARN_PRINT("current window not in use!");
+		return;
+	}
+	[_current_window->context flushBuffer];
+}
+
+void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) {
+	if (p_window_id == -1) {
+		return;
+	}
+
+	GLWindow &win = _windows[p_window_id];
+	if (!win.in_use) {
+		return;
+	}
+
+	if (&win == _current_window) {
+		return;
+	}
+
+	[win.context update];
+}
+
+Error GLManager_OSX::initialize() {
+	return OK;
+}
+
+void GLManager_OSX::set_use_vsync(bool p_use) {
+	use_vsync = p_use;
+	CGLContextObj ctx = CGLGetCurrentContext();
+	if (ctx) {
+		GLint swapInterval = p_use ? 1 : 0;
+		CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
+		use_vsync = p_use;
+	}
+}
+
+bool GLManager_OSX::is_using_vsync() const {
+	return use_vsync;
+}
+
+GLManager_OSX::GLManager_OSX(ContextType p_context_type) {
+	context_type = p_context_type;
+	use_vsync = false;
+	_current_window = nullptr;
+}
+
+GLManager_OSX::~GLManager_OSX() {
+	release_current();
+}
+
+#endif // GLES3_ENABLED
+#endif // OSX