diff --git a/gfx/drivers_context/cocoa_gl_ctx.m b/gfx/drivers_context/cocoa_gl_ctx.m index 815b850fbc..0ce078e8cc 100644 --- a/gfx/drivers_context/cocoa_gl_ctx.m +++ b/gfx/drivers_context/cocoa_gl_ctx.m @@ -23,24 +23,38 @@ #else #include #endif -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) + +#ifdef HAVE_OPENGL #include #include -#include #include +#endif + +#include #elif defined(HAVE_COCOATOUCH) + +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) #include #endif +#endif + #include #include +#include "../../ui/drivers/ui_cocoa.h" #import "../../ui/drivers/cocoa/cocoa_common.h" #include "../video_driver.h" #include "../../configuration.h" #include "../../verbosity.h" +#ifdef HAVE_VULKAN +#include "../common/vulkan_common.h" +#endif + #if defined(HAVE_COCOATOUCH) + #define GLContextClass EAGLContext #define GLFrameworkID CFSTR("com.apple.opengles") #define RAScreen UIScreen @@ -53,11 +67,13 @@ #define UIUserInterfaceIdiomCarPlay 3 #endif +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) @interface EAGLContext (OSXCompat) @end @implementation EAGLContext (OSXCompat) + (void)clearCurrentContext { [EAGLContext setCurrentContext:nil]; } - (void)makeCurrentContext { [EAGLContext setCurrentContext:self]; } @end +#endif #else @@ -81,30 +97,38 @@ static enum gfx_ctx_api cocoagl_api = GFX_CTX_NONE; typedef struct cocoa_ctx_data { bool core_hw_context_enable; +#ifdef HAVE_VULKAN + gfx_ctx_vulkan_data_t vk; + int swap_interval; +#endif + unsigned width; + unsigned height; } cocoa_ctx_data_t; #if defined(HAVE_COCOATOUCH) - -static GLKView *g_view; UIView *g_pause_indicator_view; #endif +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) static GLContextClass* g_hw_ctx; static GLContextClass* g_context; +#if defined(HAVE_COCOATOUCH) +static GLKView *g_view; +#endif static int g_fast_forward_skips; static bool g_is_syncing = true; static bool g_use_hw_ctx = false; -#if defined(HAVE_COCOA) -#include "../../ui/drivers/ui_cocoa.h" +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) static NSOpenGLPixelFormat* g_format; void *glcontext_get_ptr(void) { - return g_context; + return (BRIDGE void*)g_context; } #endif +#endif static unsigned g_minor = 0; static unsigned g_major = 0; @@ -112,20 +136,14 @@ static unsigned g_major = 0; /* forward declaration */ void *nsview_get_ptr(void); -#if defined(HAVE_COCOATOUCH) -static void glkitview_init_xibs(void) -{ - /* iOS Pause menu and lifecycle. */ - UINib *xib = (UINib*)[UINib nibWithNibName:BOXSTRING("PauseIndicatorView") bundle:nil]; - g_pause_indicator_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject]; -} -#endif - +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) void *glkitview_init(void) { #if defined(HAVE_COCOATOUCH) #if TARGET_OS_IOS - glkitview_init_xibs(); + /* iOS Pause menu and lifecycle. */ + UINib *xib = (UINib*)[UINib nibWithNibName:BOXSTRING("PauseIndicatorView") bundle:nil]; + g_pause_indicator_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject]; #endif g_view = [GLKView new]; @@ -148,8 +166,10 @@ void cocoagl_bind_game_view_fbo(void) [g_view bindDrawable]; } #endif +#endif -static float get_from_selector(Class obj_class, id obj_id, SEL selector, CGFloat *ret) +static float get_from_selector(Class obj_class, id obj_id, + SEL selector, CGFloat *ret) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [obj_class instanceMethodSignatureForSelector:selector]]; @@ -157,10 +177,7 @@ static float get_from_selector(Class obj_class, id obj_id, SEL selector, CGFloat [invocation setTarget:obj_id]; [invocation invoke]; [invocation getReturnValue:ret]; -#if __has_feature(objc_arc) -#else - [invocation release]; -#endif + RELEASE(invocation); return *ret; } @@ -192,7 +209,7 @@ float get_backing_scale_factor(void) return backing_scale_def; backing_scale_def = 1.0f; -#ifdef HAVE_COCOA +#ifdef HAVE_COCOA || defined(HAVE_COCOA_METAL) screen = (BRIDGE RAScreen*)get_chosen_screen(); if (screen) @@ -201,7 +218,11 @@ float get_backing_scale_factor(void) if ([screen respondsToSelector:selector]) { CGFloat ret; +#if defined(HAVE_COCOA_METAL) + NSView *g_view = apple_platform.renderView; +#else CocoaView *g_view = (CocoaView*)nsview_get_ptr(); +#endif backing_scale_def = (float)get_from_selector ([[g_view window] class], [g_view window], selector, &ret); } @@ -213,18 +234,28 @@ float get_backing_scale_factor(void) void cocoagl_gfx_ctx_update(void) { -#if defined(HAVE_COCOA) + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) #if MAC_OS_X_VERSION_10_7 - CGLUpdateContext(g_hw_ctx.CGLContextObj); - CGLUpdateContext(g_context.CGLContextObj); + CGLUpdateContext(g_hw_ctx.CGLContextObj); + CGLUpdateContext(g_context.CGLContextObj); #else - [g_hw_ctx update]; - [g_context update]; + [g_hw_ctx update]; + [g_context update]; #endif #endif +#endif + break; + default: + break; + } } -static void *cocoagl_gfx_ctx_init(video_frame_info_t *video_info, void *video_driver) +static void *cocoagl_gfx_ctx_init( + video_frame_info_t *video_info, void *video_driver) { cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*) calloc(1, sizeof(cocoa_ctx_data_t)); @@ -232,6 +263,32 @@ static void *cocoagl_gfx_ctx_init(video_frame_info_t *video_info, void *video_dr if (!cocoa_ctx) return NULL; + switch (cocoagl_api) + { +#if defined(HAVE_COCOATOUCH) + case GFX_CTX_OPENGL_ES_API: + // setViewType is not (yet?) defined for iOS + // [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL_ES]; + break; +#elif defined(HAVE_COCOA_METAL) + case GFX_CTX_OPENGL_API: + [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL]; + break; +#endif + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + [apple_platform setViewType:APPLE_VIEW_TYPE_VULKAN]; + if (!vulkan_context_init(&cocoa_ctx->vk, VULKAN_WSI_MVK_MACOS)) + { + goto error; + } +#endif + break; + case GFX_CTX_NONE: + default: + break; + } + return cocoa_ctx; } @@ -242,25 +299,40 @@ static void cocoagl_gfx_ctx_destroy(void *data) if (!cocoa_ctx) return; - [GLContextClass clearCurrentContext]; + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) + [GLContextClass clearCurrentContext]; +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) + [g_context clearDrawable]; + if (g_hw_ctx) + [g_hw_ctx clearDrawable]; + RELEASE(g_context); + RELEASE(g_format); + RELEASE(g_hw_ctx); -#if defined(HAVE_COCOA) - [g_context clearDrawable]; - if (g_context) - [g_context release]; - g_context = nil; - if (g_format) - [g_format release]; - g_format = nil; - if (g_hw_ctx) - { - [g_hw_ctx clearDrawable]; - [g_hw_ctx release]; - } - g_hw_ctx = nil; #endif - [GLContextClass clearCurrentContext]; - g_context = nil; + [GLContextClass clearCurrentContext]; + g_context = nil; + g_format = nil; + g_hw_ctx = nil; +#endif + break; + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + vulkan_context_destroy(&cocoa_ctx->vk, cocoa_ctx->vk.vk_surface != VK_NULL_HANDLE); + if (cocoa_ctx->vk.context.queue_lock) + slock_free(cocoa_ctx->vk.context.queue_lock); + memset(&cocoa_ctx->vk, 0, sizeof(cocoa_ctx->vk)); + +#endif + break; + case GFX_CTX_NONE: + default: + break; + } free(cocoa_ctx); } @@ -270,16 +342,28 @@ static enum gfx_ctx_api cocoagl_gfx_ctx_get_api(void *data) return cocoagl_api; } -static bool cocoagl_gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor) +static bool cocoagl_gfx_ctx_bind_api(void *data, + enum gfx_ctx_api api, unsigned major, unsigned minor) { (void)data; + + switch (api) + { #if defined(HAVE_COCOATOUCH) - if (api != GFX_CTX_OPENGL_ES_API) - return false; -#elif defined(HAVE_COCOA) - if (api != GFX_CTX_OPENGL_API) - return false; + case GFX_CTX_OPENGL_ES_API: + break; +#elif defined(HAVE_COCOA_METAL) + case GFX_CTX_OPENGL_API: + break; +#ifdef HAVE_VULKAN + case GFX_CTX_VULKAN_API: + break; #endif +#endif + case GFX_CTX_NONE: + default: + return false; + } cocoagl_api = api; g_minor = minor; @@ -290,24 +374,47 @@ static bool cocoagl_gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned static void cocoagl_gfx_ctx_swap_interval(void *data, int i) { - (void)data; + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; unsigned interval = (unsigned)i; -#if defined(HAVE_COCOATOUCH) // < No way to disable Vsync on iOS? - // Just skip presents so fast forward still works. - g_is_syncing = interval ? true : false; - g_fast_forward_skips = interval ? 0 : 3; -#elif defined(HAVE_COCOA) - GLint value = interval ? 1 : 0; - [g_context setValues:&value forParameter:NSOpenGLCPSwapInterval]; + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: + { +#if defined(HAVE_COCOATOUCH) + /* < No way to disable Vsync on iOS? + * Just skip presents so fast forward still works. */ + g_is_syncing = interval ? true : false; + g_fast_forward_skips = interval ? 0 : 3; +#elif defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) + GLint value = interval ? 1 : 0; + [g_context setValues:&value forParameter:NSOpenGLCPSwapInterval]; #endif + break; + } + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + if (cocoa_ctx->swap_interval != interval) + { + cocoa_ctx->swap_interval = interval; + if (cocoa_ctx->vk.swapchain) + cocoa_ctx->vk.need_new_swapchain = true; + } +#endif + break; + case GFX_CTX_NONE: + default: + break; + } + } static void cocoagl_gfx_ctx_show_mouse(void *data, bool state) { (void)data; -#ifdef HAVE_COCOA +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) if (state) [NSCursor unhide]; else @@ -319,65 +426,101 @@ static bool cocoagl_gfx_ctx_set_video_mode(void *data, video_frame_info_t *video_info, unsigned width, unsigned height, bool fullscreen) { + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; #if defined(HAVE_COCOA) - CocoaView *g_view = (CocoaView*)nsview_get_ptr(); - if ([g_view respondsToSelector: @selector(setWantsBestResolutionOpenGLSurface:)]) - [g_view setWantsBestResolutionOpenGLSurface:YES]; + CocoaView *g_view = (CocoaView*)nsview_get_ptr(); +#elif defined(HAVE_COCOA_METAL) + NSView *g_view = apple_platform.renderView; +#endif - NSOpenGLPixelFormatAttribute attributes [] = { - NSOpenGLPFAColorSize, - 24, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAllowOfflineRenderers, - NSOpenGLPFADepthSize, - (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer - 0, /* profile */ - 0, /* profile enum */ - (NSOpenGLPixelFormatAttribute)0 - }; + cocoa_ctx->width = width; + cocoa_ctx->height = height; + + + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) + { +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) + if ([g_view respondsToSelector: @selector(setWantsBestResolutionOpenGLSurface:)]) + [g_view setWantsBestResolutionOpenGLSurface:YES]; + + NSOpenGLPixelFormatAttribute attributes [] = { + NSOpenGLPFAColorSize, + 24, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAllowOfflineRenderers, + NSOpenGLPFADepthSize, + (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer + 0, /* profile */ + 0, /* profile enum */ + (NSOpenGLPixelFormatAttribute)0 + }; #if MAC_OS_X_VERSION_10_7 - if (g_major == 3 && (g_minor >= 1 && g_minor <= 3)) - { - attributes[6] = NSOpenGLPFAOpenGLProfile; - attributes[7] = NSOpenGLProfileVersion3_2Core; - } + if (g_major == 3 && (g_minor >= 1 && g_minor <= 3)) + { + attributes[6] = NSOpenGLPFAOpenGLProfile; + attributes[7] = NSOpenGLProfileVersion3_2Core; + } #endif #if MAC_OS_X_VERSION_10_10 - if (g_major == 4 && g_minor == 1) - { - attributes[6] = NSOpenGLPFAOpenGLProfile; - attributes[7] = NSOpenGLProfileVersion4_1Core; - } + if (g_major == 4 && g_minor == 1) + { + attributes[6] = NSOpenGLPFAOpenGLProfile; + attributes[7] = NSOpenGLProfileVersion4_1Core; + } #endif - g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (g_format == nil) - { - /* NSOpenGLFPAAllowOfflineRenderers is - not supported on this OS version. */ - attributes[3] = (NSOpenGLPixelFormatAttribute)0; - g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - } + if (g_format == nil) + { + /* NSOpenGLFPAAllowOfflineRenderers is + not supported on this OS version. */ + attributes[3] = (NSOpenGLPixelFormatAttribute)0; + g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + } #endif - if (g_use_hw_ctx) - g_hw_ctx = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil]; - g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:(g_use_hw_ctx) ? g_hw_ctx : nil]; - [g_context setView:g_view]; + if (g_use_hw_ctx) + g_hw_ctx = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil]; + g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:(g_use_hw_ctx) ? g_hw_ctx : nil]; + [g_context setView:g_view]; #else - if (g_use_hw_ctx) - g_hw_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - g_view.context = g_context; + if (g_use_hw_ctx) + g_hw_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + g_view.context = g_context; #endif - [g_context makeCurrentContext]; + [g_context makeCurrentContext]; +#endif + break; + } + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + RARCH_LOG("[macOS]: Native window size: %u x %u.\n", cocoa_ctx->width, cocoa_ctx->height); + if (!vulkan_surface_create(&cocoa_ctx->vk, + VULKAN_WSI_MVK_MACOS, NULL, + (BRIDGE void *)g_view, cocoa_ctx->width, cocoa_ctx->height, + cocoa_ctx->swap_interval)) + { + RARCH_ERR("[macOS]: Failed to create surface.\n"); + return false; + } +#endif + break; + case GFX_CTX_NONE: + default: + break; + } -#if defined(HAVE_COCOA) +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) static bool has_went_fullscreen = false; /* TODO: Screen mode support. */ @@ -436,9 +579,13 @@ static void cocoagl_gfx_ctx_get_video_size(void *data, unsigned* width, unsigned { float screenscale = cocoagl_gfx_ctx_get_native_scale(); #if defined(HAVE_COCOA) + CocoaView *g_view = (CocoaView*)nsview_get_ptr(); +#elif defined(HAVE_COCOA_METAL) + NSView *g_view = apple_platform.renderView; +#endif +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) CGRect size; GLsizei backingPixelWidth, backingPixelHeight; - CocoaView *g_view = (CocoaView*)nsview_get_ptr(); CGRect cgrect = NSRectToCGRect([g_view frame]); #if MAC_OS_X_VERSION_10_7 SEL selector = NSSelectorFromString(BOXSTRING("convertRectToBacking:")); @@ -455,13 +602,17 @@ static void cocoagl_gfx_ctx_get_video_size(void *data, unsigned* width, unsigned *height = CGRectGetHeight(size) * screenscale; } -#if defined(HAVE_COCOA) static void cocoagl_gfx_ctx_update_title(void *data, void *data2) { +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) ui_window_cocoa_t view; const ui_window_t *window = ui_companion_driver_get_window_ptr(); - view.data = (CocoaView*)nsview_get_ptr(); +#if defined(HAVE_COCOA) + view.data = (CocoaView*)nsview_get_ptr(); +#elif defined(HAVE_COCOA_METAL) + view.data = (BRIDGE void *)apple_platform.renderView; +#endif if (window) { @@ -474,11 +625,12 @@ static void cocoagl_gfx_ctx_update_title(void *data, void *data2) if (title[0]) window->set_title(&view, title); } -} #endif +} -static bool cocoagl_gfx_ctx_get_metrics(void *data, enum display_metric_types type, - float *value) +static bool cocoagl_gfx_ctx_get_metrics(void *data, + enum display_metric_types type, + float *value) { RAScreen *screen = (BRIDGE RAScreen*)get_chosen_screen(); #if defined(HAVE_COCOA) @@ -567,36 +719,95 @@ static bool cocoagl_gfx_ctx_has_windowed(void *data) } #endif -static void cocoagl_gfx_ctx_swap_buffers(void *data, void *data2) +#ifdef HAVE_VULKAN +static void *cocoagl_gfx_ctx_get_context_data(void *data) { - if (!(--g_fast_forward_skips < 0)) - return; - -#if defined(HAVE_COCOA) - [g_context flushBuffer]; - [g_hw_ctx flushBuffer]; -#elif defined(HAVE_COCOATOUCH) - if (g_view) - [g_view display]; + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; + return &cocoa_ctx->vk.context; +} #endif - g_fast_forward_skips = g_is_syncing ? 0 : 3; +static void cocoagl_gfx_ctx_swap_buffers(void *data, void *data2) +{ + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; + + (void)cocoa_ctx; + + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) + if (!(--g_fast_forward_skips < 0)) + return; + +#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) + [g_context flushBuffer]; + [g_hw_ctx flushBuffer]; +#elif defined(HAVE_COCOATOUCH) + if (g_view) + [g_view display]; +#endif + + g_fast_forward_skips = g_is_syncing ? 0 : 3; +#endif + break; + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + vulkan_present(&cocoa_ctx->vk, cocoa_ctx->vk.context.current_swapchain_index); + vulkan_acquire_next_image(&cocoa_ctx->vk); +#endif + break; + case GFX_CTX_NONE: + default: + break; + } } static gfx_ctx_proc_t cocoagl_gfx_ctx_get_proc_address(const char *symbol_name) { - return (gfx_ctx_proc_t)CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(GLFrameworkID), - (BRIDGE CFStringRef)BOXSTRING(symbol_name) - ); + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: +#ifdef (HAVE_OPENGL) || defined(HAVE_OPENGLES) + return (gfx_ctx_proc_t) + CFBundleGetFunctionPointerForName( + CFBundleGetBundleWithIdentifier(GLFrameworkID), + (BRIDGE CFStringRef)BOXSTRING(symbol_name) + ); +#endif + case GFX_CTX_NONE: + default: + break; + } + + return NULL; } static void cocoagl_gfx_ctx_check_window(void *data, bool *quit, bool *resize, unsigned *width, unsigned *height, bool is_shutdown) { unsigned new_width, new_height; + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; *quit = false; + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: + break; + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + *resize = cocoa_ctx->vk.need_new_swapchain; +#endif + break; + case GFX_CTX_NONE: + default: + break; + } + cocoagl_gfx_ctx_get_video_size(data, &new_width, &new_height); if (new_width != *width || new_height != *height) { @@ -617,12 +828,23 @@ static void cocoagl_gfx_ctx_input_driver(void *data, static void cocoagl_gfx_ctx_bind_hw_render(void *data, bool enable) { (void)data; - g_use_hw_ctx = enable; + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: +#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) + g_use_hw_ctx = enable; - if (enable) - [g_hw_ctx makeCurrentContext]; - else - [g_context makeCurrentContext]; + if (enable) + [g_hw_ctx makeCurrentContext]; + else + [g_context makeCurrentContext]; +#endif + break; + case GFX_CTX_NONE: + default: + break; + } } static uint32_t cocoagl_gfx_ctx_get_flags(void *data) @@ -647,6 +869,45 @@ static void cocoagl_gfx_ctx_set_flags(void *data, uint32_t flags) cocoa_ctx->core_hw_context_enable = true; } +static bool cocoagl_gfx_ctx_set_resize( + void *data, unsigned width, unsigned height) +{ + cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; + + switch (cocoagl_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: + break; + case GFX_CTX_VULKAN_API: +#ifdef HAVE_VULKAN + cocoa_ctx->width = width; + cocoa_ctx->height = height; + + if (vulkan_create_swapchain(&cocoa_ctx->vk, + width, height, cocoa_ctx->swap_interval)) + { + cocoa_ctx->vk.context.invalid_swapchain = true; + if (cocoa_ctx->vk.created_new_swapchain) + vulkan_acquire_next_image(&cocoa_ctx->vk); + } + else + { + RARCH_ERR("[macOS/Vulkan]: Failed to update swapchain.\n"); + return false; + } + + cocoa_ctx->vk.need_new_swapchain = false; +#endif + break; + case GFX_CTX_NONE: + default: + break; + } + + return true; +} + const gfx_ctx_driver_t gfx_ctx_cocoagl = { cocoagl_gfx_ctx_init, cocoagl_gfx_ctx_destroy, @@ -667,7 +928,7 @@ const gfx_ctx_driver_t gfx_ctx_cocoagl = { NULL, /* update_title */ #endif cocoagl_gfx_ctx_check_window, - NULL, /* set_resize */ + cocoagl_gfx_ctx_set_resize, cocoagl_gfx_ctx_has_focus, cocoagl_gfx_ctx_suppress_screensaver, #if defined(HAVE_COCOATOUCH) @@ -685,6 +946,10 @@ const gfx_ctx_driver_t gfx_ctx_cocoagl = { cocoagl_gfx_ctx_get_flags, cocoagl_gfx_ctx_set_flags, cocoagl_gfx_ctx_bind_hw_render, +#if defined(HAVE_VULKAN) + cocoagl_gfx_ctx_get_context_data, +#else NULL, +#endif NULL }; diff --git a/gfx/drivers_context/cocoa_gl_ctx_metal.m b/gfx/drivers_context/cocoa_gl_ctx_metal.m deleted file mode 100644 index 3cd1fede81..0000000000 --- a/gfx/drivers_context/cocoa_gl_ctx_metal.m +++ /dev/null @@ -1,906 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2018 - Stuart Carnie - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#ifdef HAVE_CONFIG_H -#include "../../config.h" -#endif - -#if TARGET_OS_IPHONE -#include -#else -#include -#endif -#if defined(HAVE_COCOA_METAL) -#include -#include -#include -#include -#elif defined(HAVE_COCOATOUCH) -#include -#endif - -#include -#include - -#import "../../ui/drivers/cocoa/cocoa_common.h" -#include "../video_driver.h" -#include "../../configuration.h" -#include "../../verbosity.h" -#ifdef HAVE_VULKAN -#include "../common/vulkan_common.h" -#endif - -#if defined(HAVE_COCOATOUCH) -#define GLContextClass EAGLContext -#define GLFrameworkID CFSTR("com.apple.opengles") -#define RAScreen UIScreen - -#ifndef UIUserInterfaceIdiomTV -#define UIUserInterfaceIdiomTV 2 -#endif - -#ifndef UIUserInterfaceIdiomCarPlay -#define UIUserInterfaceIdiomCarPlay 3 -#endif - -@interface EAGLContext (OSXCompat) @end -@implementation EAGLContext (OSXCompat) -+ (void)clearCurrentContext { [EAGLContext setCurrentContext:nil]; } -- (void)makeCurrentContext { [EAGLContext setCurrentContext:self]; } -@end - -#else - -@interface NSScreen (IOSCompat) @end -@implementation NSScreen (IOSCompat) -- (CGRect)bounds -{ - CGRect cgrect = NSRectToCGRect(self.frame); - return CGRectMake(0, 0, CGRectGetWidth(cgrect), CGRectGetHeight(cgrect)); -} -- (float) scale { return 1.0f; } -@end - -#define GLContextClass NSOpenGLContext -#define GLFrameworkID CFSTR("com.apple.opengl") -#define RAScreen NSScreen -#endif - -static enum gfx_ctx_api cocoagl_api = GFX_CTX_NONE; - -typedef struct cocoa_ctx_data -{ - bool core_hw_context_enable; -#ifdef HAVE_VULKAN - gfx_ctx_vulkan_data_t vk; - int swap_interval; -#endif - unsigned width; - unsigned height; -} cocoa_ctx_data_t; - -#if defined(HAVE_COCOATOUCH) - -static GLKView *g_view; -UIView *g_pause_indicator_view; -#endif - -static GLContextClass* g_hw_ctx; -static GLContextClass* g_context; - -static int g_fast_forward_skips; -static bool g_is_syncing = true; -static bool g_use_hw_ctx = false; - -#include "../../ui/drivers/ui_cocoa.h" - -#if defined(HAVE_COCOA_METAL) -static NSOpenGLPixelFormat* g_format; - -void *glcontext_get_ptr(void) -{ - return (BRIDGE void *)g_context; -} -#endif - -static unsigned g_minor = 0; -static unsigned g_major = 0; - -/* forward declaration */ -void *nsview_get_ptr(void); - -#if defined(HAVE_COCOATOUCH) -static void glkitview_init_xibs(void) -{ - /* iOS Pause menu and lifecycle. */ - UINib *xib = (UINib*)[UINib nibWithNibName:BOXSTRING("PauseIndicatorView") bundle:nil]; - g_pause_indicator_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject]; -} -#endif - -void *glkitview_init(void) -{ -#if defined(HAVE_COCOATOUCH) - glkitview_init_xibs(); - - g_view = [GLKView new]; - g_view.multipleTouchEnabled = YES; - g_view.enableSetNeedsDisplay = NO; - [g_view addSubview:g_pause_indicator_view]; - - return (BRIDGE void *)((GLKView*)g_view); -#else - return nsview_get_ptr(); -#endif -} - -#if defined(HAVE_COCOATOUCH) -void cocoagl_bind_game_view_fbo(void) -{ - if (g_context) - [g_view bindDrawable]; -} -#endif - -static float get_from_selector(Class obj_class, id obj_id, SEL selector, CGFloat *ret) -{ - NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: - [obj_class instanceMethodSignatureForSelector:selector]]; - [invocation setSelector:selector]; - [invocation setTarget:obj_id]; - [invocation invoke]; - [invocation getReturnValue:ret]; - RELEASE(invocation); - return *ret; -} - -void *get_chosen_screen(void) -{ - settings_t *settings = config_get_ptr(); - NSArray *screens = [RAScreen screens]; - if (!screens || !settings) - return NULL; - - if (settings->uints.video_monitor_index >= screens.count) - { - RARCH_WARN("video_monitor_index is greater than the number of connected monitors; using main screen instead."); - return (BRIDGE void*)screens; - } - - return ((BRIDGE void*)[screens objectAtIndex:settings->uints.video_monitor_index]); -} - -float get_backing_scale_factor(void) -{ - static float - backing_scale_def = 0.0f; - RAScreen *screen = NULL; - - (void)screen; - - if (backing_scale_def != 0.0f) - return backing_scale_def; - - backing_scale_def = 1.0f; -#ifdef HAVE_COCOA_METAL - screen = (BRIDGE RAScreen*)get_chosen_screen(); - - if (screen) - { - SEL selector = NSSelectorFromString(BOXSTRING("backingScaleFactor")); - if ([screen respondsToSelector:selector]) - { - CGFloat ret; - NSView *g_view = apple_platform.renderView; - //CocoaView *g_view = (CocoaView*)nsview_get_ptr(); - backing_scale_def = (float)get_from_selector - ([[g_view window] class], [g_view window], selector, &ret); - } - } -#endif - - return backing_scale_def; -} - -void cocoagl_gfx_ctx_update(void) -{ - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: -#if defined(HAVE_COCOA_METAL) -#if MAC_OS_X_VERSION_10_7 - CGLUpdateContext(g_hw_ctx.CGLContextObj); - CGLUpdateContext(g_context.CGLContextObj); -#else - [g_hw_ctx update]; - [g_context update]; -#endif -#endif - break; - default: - break; - } -} - -static void cocoagl_gfx_ctx_destroy(void *data) -{ - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; - - if (!cocoa_ctx) - return; - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - [GLContextClass clearCurrentContext]; - -#if defined(HAVE_COCOA_METAL) - [g_context clearDrawable]; - RELEASE(g_context); - RELEASE(g_format); - if (g_hw_ctx) - { - [g_hw_ctx clearDrawable]; - } - RELEASE(g_hw_ctx); -#endif - [GLContextClass clearCurrentContext]; - g_context = nil; - break; - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - vulkan_context_destroy(&cocoa_ctx->vk, cocoa_ctx->vk.vk_surface != VK_NULL_HANDLE); - if (cocoa_ctx->vk.context.queue_lock) { - slock_free(cocoa_ctx->vk.context.queue_lock); - } - memset(&cocoa_ctx->vk, 0, sizeof(cocoa_ctx->vk)); - -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - - free(cocoa_ctx); -} - -static void *cocoagl_gfx_ctx_init(video_frame_info_t *video_info, void *video_driver) -{ - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*) - calloc(1, sizeof(cocoa_ctx_data_t)); - - if (!cocoa_ctx) - return NULL; - - switch (cocoagl_api) - { -#if defined(HAVE_COCOATOUCH) - case GFX_CTX_OPENGL_ES_API: - // setViewType is not (yet?) defined for iOS - // [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL_ES]; - break; -#elif defined(HAVE_COCOA_METAL) - case GFX_CTX_OPENGL_API: - [apple_platform setViewType:APPLE_VIEW_TYPE_OPENGL]; - break; -#endif - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - [apple_platform setViewType:APPLE_VIEW_TYPE_VULKAN]; - if (!vulkan_context_init(&cocoa_ctx->vk, VULKAN_WSI_MVK_MACOS)) - { - goto error; - } -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - - return cocoa_ctx; - -error: - free(cocoa_ctx); - return NULL; -} - -static enum gfx_ctx_api cocoagl_gfx_ctx_get_api(void *data) -{ - return cocoagl_api; -} - -static bool cocoagl_gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned major, unsigned minor) -{ - (void)data; - switch (api) - { -#if defined(HAVE_COCOATOUCH) - case GFX_CTX_OPENGL_ES_API: - break; -#elif defined(HAVE_COCOA_METAL) - case GFX_CTX_OPENGL_API: - break; -#ifdef HAVE_VULKAN - case GFX_CTX_VULKAN_API: - break; -#endif -#endif - case GFX_CTX_NONE: - default: - return false; - } - - cocoagl_api = api; - g_minor = minor; - g_major = major; - - return true; -} - -static void cocoagl_gfx_ctx_swap_interval(void *data, int interval) -{ -#ifdef HAVE_VULKAN - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; -#endif - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - { -#if defined(HAVE_COCOATOUCH) // < No way to disable Vsync on iOS? - // Just skip presents so fast forward still works. - g_is_syncing = interval ? true : false; - g_fast_forward_skips = interval ? 0 : 3; -#elif defined(HAVE_COCOA_METAL) - GLint value = interval ? 1 : 0; - [g_context setValues:&value forParameter:NSOpenGLCPSwapInterval]; -#endif - break; - } - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - if (cocoa_ctx->swap_interval != interval) - { - cocoa_ctx->swap_interval = interval; - if (cocoa_ctx->vk.swapchain) - { - cocoa_ctx->vk.need_new_swapchain = true; - } - } -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - -} - -static void cocoagl_gfx_ctx_show_mouse(void *data, bool state) -{ - (void)data; - -#ifdef HAVE_COCOA_METAL - if (state) - [NSCursor unhide]; - else - [NSCursor hide]; -#endif -} - -static bool cocoagl_gfx_ctx_set_video_mode(void *data, - video_frame_info_t *video_info, - unsigned width, unsigned height, bool fullscreen) -{ - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; - cocoa_ctx->width = width; - cocoa_ctx->height = height; - -#if defined(HAVE_COCOA_METAL) - //CocoaView *g_view = (BRIDGE CocoaView *)nsview_get_ptr(); - NSView *g_view = apple_platform.renderView; -#endif - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - { -#if defined(HAVE_COCOA_METAL) - if ([g_view respondsToSelector: @selector(setWantsBestResolutionOpenGLSurface:)]) - [g_view setWantsBestResolutionOpenGLSurface:YES]; - - NSOpenGLPixelFormatAttribute attributes [] = { - NSOpenGLPFAColorSize, - 24, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAllowOfflineRenderers, - NSOpenGLPFADepthSize, - (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer - 0, /* profile */ - 0, /* profile enum */ - (NSOpenGLPixelFormatAttribute)0 - }; - -#if MAC_OS_X_VERSION_10_7 - if (g_major == 3 && (g_minor >= 1 && g_minor <= 3)) - { - attributes[6] = NSOpenGLPFAOpenGLProfile; - attributes[7] = NSOpenGLProfileVersion3_2Core; - } -#endif - -#if MAC_OS_X_VERSION_10_10 - if (g_major == 4 && g_minor == 1) - { - attributes[6] = NSOpenGLPFAOpenGLProfile; - attributes[7] = NSOpenGLProfileVersion4_1Core; - } -#endif - - g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 - if (g_format == nil) - { - /* NSOpenGLFPAAllowOfflineRenderers is - not supported on this OS version. */ - attributes[3] = (NSOpenGLPixelFormatAttribute)0; - g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - } -#endif - - if (g_use_hw_ctx) - g_hw_ctx = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil]; - g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:(g_use_hw_ctx) ? g_hw_ctx : nil]; - [g_context setView:g_view]; -#else - if (g_use_hw_ctx) - g_hw_ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - g_view.context = g_context; -#endif - - [g_context makeCurrentContext]; - break; - } - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - RARCH_LOG("[macOS]: Native window size: %u x %u.\n", cocoa_ctx->width, cocoa_ctx->height); - if (!vulkan_surface_create(&cocoa_ctx->vk, - VULKAN_WSI_MVK_MACOS, NULL, - (BRIDGE void *)g_view, cocoa_ctx->width, cocoa_ctx->height, - cocoa_ctx->swap_interval)) - { - RARCH_ERR("[macOS]: Failed to create surface.\n"); - return false; - } -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - -#if defined(HAVE_COCOA_METAL) - static bool has_went_fullscreen = false; - /* TODO: Screen mode support. */ - - if (fullscreen) - { - if (!has_went_fullscreen) - { - [g_view enterFullScreenMode:(BRIDGE NSScreen *)get_chosen_screen() withOptions:nil]; - cocoagl_gfx_ctx_show_mouse(data, false); - } - } - else - { - if (has_went_fullscreen) - { - [g_view exitFullScreenModeWithOptions:nil]; - [[g_view window] makeFirstResponder:g_view]; - cocoagl_gfx_ctx_show_mouse(data, true); - } - - [[g_view window] setContentSize:NSMakeSize(width, height)]; - } - - has_went_fullscreen = fullscreen; -#endif - - /* TODO: Maybe iOS users should be able to show/hide the status bar here? */ - - return true; -} - -float cocoagl_gfx_ctx_get_native_scale(void) -{ - static CGFloat ret = 0.0f; - SEL selector = NSSelectorFromString(BOXSTRING("nativeScale")); - RAScreen *screen = (BRIDGE RAScreen*)get_chosen_screen(); - - if (ret != 0.0f) - return ret; - if (!screen) - return 0.0f; - - if ([screen respondsToSelector:selector]) - return (float)get_from_selector([screen class], screen, selector, &ret); - - ret = 1.0f; - selector = NSSelectorFromString(BOXSTRING("scale")); - if ([screen respondsToSelector:selector]) - ret = screen.scale; - return ret; -} - -static void cocoagl_gfx_ctx_get_video_size(void *data, unsigned* width, unsigned* height) -{ - float screenscale = cocoagl_gfx_ctx_get_native_scale(); -#if defined(HAVE_COCOA_METAL) - CGRect size; - GLsizei backingPixelWidth, backingPixelHeight; - NSView *g_view = apple_platform.renderView; - //CocoaView *g_view = (CocoaView*)nsview_get_ptr(); - CGRect cgrect = NSRectToCGRect([g_view frame]); -#if MAC_OS_X_VERSION_10_7 - SEL selector = NSSelectorFromString(BOXSTRING("convertRectToBacking:")); - if ([g_view respondsToSelector:selector]) - cgrect = NSRectToCGRect([g_view convertRectToBacking:[g_view bounds]]); -#endif - backingPixelWidth = CGRectGetWidth(cgrect); - backingPixelHeight = CGRectGetHeight(cgrect); - size = CGRectMake(0, 0, backingPixelWidth, backingPixelHeight); -#else - CGRect size = g_view.bounds; -#endif - *width = CGRectGetWidth(size) * screenscale; - *height = CGRectGetHeight(size) * screenscale; -} - -#if defined(HAVE_COCOA_METAL) -static void cocoagl_gfx_ctx_update_title(void *data, void *data2) -{ - ui_window_cocoa_t view; - const ui_window_t *window = ui_companion_driver_get_window_ptr(); - - //view.data = (CocoaView*)nsview_get_ptr(); - view.data = (BRIDGE void *)apple_platform.renderView; - - if (window) - { - char title[128]; - - title[0] = '\0'; - - video_driver_get_window_title(title, sizeof(title)); - - if (title[0]) - window->set_title(&view, title); - } -} -#endif - -static bool cocoagl_gfx_ctx_get_metrics(void *data, enum display_metric_types type, - float *value) -{ - RAScreen *screen = (BRIDGE RAScreen*)get_chosen_screen(); -#if defined(HAVE_COCOA_METAL) - NSDictionary *description = [screen deviceDescription]; - NSSize display_pixel_size = [[description objectForKey:NSDeviceSize] sizeValue]; - CGSize display_physical_size = CGDisplayScreenSize( - [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]); - - float display_width = display_pixel_size.width; - float display_height = display_pixel_size.height; - float physical_width = display_physical_size.width; - float physical_height = display_physical_size.height; - float scale = get_backing_scale_factor(); - float dpi = (display_width/ physical_width) * 25.4f * scale; -#elif defined(HAVE_COCOATOUCH) - float scale = cocoagl_gfx_ctx_get_native_scale(); - CGRect screen_rect = [screen bounds]; - float display_height = screen_rect.size.height; - float physical_width = screen_rect.size.width * scale; - float physical_height = screen_rect.size.height * scale; - float dpi = 160 * scale; - unsigned idiom_type = UI_USER_INTERFACE_IDIOM(); - - switch (idiom_type) - { - case -1: /* UIUserInterfaceIdiomUnspecified */ - /* TODO */ - break; - case UIUserInterfaceIdiomPad: - dpi = 132 * scale; - break; - case UIUserInterfaceIdiomPhone: - dpi = 163 * scale; - break; - case UIUserInterfaceIdiomTV: - case UIUserInterfaceIdiomCarPlay: - /* TODO */ - break; - } -#endif - - (void)display_height; - - switch (type) - { - case DISPLAY_METRIC_MM_WIDTH: - *value = physical_width; - break; - case DISPLAY_METRIC_MM_HEIGHT: - *value = physical_height; - break; - case DISPLAY_METRIC_DPI: - *value = dpi; - break; - case DISPLAY_METRIC_NONE: - default: - *value = 0; - return false; - } - - return true; -} - -static bool cocoagl_gfx_ctx_has_focus(void *data) -{ - (void)data; -#if defined(HAVE_COCOATOUCH) - return ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive); -#else - return [NSApp isActive]; -#endif -} - -static bool cocoagl_gfx_ctx_suppress_screensaver(void *data, bool enable) -{ - (void)data; - (void)enable; - - return false; -} - -#if !defined(HAVE_COCOATOUCH) -static bool cocoagl_gfx_ctx_has_windowed(void *data) -{ - return true; -} -#endif - -#ifdef HAVE_VULKAN -static void *cocoagl_gfx_ctx_get_context_data(void *data) -{ - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; - return &cocoa_ctx->vk.context; -} -#endif - -static void cocoagl_gfx_ctx_swap_buffers(void *data, void *data2) -{ -#ifdef HAVE_VULKAN - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; -#endif - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - if (!(--g_fast_forward_skips < 0)) - return; - -#if defined(HAVE_COCOA_METAL) - [g_context flushBuffer]; - [g_hw_ctx flushBuffer]; -#elif defined(HAVE_COCOATOUCH) - if (g_view) - [g_view display]; -#endif - - g_fast_forward_skips = g_is_syncing ? 0 : 3; - break; - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - vulkan_present(&cocoa_ctx->vk, cocoa_ctx->vk.context.current_swapchain_index); - vulkan_acquire_next_image(&cocoa_ctx->vk); -#endif - break; - case GFX_CTX_NONE: - default: - break; - } -} - -static gfx_ctx_proc_t cocoagl_gfx_ctx_get_proc_address(const char *symbol_name) -{ - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - return (gfx_ctx_proc_t)CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(GLFrameworkID), - (BRIDGE CFStringRef)BOXSTRING(symbol_name) - ); - case GFX_CTX_NONE: - default: - break; - } - - return NULL; -} - -static bool cocoagl_gfx_ctx_set_resize(void *data, unsigned width, unsigned height) -{ -#ifdef HAVE_VULKAN - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; -#endif - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - break; - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - cocoa_ctx->width = width; - cocoa_ctx->height = height; - - if (vulkan_create_swapchain(&cocoa_ctx->vk, - width, height, cocoa_ctx->swap_interval)) - { - cocoa_ctx->vk.context.invalid_swapchain = true; - if (cocoa_ctx->vk.created_new_swapchain) - vulkan_acquire_next_image(&cocoa_ctx->vk); - } - else - { - RARCH_ERR("[macOS/Vulkan]: Failed to update swapchain.\n"); - return false; - } - - cocoa_ctx->vk.need_new_swapchain = false; -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - - return true; -} - -static void cocoagl_gfx_ctx_check_window(void *data, bool *quit, - bool *resize, unsigned *width, unsigned *height, bool is_shutdown) -{ - unsigned new_width, new_height; -#ifdef HAVE_VULKAN - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; -#endif - - *quit = false; - - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - break; - case GFX_CTX_VULKAN_API: -#ifdef HAVE_VULKAN - *resize = cocoa_ctx->vk.need_new_swapchain; -#endif - break; - case GFX_CTX_NONE: - default: - break; - } - - cocoagl_gfx_ctx_get_video_size(data, &new_width, &new_height); - if (new_width != *width || new_height != *height) - { - *width = new_width; - *height = new_height; - *resize = true; - } -} - -static void cocoagl_gfx_ctx_input_driver(void *data, - const char *name, - const input_driver_t **input, void **input_data) -{ - *input = NULL; - *input_data = NULL; -} - -static void cocoagl_gfx_ctx_bind_hw_render(void *data, bool enable) -{ - (void)data; - switch (cocoagl_api) - { - case GFX_CTX_OPENGL_API: - case GFX_CTX_OPENGL_ES_API: - g_use_hw_ctx = enable; - - if (enable) - [g_hw_ctx makeCurrentContext]; - else - [g_context makeCurrentContext]; - break; - case GFX_CTX_NONE: - default: - break; - } -} - -static uint32_t cocoagl_gfx_ctx_get_flags(void *data) -{ - uint32_t flags = 0; - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; - - BIT32_SET(flags, GFX_CTX_FLAGS_NONE); - - if (cocoa_ctx->core_hw_context_enable) - BIT32_SET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT); - - return flags; -} - -static void cocoagl_gfx_ctx_set_flags(void *data, uint32_t flags) -{ - (void)flags; - cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; - - if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) - cocoa_ctx->core_hw_context_enable = true; -} - -const gfx_ctx_driver_t gfx_ctx_cocoagl = { - .init = cocoagl_gfx_ctx_init, - .destroy = cocoagl_gfx_ctx_destroy, - .get_api = cocoagl_gfx_ctx_get_api, - .bind_api = cocoagl_gfx_ctx_bind_api, - .swap_interval = cocoagl_gfx_ctx_swap_interval, - .set_video_mode = cocoagl_gfx_ctx_set_video_mode, - .get_video_size = cocoagl_gfx_ctx_get_video_size, - .get_metrics = cocoagl_gfx_ctx_get_metrics, -#if defined(HAVE_COCOA_METAL) - .update_window_title = cocoagl_gfx_ctx_update_title, -#endif - .check_window = cocoagl_gfx_ctx_check_window, - .set_resize = cocoagl_gfx_ctx_set_resize, - .has_focus = cocoagl_gfx_ctx_has_focus, - .suppress_screensaver = cocoagl_gfx_ctx_suppress_screensaver, -#if !defined(HAVE_COCOATOUCH) - .has_windowed = cocoagl_gfx_ctx_has_windowed, -#endif - .swap_buffers = cocoagl_gfx_ctx_swap_buffers, - .input_driver = cocoagl_gfx_ctx_input_driver, - .get_proc_address = cocoagl_gfx_ctx_get_proc_address, - .ident = "macOS", - .get_flags = cocoagl_gfx_ctx_get_flags, - .set_flags = cocoagl_gfx_ctx_set_flags, - .bind_hw_render = cocoagl_gfx_ctx_bind_hw_render, -#if defined(HAVE_VULKAN) - .get_context_data = cocoagl_gfx_ctx_get_context_data, -#else - .get_context_data = NULL, -#endif -}; diff --git a/griffin/griffin_objc.m b/griffin/griffin_objc.m index 1d7ab3dced..03e5c6f985 100644 --- a/griffin/griffin_objc.m +++ b/griffin/griffin_objc.m @@ -30,12 +30,7 @@ #if defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL) #include "../ui/drivers/cocoa/cocoa_common.m" - -#if defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA) #include "../gfx/drivers_context/cocoa_gl_ctx.m" -#else -#include "../gfx/drivers_context/cocoa_gl_ctx_metal.m" -#endif #if defined(HAVE_COCOATOUCH)