summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2019-09-15 20:00:59 -0400
committer arbee <rb6502@users.noreply.github.com>2019-09-15 20:00:59 -0400
commit2292cf332c989bf374377b61719beead0706b989 (patch)
tree8ba3c9f5af0b9e6f487a7b3fe8fccf6c3c99154a /src
parentfd505eb0d643a8a8a50ba32f7f0704fec400138d (diff)
Preliminary Mac native OSD. Not working yet. [R. Belmont]
This will compile, link, and run a driver all the way to the first info screen, provided you use -video bgfx. However, although there's a valid NSWindow created, it never actually appears on screen for unknown (but likely silly) reasons. Inputs are not implemented and fullscreen exists but is untried.
Diffstat (limited to 'src')
-rw-r--r--src/osd/mac/appdelegate.h15
-rw-r--r--src/osd/mac/appdelegate.mm54
-rw-r--r--src/osd/mac/macmain.cpp271
-rw-r--r--src/osd/mac/main.mm19
-rw-r--r--src/osd/mac/mamefswindow.h15
-rw-r--r--src/osd/mac/mamefswindow.mm41
-rw-r--r--src/osd/mac/oglview.h19
-rw-r--r--src/osd/mac/oglview.mm106
-rw-r--r--src/osd/mac/osdmac.h86
-rw-r--r--src/osd/mac/video.cpp316
-rw-r--r--src/osd/mac/window.cpp970
-rw-r--r--src/osd/mac/window.h134
-rw-r--r--src/osd/mac/windowcontroller.h16
-rw-r--r--src/osd/mac/windowcontroller.mm121
-rw-r--r--src/osd/modules/opengl/osd_opengl.h3
-rw-r--r--src/osd/modules/render/drawbgfx.cpp21
-rw-r--r--src/osd/modules/render/drawogl.cpp15
-rw-r--r--src/osd/modules/render/drawogl.h5
18 files changed, 2223 insertions, 4 deletions
diff --git a/src/osd/mac/appdelegate.h b/src/osd/mac/appdelegate.h
new file mode 100644
index 00000000000..31daea1240a
--- /dev/null
+++ b/src/osd/mac/appdelegate.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// appdelegate.h - Cocoa app delegate
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import <Cocoa/Cocoa.h>
+
+@interface MAMEAppDelegate : NSObject <NSApplicationDelegate>
+
+@end
diff --git a/src/osd/mac/appdelegate.mm b/src/osd/mac/appdelegate.mm
new file mode 100644
index 00000000000..4207f515beb
--- /dev/null
+++ b/src/osd/mac/appdelegate.mm
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// appdelegate.mm - Cocoa app delegate
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import "appdelegate.h"
+
+extern int mac_run_emulator();
+
+@interface MAMEThread : NSThread
+@end
+
+@implementation MAMEThread
+- (void)main
+{
+ mac_run_emulator();
+}
+@end
+
+@interface MAMEAppDelegate ()
+@end
+
+@implementation MAMEAppDelegate
+MAMEThread *appThread;
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ // run MAME on a thread so event dispatching happens normally
+ appThread = [[MAMEThread alloc] init];
+ [appThread start];
+}
+
+- (void)applicationWillTerminate:(NSNotification *)notification
+{
+}
+
+- (void)applicationDidBecomeActive:(NSNotification *)notification
+{
+}
+
+- (void)applicationDidResignActive:(NSNotification *)notification
+{
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSNotification *)notification
+{
+ return NSTerminateNow;
+}
+@end
diff --git a/src/osd/mac/macmain.cpp b/src/osd/mac/macmain.cpp
new file mode 100644
index 00000000000..8e50361a2b1
--- /dev/null
+++ b/src/osd/mac/macmain.cpp
@@ -0,0 +1,271 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// macmain.cpp - C++ side main file for MAME on the Mac
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+// oslog callback
+#include <functional>
+
+#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#include <Carbon/Carbon.h>
+#include <crt_externs.h>
+#include <unistd.h>
+
+// MAME headers
+#include "osdepend.h"
+#include "emu.h"
+#include "emuopts.h"
+#include "strconv.h"
+
+// OSD headers
+#include "video.h"
+#include "osdmac.h"
+#include "modules/lib/osdlib.h"
+#include "modules/diagnostics/diagnostics_module.h"
+
+//============================================================
+// OPTIONS
+//============================================================
+
+#ifndef INI_PATH
+#define INI_PATH "$HOME/Library/Application Support/APP_NAME;$HOME/.APP_NAME;.;ini"
+#endif // INI_PATH
+
+//============================================================
+// Local variables
+//============================================================
+
+const options_entry mac_options::s_option_entries[] =
+{
+ { MACOPTION_INIPATH, INI_PATH, OPTION_STRING, "path to ini files" },
+
+ // End of list
+ { nullptr }
+};
+
+//============================================================
+// mac_options
+//============================================================
+
+mac_options::mac_options()
+: osd_options()
+{
+ std::string ini_path(INI_PATH);
+ add_entries(mac_options::s_option_entries);
+ strreplace(ini_path,"APP_NAME", emulator_info::get_appname_lower());
+ set_default_value(MACOPTION_INIPATH, ini_path.c_str());
+}
+
+//============================================================
+// main
+//============================================================
+
+// we do some special sauce on Win32...
+int mac_run_emulator()
+{
+ int argc = *_NSGetArgc();
+ char **argv = *_NSGetArgv();
+
+ std::vector<std::string> args = osd_get_command_line(argc, argv);
+ int res = 0;
+
+ // disable I/O buffering
+ setvbuf(stdout, (char *) nullptr, _IONBF, 0);
+ setvbuf(stderr, (char *) nullptr, _IONBF, 0);
+
+ // Initialize crash diagnostics
+ diagnostics_module::get_instance()->init_crash_diagnostics();
+
+ {
+ mac_options options;
+ mac_osd_interface osd(options);
+ osd.register_options();
+ res = emulator_info::start_frontend(options, osd, args);
+ }
+
+ exit(res);
+}
+
+//============================================================
+// constructor
+//============================================================
+
+mac_osd_interface::mac_osd_interface(mac_options &options)
+: osd_common_t(options), m_options(options)
+{
+}
+
+
+//============================================================
+// destructor
+//============================================================
+
+mac_osd_interface::~mac_osd_interface()
+{
+}
+
+
+//============================================================
+// osd_exit
+//============================================================
+
+void mac_osd_interface::osd_exit()
+{
+ osd_common_t::osd_exit();
+}
+
+//============================================================
+// defines_verbose
+//============================================================
+
+#define MAC_EXPAND_STR(_m) #_m
+#define MACRO_VERBOSE(_mac) \
+ do { \
+ if (strcmp(MAC_EXPAND_STR(_mac), #_mac) != 0) \
+ osd_printf_verbose("%s=%s ", #_mac, MAC_EXPAND_STR(_mac)); \
+ } while (0)
+
+#define _mac_VER #mac_MAJOR_VERSION "." #mac_MINOR_VERSION "." #mac_PATCHLEVEL
+
+static void defines_verbose(void)
+{
+ osd_printf_verbose("Build version: %s\n", emulator_info::get_build_version());
+ osd_printf_verbose("Build architecure: ");
+ MACRO_VERBOSE(SDLMAME_ARCH);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Build defines 1: ");
+ MACRO_VERBOSE(SDLMAME_UNIX);
+ MACRO_VERBOSE(SDLMAME_X11);
+ MACRO_VERBOSE(SDLMAME_WIN32);
+ MACRO_VERBOSE(SDLMAME_MACOSX);
+ MACRO_VERBOSE(SDLMAME_DARWIN);
+ MACRO_VERBOSE(SDLMAME_LINUX);
+ MACRO_VERBOSE(SDLMAME_SOLARIS);
+ MACRO_VERBOSE(SDLMAME_IRIX);
+ MACRO_VERBOSE(SDLMAME_BSD);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Build defines 1: ");
+ MACRO_VERBOSE(LSB_FIRST);
+ MACRO_VERBOSE(PTR64);
+ MACRO_VERBOSE(MAME_NOASM);
+ MACRO_VERBOSE(MAME_DEBUG);
+ MACRO_VERBOSE(BIGENDIAN);
+ MACRO_VERBOSE(CPP_COMPILE);
+ MACRO_VERBOSE(SYNC_IMPLEMENTATION);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("OpenGL defines: ");
+ MACRO_VERBOSE(USE_OPENGL);
+ MACRO_VERBOSE(USE_DISPATCH_GL);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines A: ");
+ MACRO_VERBOSE(__GNUC__);
+ MACRO_VERBOSE(__GNUC_MINOR__);
+ MACRO_VERBOSE(__GNUC_PATCHLEVEL__);
+ MACRO_VERBOSE(__VERSION__);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines B: ");
+ MACRO_VERBOSE(__amd64__);
+ MACRO_VERBOSE(__x86_64__);
+ MACRO_VERBOSE(__unix__);
+ MACRO_VERBOSE(__i386__);
+ MACRO_VERBOSE(__ppc__);
+ MACRO_VERBOSE(__ppc64__);
+ osd_printf_verbose("\n");
+ osd_printf_verbose("Compiler defines C: ");
+ MACRO_VERBOSE(_FORTIFY_SOURCE);
+ MACRO_VERBOSE(__USE_FORTIFY_LEVEL);
+ osd_printf_verbose("\n");
+}
+
+//============================================================
+// osd_mac_info
+//============================================================
+
+static void osd_mac_info(void)
+{
+}
+
+
+//============================================================
+// video_register
+//============================================================
+
+void mac_osd_interface::video_register()
+{
+ video_options_add("opengl", nullptr);
+ video_options_add("bgfx", nullptr);
+}
+
+//============================================================
+// output_oslog
+//============================================================
+
+void mac_osd_interface::output_oslog(const char *buffer)
+{
+ fputs(buffer, stderr);
+}
+
+
+//============================================================
+// osd_setup_osd_specific_emu_options
+//============================================================
+
+void osd_setup_osd_specific_emu_options(emu_options &opts)
+{
+ opts.add_entries(osd_options::s_option_entries);
+}
+
+
+//============================================================
+// init
+//============================================================
+
+void mac_osd_interface::init(running_machine &machine)
+{
+ // call our parent
+ osd_common_t::init(machine);
+
+ const char *stemp;
+
+ // determine if we are benchmarking, and adjust options appropriately
+ int bench = options().bench();
+ if (bench > 0)
+ {
+ options().set_value(OPTION_THROTTLE, false, OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OSDOPTION_SOUND, "none", OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OSDOPTION_VIDEO, "none", OPTION_PRIORITY_MAXIMUM);
+ options().set_value(OPTION_SECONDS_TO_RUN, bench, OPTION_PRIORITY_MAXIMUM);
+ }
+
+ /* get number of processors */
+ stemp = options().numprocessors();
+
+ osd_num_processors = 0;
+
+ if (strcmp(stemp, "auto") != 0)
+ {
+ osd_num_processors = atoi(stemp);
+ if (osd_num_processors < 1)
+ {
+ osd_printf_warning("numprocessors < 1 doesn't make much sense. Assuming auto ...\n");
+ osd_num_processors = 0;
+ }
+ }
+
+ osd_mac_info();
+
+ defines_verbose();
+
+ osd_common_t::init_subsystems();
+
+ if (options().oslog())
+ {
+ using namespace std::placeholders;
+ machine.add_logerror_callback(std::bind(&mac_osd_interface::output_oslog, this, _1));
+ }
+}
diff --git a/src/osd/mac/main.mm b/src/osd/mac/main.mm
new file mode 100644
index 00000000000..fdc50be53fe
--- /dev/null
+++ b/src/osd/mac/main.mm
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// main.mm - main file for MAME on Mac
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import "appdelegate.h"
+
+int main(int argc, char * argv[])
+{
+ [NSApplication sharedApplication];
+ [NSApp setDelegate: [MAMEAppDelegate new]];
+
+ return NSApplicationMain(argc, (const char**)argv);
+}
diff --git a/src/osd/mac/mamefswindow.h b/src/osd/mac/mamefswindow.h
new file mode 100644
index 00000000000..d326b9dfb37
--- /dev/null
+++ b/src/osd/mac/mamefswindow.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// mamefswindow.h - our fullscreen window, subclassed from NSWindow
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import <Cocoa/Cocoa.h>
+
+@interface MAMEFSWindow : NSWindow
+
+@end
diff --git a/src/osd/mac/mamefswindow.mm b/src/osd/mac/mamefswindow.mm
new file mode 100644
index 00000000000..1fcbdcd02c3
--- /dev/null
+++ b/src/osd/mac/mamefswindow.mm
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// mamewfsindow.mm - our fullscreen window, subclassed from NSWindow
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import "mamefswindow.h"
+
+@implementation MAMEFSWindow
+
+-(instancetype)init
+{
+ NSRect screenRect = [[NSScreen mainScreen] frame];
+ self = [super initWithContentRect:screenRect
+ styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered
+ defer:YES];
+
+ // Set the window level to be above the menu bar
+ [self setLevel:NSMainMenuWindowLevel+1];
+ [self setOpaque:YES];
+ [self setHidesOnDeactivate:YES];
+
+ return self;
+}
+
+-(BOOL)canBecomeKeyWindow
+{
+ return YES;
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+ [[self windowController] keyDown:event];
+}
+
+@end
diff --git a/src/osd/mac/oglview.h b/src/osd/mac/oglview.h
new file mode 100644
index 00000000000..2f876952cba
--- /dev/null
+++ b/src/osd/mac/oglview.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// oglview.h - our OpenGL view
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#define GL_SILENCE_DEPRECATION (1)
+
+#import <Cocoa/Cocoa.h>
+
+@interface MAMEGLView : NSOpenGLView
+{
+}
+
+@end
diff --git a/src/osd/mac/oglview.mm b/src/osd/mac/oglview.mm
new file mode 100644
index 00000000000..8ef0a94f880
--- /dev/null
+++ b/src/osd/mac/oglview.mm
@@ -0,0 +1,106 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// oglview.mm - our OpenGL view
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import "oglview.h"
+
+#define SUPPORT_RETINA_RESOLUTION 1
+
+@interface MAMEGLView ()
+{
+}
+@end
+
+@implementation MAMEGLView
+
+- (void) awakeFromNib
+{
+ NSOpenGLPixelFormatAttribute attrs[] =
+ {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFADepthSize, 24,
+ 0
+ };
+
+ NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+ NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil];
+
+ [self setPixelFormat:pf];
+ [self setOpenGLContext:context];
+
+#if SUPPORT_RETINA_RESOLUTION
+ // Opt-In to Retina resolution
+ [self setWantsBestResolutionOpenGLSurface:YES];
+#endif // SUPPORT_RETINA_RESOLUTION
+}
+
+- (void) prepareOpenGL
+{
+ [super prepareOpenGL];
+
+ [self initGL];
+}
+
+- (void) windowWillClose:(NSNotification*)notification
+{
+}
+
+- (void) initGL
+{
+ [[self openGLContext] makeCurrentContext];
+ GLint swapInt = 1;
+ [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+}
+
+- (void)reshape
+{
+ [super reshape];
+
+ CGLLockContext([[self openGLContext] CGLContextObj]);
+
+// NSRect viewRectPoints = [self bounds];
+
+//#if SUPPORT_RETINA_RESOLUTION
+// NSRect viewRectPixels = [self convertRectToBacking:viewRectPoints];
+//#else
+// NSRect viewRectPixels = viewRectPoints;
+//#endif
+
+ CGLUnlockContext([[self openGLContext] CGLContextObj]);
+}
+
+
+- (void)renewGState
+{
+ [[self window] disableScreenUpdatesUntilFlush];
+ [super renewGState];
+}
+
+- (void) drawRect: (NSRect) theRect
+{
+}
+
+- (void) startDrawView
+{
+ [[self openGLContext] makeCurrentContext];
+
+ CGLLockContext([[self openGLContext] CGLContextObj]);
+}
+
+- (void) completeDrawView
+{
+ CGLFlushDrawable([[self openGLContext] CGLContextObj]);
+ CGLUnlockContext([[self openGLContext] CGLContextObj]);
+}
+
+- (void) dealloc
+{
+ [super dealloc];
+}
+@end
diff --git a/src/osd/mac/osdmac.h b/src/osd/mac/osdmac.h
new file mode 100644
index 00000000000..1ed9e6b8a5b
--- /dev/null
+++ b/src/osd/mac/osdmac.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef _osdmac_h_
+#define _osdmac_h_
+
+#include "modules/lib/osdobj_common.h"
+#include "modules/osdmodule.h"
+#include "modules/font/font_module.h"
+
+//============================================================
+// Defines
+//============================================================
+
+#define MACOPTION_INIPATH "inipath"
+
+#define MACOPTVAL_OPENGL "opengl"
+#define MACOPTVAL_BGFX "bgfx"
+#define MACOPTVAL_METAL "metal"
+
+#define MACOPTVAL_GLLIB "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class mac_options : public osd_options
+{
+public:
+ // construction/destruction
+ mac_options();
+
+private:
+ static const options_entry s_option_entries[];
+};
+
+
+class mac_osd_interface : public osd_common_t
+{
+public:
+ // construction/destruction
+ mac_osd_interface(mac_options &options);
+ virtual ~mac_osd_interface();
+
+ // general overridables
+ virtual void init(running_machine &machine) override;
+ virtual void update(bool skip_redraw) override;
+
+ // input overridables
+ virtual void customize_input_type_list(simple_list<input_type_entry> &typelist) override;
+
+ virtual void video_register() override;
+
+ virtual bool video_init() override;
+ virtual bool window_init() override;
+
+ virtual void video_exit() override;
+ virtual void window_exit() override;
+
+ // sdl specific
+ void poll_inputs(running_machine &machine);
+ void release_keys();
+ bool should_hide_mouse();
+ void process_events_buf();
+
+ virtual mac_options &options() override { return m_options; }
+
+protected:
+ virtual void build_slider_list() override;
+ virtual void update_slider_list() override;
+
+private:
+ virtual void osd_exit() override;
+
+ void extract_video_config();
+ void output_oslog(const char *buffer);
+
+ mac_options &m_options;
+};
+
+//============================================================
+// macwork.cpp
+//============================================================
+
+extern int osd_num_processors;
+
+#endif
diff --git a/src/osd/mac/video.cpp b/src/osd/mac/video.cpp
new file mode 100644
index 00000000000..638e7a949b3
--- /dev/null
+++ b/src/osd/mac/video.cpp
@@ -0,0 +1,316 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+//============================================================
+//
+// video.cpp - Mac video handling
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+// MAME headers
+#include "emu.h"
+#include "rendutil.h"
+#include "ui/uimain.h"
+#include "emuopts.h"
+#include "uiinput.h"
+
+
+// MAMEOS headers
+#include "video.h"
+#include "window.h"
+#include "osdmac.h"
+#include "modules/lib/osdlib.h"
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+
+//============================================================
+// GLOBAL VARIABLES
+//============================================================
+
+osd_video_config video_config;
+
+//============================================================
+// LOCAL VARIABLES
+//============================================================
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+static void check_osd_inputs(running_machine &machine);
+
+static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error);
+
+
+//============================================================
+// video_init
+//============================================================
+
+bool mac_osd_interface::video_init()
+{
+ int index;
+
+ // extract data from the options
+ extract_video_config();
+
+ // we need the beam width in a float, contrary to what the core does.
+ video_config.beamwidth = options().beam_width_min();
+
+ // initialize the window system so we can make windows
+ if (!window_init())
+ return false;
+
+ // create the windows
+ for (index = 0; index < video_config.numscreens; index++)
+ {
+ osd_window_config conf;
+ memset(&conf, 0, sizeof(conf));
+ get_resolution(options().resolution(), options().resolution(index), &conf, true);
+
+ // create window ...
+ std::shared_ptr<mac_window_info> win = std::make_shared<mac_window_info>(machine(), index, m_monitor_module->pick_monitor(reinterpret_cast<osd_options &>(options()), index), &conf);
+
+ if (win->window_init())
+ return false;
+ }
+
+ return true;
+}
+
+//============================================================
+// video_exit
+//============================================================
+
+void mac_osd_interface::video_exit()
+{
+ window_exit();
+}
+
+//============================================================
+// update
+//============================================================
+
+void mac_osd_interface::update(bool skip_redraw)
+{
+ osd_common_t::update(skip_redraw);
+
+ // if we're not skipping this redraw, update all windows
+ if (!skip_redraw)
+ {
+// profiler_mark(PROFILER_BLIT);
+ for (auto window : osd_common_t::s_window_list)
+ window->update();
+// profiler_mark(PROFILER_END);
+ }
+
+ // poll the joystick values here
+ downcast<mac_osd_interface&>(machine().osd()).poll_inputs(machine());
+
+ check_osd_inputs(machine());
+ // if we're running, disable some parts of the debugger
+ if ((machine().debug_flags & DEBUG_FLAG_OSD_ENABLED) != 0)
+ debugger_update();
+}
+
+//============================================================
+// check_osd_inputs
+//============================================================
+
+static void check_osd_inputs(running_machine &machine)
+{
+ // check for toggling fullscreen mode
+ if (machine.ui_input().pressed(IPT_OSD_1))
+ {
+ for (auto curwin : osd_common_t::s_window_list)
+ std::static_pointer_cast<mac_window_info>(curwin)->toggle_full_screen();
+ }
+
+ auto window = osd_common_t::s_window_list.front();
+ if (machine.ui_input().pressed(IPT_OSD_2))
+ {
+ //FIXME: on a per window basis
+ video_config.fullstretch = !video_config.fullstretch;
+ window->target()->set_scale_mode(video_config.fullstretch? SCALE_FRACTIONAL : SCALE_INTEGER);
+ machine.ui().popup_time(1, "Uneven stretch %s", video_config.fullstretch? "enabled":"disabled");
+ }
+
+ if (machine.ui_input().pressed(IPT_OSD_4))
+ {
+ //FIXME: on a per window basis
+ video_config.keepaspect = !video_config.keepaspect;
+ window->target()->set_keepaspect(video_config.keepaspect);
+ machine.ui().popup_time(1, "Keepaspect %s", video_config.keepaspect? "enabled":"disabled");
+ }
+
+ //FIXME: on a per window basis
+ if (machine.ui_input().pressed(IPT_OSD_5))
+ {
+ video_config.filter = !video_config.filter;
+ machine.ui().popup_time(1, "Filter %s", video_config.filter? "enabled":"disabled");
+ }
+
+ if (machine.ui_input().pressed(IPT_OSD_6))
+ std::static_pointer_cast<mac_window_info>(window)->modify_prescale(-1);
+
+ if (machine.ui_input().pressed(IPT_OSD_7))
+ std::static_pointer_cast<mac_window_info>(window)->modify_prescale(1);
+
+ if (machine.ui_input().pressed(IPT_OSD_8))
+ window->renderer().record();
+}
+
+//============================================================
+// extract_video_config
+//============================================================
+
+void mac_osd_interface::extract_video_config()
+{
+ const char *stemp;
+
+ // global options: extract the data
+ video_config.windowed = options().window();
+ video_config.prescale = options().prescale();
+ video_config.filter = options().filter();
+ video_config.keepaspect = options().keep_aspect();
+ video_config.numscreens = options().numscreens();
+ video_config.fullstretch = options().uneven_stretch();
+
+ // if we are in debug mode, never go full screen
+ if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED)
+ video_config.windowed = true;
+
+ // default to working video please
+ video_config.novideo = 0;
+
+ // d3d options: extract the data
+ stemp = options().video();
+ if (strcmp(stemp, "auto") == 0)
+ {
+ stemp = "opengl";
+ }
+
+ if (strcmp(stemp, OSDOPTVAL_NONE) == 0)
+ {
+ video_config.mode = VIDEO_MODE_SOFT;
+ video_config.novideo = 1;
+
+ if (!emulator_info::standalone() && options().seconds_to_run() == 0)
+ osd_printf_warning("Warning: -video none doesn't make much sense without -seconds_to_run\n");
+ }
+
+ else if (strcmp(stemp, MACOPTVAL_OPENGL) == 0)
+ video_config.mode = VIDEO_MODE_OPENGL;
+ else if (strcmp(stemp, MACOPTVAL_BGFX) == 0)
+ {
+ video_config.mode = VIDEO_MODE_BGFX;
+ }
+ else
+ {
+ osd_printf_warning("Invalid video value %s; reverting to OpenGL\n", stemp);
+ video_config.mode = VIDEO_MODE_OPENGL;
+ }
+
+ video_config.switchres = options().switch_res();
+ video_config.waitvsync = options().wait_vsync();
+ video_config.syncrefresh = options().sync_refresh();
+ if (!video_config.waitvsync && video_config.syncrefresh)
+ {
+ osd_printf_warning("-syncrefresh specified without -waitvsync. Reverting to -nosyncrefresh\n");
+ video_config.syncrefresh = 0;
+ }
+
+ if (video_config.prescale < 1 || video_config.prescale > 3)
+ {
+ osd_printf_warning("Invalid prescale option, reverting to '1'\n");
+ video_config.prescale = 1;
+ }
+
+ // default to working video please
+ video_config.forcepow2texture = options().gl_force_pow2_texture();
+ video_config.allowtexturerect = !(options().gl_no_texture_rect());
+ video_config.vbo = options().gl_vbo();
+ video_config.pbo = options().gl_pbo();
+ video_config.glsl = options().gl_glsl();
+ if ( video_config.glsl )
+ {
+ int i;
+ video_config.glsl_filter = options().glsl_filter();
+ video_config.glsl_shader_mamebm_num=0;
+ for(i=0; i<GLSL_SHADER_MAX; i++)
+ {
+ stemp = options().shader_mame(i);
+ if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0)
+ {
+ video_config.glsl_shader_mamebm[i] = (char *) malloc(strlen(stemp)+1);
+ strcpy(video_config.glsl_shader_mamebm[i], stemp);
+ video_config.glsl_shader_mamebm_num++;
+ } else {
+ video_config.glsl_shader_mamebm[i] = nullptr;
+ }
+ }
+ video_config.glsl_shader_scrn_num=0;
+ for(i=0; i<GLSL_SHADER_MAX; i++)
+ {
+ stemp = options().shader_screen(i);
+ if (stemp && strcmp(stemp, OSDOPTVAL_NONE) != 0 && strlen(stemp)>0)
+ {
+ video_config.glsl_shader_scrn[i] = (char *) malloc(strlen(stemp)+1);
+ strcpy(video_config.glsl_shader_scrn[i], stemp);
+ video_config.glsl_shader_scrn_num++;
+ } else {
+ video_config.glsl_shader_scrn[i] = nullptr;
+ }
+ }
+ } else {
+ int i;
+ video_config.glsl_filter = 0;
+ video_config.glsl_shader_mamebm_num=0;
+ for(i=0; i<GLSL_SHADER_MAX; i++)
+ {
+ video_config.glsl_shader_mamebm[i] = nullptr;
+ }
+ video_config.glsl_shader_scrn_num=0;
+ for(i=0; i<GLSL_SHADER_MAX; i++)
+ {
+ video_config.glsl_shader_scrn[i] = nullptr;
+ }
+ }
+
+ // misc options: sanity check values
+
+ // global options: sanity check values
+ if (video_config.numscreens < 1 || video_config.numscreens > MAX_VIDEO_WINDOWS)
+ {
+ osd_printf_warning("Invalid numscreens value %d; reverting to 1\n", video_config.numscreens);
+ video_config.numscreens = 1;
+ }
+}
+
+
+//============================================================
+// get_resolution
+//============================================================
+
+static void get_resolution(const char *defdata, const char *data, osd_window_config *config, int report_error)
+{
+ config->width = config->height = config->depth = config->refresh = 0;
+ if (strcmp(data, OSDOPTVAL_AUTO) == 0)
+ {
+ if (strcmp(defdata, OSDOPTVAL_AUTO) == 0)
+ return;
+ data = defdata;
+ }
+
+ if (sscanf(data, "%dx%dx%d", &config->width, &config->height, &config->depth) < 2 && report_error)
+ osd_printf_error("Illegal resolution value = %s\n", data);
+
+ const char * at_pos = strchr(data, '@');
+ if (at_pos)
+ if (sscanf(at_pos + 1, "%d", &config->refresh) < 1 && report_error)
+ osd_printf_error("Illegal refresh rate in resolution value = %s\n", data);
+}
diff --git a/src/osd/mac/window.cpp b/src/osd/mac/window.cpp
new file mode 100644
index 00000000000..3993b3502d2
--- /dev/null
+++ b/src/osd/mac/window.cpp
@@ -0,0 +1,970 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+//============================================================
+//
+// window.cpp - Mac window handling
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+// standard C headers
+#include <math.h>
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <list>
+#include <memory>
+
+// MAME headers
+#include "emu.h"
+#include "emuopts.h"
+#include "render.h"
+#include "ui/uimain.h"
+
+// OSD headers
+
+#include "window.h"
+#include "osdmac.h"
+#include "modules/render/drawbgfx.h"
+#include "modules/render/drawogl.h"
+#include "modules/monitor/monitor_common.h"
+
+//============================================================
+// PARAMETERS
+//============================================================
+
+// these are arbitrary values since AFAIK there's no way to make X/SDL tell you
+#define WINDOW_DECORATION_WIDTH (8) // should be more than plenty
+#define WINDOW_DECORATION_HEIGHT (48) // title bar + bottom drag region
+
+// minimum window dimension
+#define MIN_WINDOW_DIM 200
+
+#define WMSZ_TOP (0)
+#define WMSZ_BOTTOM (1)
+#define WMSZ_BOTTOMLEFT (2)
+#define WMSZ_BOTTOMRIGHT (3)
+#define WMSZ_LEFT (4)
+#define WMSZ_TOPLEFT (5)
+#define WMSZ_TOPRIGHT (6)
+#define WMSZ_RIGHT (7)
+
+// debugger
+//static int in_background;
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+
+//============================================================
+// window_init
+// (main thread)
+//============================================================
+
+bool mac_osd_interface::window_init()
+{
+ osd_printf_verbose("Enter macwindow_init\n");
+
+ // initialize the drawers
+
+ switch (video_config.mode)
+ {
+ case VIDEO_MODE_BGFX:
+ renderer_bgfx::init(machine());
+ break;
+ case VIDEO_MODE_OPENGL:
+ renderer_ogl::init(machine());
+ break;
+ }
+
+ // set up the window list
+ osd_printf_verbose("Leave macwindow_init\n");
+ return true;
+}
+
+
+void mac_osd_interface::update_slider_list()
+{
+ for (auto window : osd_common_t::s_window_list)
+ {
+ // check if any window has dirty sliders
+ if (window->renderer().sliders_dirty())
+ {
+ build_slider_list();
+ return;
+ }
+ }
+}
+
+void mac_osd_interface::build_slider_list()
+{
+ m_sliders.clear();
+
+ for (auto window : osd_common_t::s_window_list)
+ {
+ std::vector<ui::menu_item> window_sliders = window->renderer().get_slider_list();
+ m_sliders.insert(m_sliders.end(), window_sliders.begin(), window_sliders.end());
+ }
+}
+
+//============================================================
+// macwindow_exit
+// (main thread)
+//============================================================
+
+void mac_osd_interface::window_exit()
+{
+ osd_printf_verbose("Enter macwindow_exit\n");
+
+ // free all the windows
+ while (!osd_common_t::s_window_list.empty())
+ {
+ auto window = osd_common_t::s_window_list.front();
+
+ // Part of destroy removes the window from the list
+ window->destroy();
+ }
+
+ switch(video_config.mode)
+ {
+ case VIDEO_MODE_BGFX:
+ renderer_bgfx::exit();
+ break;
+ case VIDEO_MODE_OPENGL:
+ renderer_ogl::exit();
+ break;
+ default:
+ break;
+ }
+ osd_printf_verbose("Leave macwindow_exit\n");
+}
+
+void mac_window_info::capture_pointer()
+{
+ if (!m_mouse_captured)
+ {
+ m_mouse_captured = true;
+ }
+}
+
+void mac_window_info::release_pointer()
+{
+ if (m_mouse_captured)
+ {
+ m_mouse_captured = false;
+ }
+}
+
+void mac_window_info::hide_pointer()
+{
+ if (!m_mouse_hidden)
+ {
+ m_mouse_hidden = true;
+ }
+}
+
+void mac_window_info::show_pointer()
+{
+ if (m_mouse_hidden)
+ {
+ m_mouse_hidden = false;
+ }
+}
+
+
+//============================================================
+// macwindow_resize
+//============================================================
+
+void mac_window_info::resize(int32_t width, int32_t height)
+{
+ osd_dim cd = get_size();
+
+ if (width != cd.width() || height != cd.height())
+ {
+ // TODO: change window size here
+ renderer().notify_changed();
+ }
+}
+
+
+//============================================================
+// notify_changed
+//============================================================
+
+void mac_window_info::notify_changed()
+{
+ renderer().notify_changed();
+}
+
+
+//============================================================
+// toggle_full_screen
+//============================================================
+
+void mac_window_info::toggle_full_screen()
+{
+ // if we are in debug mode, never go full screen
+ if (machine().debug_flags & DEBUG_FLAG_OSD_ENABLED)
+ return;
+
+ // If we are going fullscreen (leaving windowed) remember our windowed size
+ if (!fullscreen())
+ {
+ m_windowed_dim = get_size();
+ }
+
+ // reset UI to main menu
+ machine().ui().menu_reset();
+ // kill off the drawers
+ renderer_reset();
+ if (fullscreen() && video_config.switchres)
+ {
+ }
+ //SDL_DestroyWindow(platform_window());
+ //set_platform_window(nullptr);
+
+ downcast<mac_osd_interface &>(machine().osd()).release_keys();
+
+ set_renderer(osd_renderer::make_for_type(video_config.mode, shared_from_this()));
+
+ // toggle the window mode
+ set_fullscreen(!fullscreen());
+
+ complete_create();
+}
+
+void mac_window_info::modify_prescale(int dir)
+{
+ int new_prescale = prescale();
+
+ if (dir > 0 && prescale() < 3)
+ new_prescale = prescale() + 1;
+ if (dir < 0 && prescale() > 1)
+ new_prescale = prescale() - 1;
+
+ if (new_prescale != prescale())
+ {
+ if (m_fullscreen && video_config.switchres)
+ {
+ complete_destroy();
+
+ m_prescale = new_prescale;
+
+ complete_create();
+ }
+ else
+ {
+ notify_changed();
+ m_prescale = new_prescale;
+ }
+ machine().ui().popup_time(1, "Prescale %d", prescale());
+ }
+}
+
+//============================================================
+// update_cursor_state
+// (main or window thread)
+//============================================================
+
+void mac_window_info::update_cursor_state()
+{
+ // do not do mouse capture if the debugger's enabled to avoid
+ // the possibility of losing control
+ if (!(machine().debug_flags & DEBUG_FLAG_OSD_ENABLED))
+ {
+ bool should_hide_mouse = downcast<mac_osd_interface&>(machine().osd()).should_hide_mouse();
+
+ if (!fullscreen() && !should_hide_mouse)
+ {
+ show_pointer();
+ release_pointer();
+ }
+ else
+ {
+ hide_pointer();
+ capture_pointer();
+ }
+ }
+}
+
+int mac_window_info::xy_to_render_target(int x, int y, int *xt, int *yt)
+{
+ return renderer().xy_to_render_target(x, y, xt, yt);
+}
+
+//============================================================
+// mac_window_info::window_init
+// (main thread)
+//============================================================
+
+int mac_window_info::window_init()
+{
+ int result;
+
+ // set the initial maximized state
+ // FIXME: Does not belong here
+ mac_options &options = downcast<mac_options &>(m_machine.options());
+ m_startmaximized = options.maximize();
+
+ // add us to the list
+ osd_common_t::s_window_list.push_back(std::static_pointer_cast<mac_window_info>(shared_from_this()));
+
+ set_renderer(osd_renderer::make_for_type(video_config.mode, static_cast<osd_window*>(this)->shared_from_this()));
+
+ // load the layout
+ m_target = m_machine.render().target_alloc();
+
+ // set the specific view
+ set_starting_view(m_index, options.view(), options.view(m_index));
+
+ // make the window title
+ if (video_config.numscreens == 1)
+ sprintf(m_title, "%s: %s [%s]", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name);
+ else
+ sprintf(m_title, "%s: %s [%s] - Screen %d", emulator_info::get_appname(), m_machine.system().type.fullname(), m_machine.system().name, m_index);
+
+ result = complete_create();
+
+ // handle error conditions
+ if (result == 1)
+ goto error;
+
+ return 0;
+
+error:
+ destroy();
+ return 1;
+}
+
+
+//============================================================
+// mac_window_info::complete_destroy
+//============================================================
+
+void mac_window_info::complete_destroy()
+{
+ // Release pointer grab and hide if needed
+ show_pointer();
+ release_pointer();
+
+ if (fullscreen() && video_config.switchres)
+ {
+ }
+
+ //SDL_DestroyWindow(platform_window());
+ // release all keys ...
+ downcast<mac_osd_interface &>(machine().osd()).release_keys();
+}
+
+void mac_window_info::destroy()
+{
+ // remove us from the list
+ osd_common_t::s_window_list.remove(std::static_pointer_cast<mac_window_info>(shared_from_this()));
+
+ // free the textures etc
+ complete_destroy();
+
+ // free the render target, after the textures!
+ machine().render().target_free(m_target);
+}
+
+
+//============================================================
+// pick_best_mode
+//============================================================
+
+osd_dim mac_window_info::pick_best_mode()
+{
+// int minimum_width, minimum_height, target_width, target_height;
+// int i;
+// int num;
+// float size_score, best_score = 0.0f;
+ osd_dim ret(0,0);
+#if 0
+ // determine the minimum width/height for the selected target
+ m_target->compute_minimum_size(minimum_width, minimum_height);
+
+ // use those as the target for now
+ target_width = minimum_width * std::max(1, prescale());
+ target_height = minimum_height * std::max(1, prescale());
+
+ // if we're not stretching, allow some slop on the minimum since we can handle it
+ {
+ minimum_width -= 4;
+ minimum_height -= 4;
+ }
+
+ // FIXME: this should be provided by monitor !
+ num = SDL_GetNumDisplayModes(m_monitor->oshandle());
+
+ if (num == 0)
+ {
+ osd_printf_error("SDL: No modes available?!\n");
+ exit(-1);
+ }
+ else
+ {
+ for (i = 0; i < num; ++i)
+ {
+ SDL_DisplayMode mode;
+ SDL_GetDisplayMode(m_monitor->oshandle(), i, &mode);
+
+ // compute initial score based on difference between target and current
+ size_score = 1.0f / (1.0f + abs((int32_t)mode.w - target_width) + abs((int32_t)mode.h - target_height));
+
+ // if the mode is too small, give a big penalty
+ if (mode.w < minimum_width || mode.h < minimum_height)
+ size_score *= 0.01f;
+
+ // if mode is smaller than we'd like, it only scores up to 0.1
+ if (mode.w < target_width || mode.h < target_height)
+ size_score *= 0.1f;
+
+ // if we're looking for a particular mode, that's a winner
+ if (mode.w == m_win_config.width && mode.h == m_win_config.height)
+ size_score = 2.0f;
+
+ // refresh adds some points
+ if (m_win_config.refresh)
+ size_score *= 1.0f / (1.0f + abs(m_win_config.refresh - mode.refresh_rate) / 10.0f);
+
+ osd_printf_verbose("%4dx%4d@%2d -> %f\n", (int)mode.w, (int)mode.h, (int) mode.refresh_rate, (double) size_score);
+
+ // best so far?
+ if (size_score > best_score)
+ {
+ best_score = size_score;
+ ret = osd_dim(mode.w, mode.h);
+ }
+
+ }
+ }
+#endif
+ return ret;
+}
+
+//============================================================
+// sdlwindow_video_window_update
+// (main thread)
+//============================================================
+
+void mac_window_info::update()
+{
+ osd_ticks_t event_wait_ticks;
+
+ // adjust the cursor state
+ //sdlwindow_update_cursor_state(machine, window);
+
+ update_cursor_state();
+
+ // if we're visible and running and not in the middle of a resize, draw
+ if (m_target != nullptr)
+ {
+ int tempwidth, tempheight;
+
+ // see if the games video mode has changed
+ m_target->compute_minimum_size(tempwidth, tempheight);
+ if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
+ {
+ m_minimum_dim = osd_dim(tempwidth, tempheight);
+
+ if (!this->m_fullscreen)
+ {
+ //Don't resize window without user interaction;
+ //window_resize(blitwidth, blitheight);
+ }
+ else if (video_config.switchres)
+ {
+ osd_dim tmp = this->pick_best_mode();
+ resize(tmp.width(), tmp.height());
+ }
+ }
+
+ if (video_config.waitvsync && video_config.syncrefresh)
+ event_wait_ticks = osd_ticks_per_second(); // block at most a second
+ else
+ event_wait_ticks = 0;
+
+ if (m_rendered_event.wait(event_wait_ticks))
+ {
+ const int update = 1;
+
+ // ensure the target bounds are up-to-date, and then get the primitives
+
+ render_primitive_list &primlist = *renderer().get_primitives();
+
+ // and redraw now
+
+ // Some configurations require events to be polled in the worker thread
+ downcast< mac_osd_interface& >(machine().osd()).process_events_buf();
+
+ // Check whether window has vector screens
+
+ {
+ const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index);
+ if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR))
+ renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
+ else
+ renderer().clear_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
+ }
+
+ m_primlist = &primlist;
+
+ // if no bitmap, just fill
+ if (m_primlist == nullptr)
+ {
+ }
+ // otherwise, render with our drawing system
+ else
+ {
+ if( video_config.perftest )
+ measure_fps(update);
+ else
+ renderer().draw(update);
+ }
+
+ /* all done, ready for next */
+ m_rendered_event.set();
+ }
+ }
+}
+
+
+//============================================================
+// set_starting_view
+// (main thread)
+//============================================================
+
+void mac_window_info::set_starting_view(int index, const char *defview, const char *view)
+{
+ int viewindex;
+
+ // choose non-auto over auto
+ if (strcmp(view, "auto") == 0 && strcmp(defview, "auto") != 0)
+ view = defview;
+
+ // query the video system to help us pick a view
+ viewindex = target()->configured_view(view, index, video_config.numscreens);
+
+ // set the view
+ target()->set_view(viewindex);
+}
+
+
+//============================================================
+// complete_create
+//============================================================
+
+extern void *CreateMAMEWindow(char *title, int x, int y, int w, int h, bool isFullscreen);
+extern void *GetOSWindow(void *wincontroller);
+
+int mac_window_info::complete_create()
+{
+ osd_dim temp(0,0);
+
+ // clear out original mode. Needed on OSX
+ if (fullscreen())
+ {
+ // default to the current mode exactly
+ temp = monitor()->position_size().dim();
+
+ // if we're allowed to switch resolutions, override with something better
+ if (video_config.switchres)
+ temp = pick_best_mode();
+ }
+ else if (m_windowed_dim.width() > 0)
+ {
+ // if we have a remembered size force the new window size to it
+ temp = m_windowed_dim;
+ }
+ else if (m_startmaximized)
+ temp = get_max_bounds(video_config.keepaspect );
+ else
+ temp = get_min_bounds(video_config.keepaspect );
+
+ // create the window .....
+ osd_printf_verbose("Enter mac_window_info::complete_create\n");
+
+ // get monitor work area for centering
+ osd_rect work = monitor()->usuable_position_size();
+
+ auto window = CreateMAMEWindow(m_title,
+ work.left() + (work.width() - temp.width()) / 2,
+ work.top() + (work.height() - temp.height()) / 2,
+ temp.width(), temp.height(), fullscreen());
+
+ if (window == nullptr)
+ {
+ osd_printf_error("Window creation failed!\n");
+ return 1;
+ }
+
+ set_platform_window(window);
+
+ // set main window
+ if (m_index > 0)
+ {
+ for (auto w : osd_common_t::s_window_list)
+ {
+ if (w->m_index == 0)
+ {
+ set_main_window(std::dynamic_pointer_cast<osd_window>(w));
+ break;
+ }
+ }
+ }
+ else
+ {
+ // We must be the main window
+ set_main_window(shared_from_this());
+ }
+
+ // update monitor resolution after mode change to ensure proper pixel aspect
+ monitor()->refresh();
+ if (fullscreen() && video_config.switchres)
+ monitor()->update_resolution(temp.width(), temp.height());
+
+ // initialize the drawing backend
+ if (renderer().create())
+ {
+ osd_printf_verbose("Exiting mac_window_info::complete_create\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+//============================================================
+// draw_video_contents
+// (window thread)
+//============================================================
+
+void mac_window_info::measure_fps(int update)
+{
+ const unsigned long frames_skip4fps = 100;
+ static int64_t lastTime=0, sumdt=0, startTime=0;
+ static unsigned long frames = 0;
+ int64_t currentTime, t0;
+ double dt;
+ double tps;
+ osd_ticks_t tps_t;
+
+ tps_t = osd_ticks_per_second();
+ tps = (double) tps_t;
+
+ t0 = osd_ticks();
+
+ renderer().draw(update);
+
+ frames++;
+ currentTime = osd_ticks();
+ if(startTime==0||frames==frames_skip4fps)
+ startTime=currentTime;
+ if( frames>=frames_skip4fps )
+ sumdt+=currentTime-t0;
+ if( (currentTime-lastTime)>1L*osd_ticks_per_second() && frames>frames_skip4fps )
+ {
+ dt = (double) (currentTime-startTime) / tps; // in decimale sec.
+ osd_printf_info("%6.2lfs, %4lu F, "
+ "avrg game: %5.2lf FPS %.2lf ms/f, "
+ "avrg video: %5.2lf FPS %.2lf ms/f, "
+ "last video: %5.2lf FPS %.2lf ms/f\n",
+ dt, frames-frames_skip4fps,
+ (double)(frames-frames_skip4fps)/dt, // avrg game fps
+ ( (currentTime-startTime) / ((frames-frames_skip4fps)) ) * 1000.0 / osd_ticks_per_second(),
+ (double)(frames-frames_skip4fps)/((double)(sumdt) / tps), // avrg vid fps
+ ( sumdt / ((frames-frames_skip4fps)) ) * 1000.0 / tps,
+ 1.0/((currentTime-t0) / osd_ticks_per_second()), // this vid fps
+ (currentTime-t0) * 1000.0 / tps
+ );
+ lastTime = currentTime;
+ }
+}
+
+int mac_window_info::wnd_extra_width()
+{
+ return m_fullscreen ? 0 : WINDOW_DECORATION_WIDTH;
+}
+
+int mac_window_info::wnd_extra_height()
+{
+ return m_fullscreen ? 0 : WINDOW_DECORATION_HEIGHT;
+}
+
+
+//============================================================
+// constrain_to_aspect_ratio
+// (window thread)
+//============================================================
+
+osd_rect mac_window_info::constrain_to_aspect_ratio(const osd_rect &rect, int adjustment)
+{
+ int32_t extrawidth = wnd_extra_width();
+ int32_t extraheight = wnd_extra_height();
+ int32_t propwidth, propheight;
+ int32_t minwidth, minheight;
+ int32_t maxwidth, maxheight;
+ int32_t viswidth, visheight;
+ int32_t adjwidth, adjheight;
+ float pixel_aspect;
+ std::shared_ptr<osd_monitor_info> monitor = m_monitor;
+
+ // do not constrain aspect ratio for integer scaled views
+ if (m_target->scale_mode() != SCALE_FRACTIONAL)
+ return rect;
+
+ // get the pixel aspect ratio for the target monitor
+ pixel_aspect = monitor->pixel_aspect();
+
+ // determine the proposed width/height
+ propwidth = rect.width() - extrawidth;
+ propheight = rect.height() - extraheight;
+
+ // based on which edge we are adjusting, take either the width, height, or both as gospel
+ // and scale to fit using that as our parameter
+ switch (adjustment)
+ {
+ case WMSZ_BOTTOM:
+ case WMSZ_TOP:
+ m_target->compute_visible_area(10000, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ break;
+
+ case WMSZ_LEFT:
+ case WMSZ_RIGHT:
+ m_target->compute_visible_area(propwidth, 10000, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ break;
+
+ default:
+ m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), propwidth, propheight);
+ break;
+ }
+
+ // get the minimum width/height for the current layout
+ m_target->compute_minimum_size(minwidth, minheight);
+
+ // clamp against the absolute minimum
+ propwidth = std::max(propwidth, MIN_WINDOW_DIM);
+ propheight = std::max(propheight, MIN_WINDOW_DIM);
+
+ // clamp against the minimum width and height
+ propwidth = std::max(propwidth, minwidth);
+ propheight = std::max(propheight, minheight);
+
+ // clamp against the maximum (fit on one screen for full screen mode)
+ if (m_fullscreen)
+ {
+ maxwidth = monitor->position_size().width() - extrawidth;
+ maxheight = monitor->position_size().height() - extraheight;
+ }
+ else
+ {
+ maxwidth = monitor->usuable_position_size().width() - extrawidth;
+ maxheight = monitor->usuable_position_size().height() - extraheight;
+
+ // further clamp to the maximum width/height in the window
+ if (m_win_config.width != 0)
+ maxwidth = std::min(maxwidth, m_win_config.width + extrawidth);
+ if (m_win_config.height != 0)
+ maxheight = std::min(maxheight, m_win_config.height + extraheight);
+ }
+
+ // clamp to the maximum
+ propwidth = std::min(propwidth, maxwidth);
+ propheight = std::min(propheight, maxheight);
+
+ // compute the visible area based on the proposed rectangle
+ m_target->compute_visible_area(propwidth, propheight, pixel_aspect, m_target->orientation(), viswidth, visheight);
+
+ // compute the adjustments we need to make
+ adjwidth = (viswidth + extrawidth) - rect.width();
+ adjheight = (visheight + extraheight) - rect.height();
+
+ // based on which corner we're adjusting, constrain in different ways
+ osd_rect ret(rect);
+
+ switch (adjustment)
+ {
+ case WMSZ_BOTTOM:
+ case WMSZ_BOTTOMRIGHT:
+ case WMSZ_RIGHT:
+ ret = rect.resize(rect.width() + adjwidth, rect.height() + adjheight);
+ break;
+
+ case WMSZ_BOTTOMLEFT:
+ ret = rect.move_by(-adjwidth, 0).resize(rect.width() + adjwidth, rect.height() + adjheight);
+ break;
+
+ case WMSZ_LEFT:
+ case WMSZ_TOPLEFT:
+ case WMSZ_TOP:
+ ret = rect.move_by(-adjwidth, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight);
+ break;
+
+ case WMSZ_TOPRIGHT:
+ ret = rect.move_by(0, -adjheight).resize(rect.width() + adjwidth, rect.height() + adjheight);
+ break;
+}
+ return ret;
+}
+
+
+
+//============================================================
+// get_min_bounds
+// (window thread)
+//============================================================
+
+osd_dim mac_window_info::get_min_bounds(int constrain)
+{
+ int32_t minwidth, minheight;
+
+ //assert(GetCurrentThreadId() == window_threadid);
+
+ // get the minimum target size
+ m_target->compute_minimum_size(minwidth, minheight);
+
+ // expand to our minimum dimensions
+ if (minwidth < MIN_WINDOW_DIM)
+ minwidth = MIN_WINDOW_DIM;
+ if (minheight < MIN_WINDOW_DIM)
+ minheight = MIN_WINDOW_DIM;
+
+ // account for extra window stuff
+ minwidth += wnd_extra_width();
+ minheight += wnd_extra_height();
+
+ // if we want it constrained, figure out which one is larger
+ if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL)
+ {
+ // first constrain with no height limit
+ osd_rect test1(0,0,minwidth,10000);
+ test1 = constrain_to_aspect_ratio(test1, WMSZ_BOTTOMRIGHT);
+
+ // then constrain with no width limit
+ osd_rect test2(0,0,10000,minheight);
+ test2 = constrain_to_aspect_ratio(test2, WMSZ_BOTTOMRIGHT);
+
+ // pick the larger
+ if (test1.width() > test2.width())
+ {
+ minwidth = test1.width();
+ minheight = test1.height();
+ }
+ else
+ {
+ minwidth = test2.width();
+ minheight = test2.height();
+ }
+ }
+
+ // remove extra window stuff
+ minwidth -= wnd_extra_width();
+ minheight -= wnd_extra_height();
+
+ return osd_dim(minwidth, minheight);
+}
+
+//============================================================
+// get_size
+//============================================================
+
+osd_dim mac_window_info::get_size()
+{
+ int w=0; int h=0;
+ // TODO: get window size from ObjC
+// SDL_GetWindowSize(platform_window(), &w, &h);
+ return osd_dim(w,h);
+}
+
+
+//============================================================
+// get_max_bounds
+// (window thread)
+//============================================================
+
+osd_dim mac_window_info::get_max_bounds(int constrain)
+{
+ //assert(GetCurrentThreadId() == window_threadid);
+
+ // compute the maximum client area
+ // m_monitor->refresh();
+ osd_rect maximum = m_monitor->usuable_position_size();
+
+ // clamp to the window's max
+ int tempw = maximum.width();
+ int temph = maximum.height();
+ if (m_win_config.width != 0)
+ {
+ int temp = m_win_config.width + wnd_extra_width();
+ if (temp < maximum.width())
+ tempw = temp;
+ }
+ if (m_win_config.height != 0)
+ {
+ int temp = m_win_config.height + wnd_extra_height();
+ if (temp < maximum.height())
+ temph = temp;
+ }
+
+ maximum = maximum.resize(tempw, temph);
+
+ // constrain to fit
+ if (constrain && m_target->scale_mode() == SCALE_FRACTIONAL)
+ maximum = constrain_to_aspect_ratio(maximum, WMSZ_BOTTOMRIGHT);
+
+ // remove extra window stuff
+ maximum = maximum.resize(maximum.width() - wnd_extra_width(), maximum.height() - wnd_extra_height());
+
+ return maximum.dim();
+}
+
+//============================================================
+// construction and destruction
+//============================================================
+
+mac_window_info::mac_window_info(
+ running_machine &a_machine,
+ int index,
+ std::shared_ptr<osd_monitor_info> a_monitor,
+ const osd_window_config *config)
+ : osd_window_t(*config)
+ , m_next(nullptr)
+ , m_startmaximized(0)
+ // Following three are used by input code to defer resizes
+ , m_minimum_dim(0, 0)
+ , m_windowed_dim(0, 0)
+ , m_rendered_event(0, 1)
+ , m_target(nullptr)
+ , m_machine(a_machine)
+ , m_monitor(a_monitor)
+ , m_fullscreen(0)
+ , m_mouse_captured(false)
+ , m_mouse_hidden(false)
+{
+ m_index = index;
+
+ //FIXME: these should be per_window in config-> or even better a bit set
+ m_fullscreen = !video_config.windowed;
+ m_prescale = video_config.prescale;
+
+ m_windowed_dim = osd_dim(config->width, config->height);
+}
+
+mac_window_info::~mac_window_info()
+{
+}
+
+
+//============================================================
+// osd_set_aggressive_input_focus
+//============================================================
+
+void osd_set_aggressive_input_focus(bool aggressive_focus)
+{
+ // dummy implementation for now
+}
diff --git a/src/osd/mac/window.h b/src/osd/mac/window.h
new file mode 100644
index 00000000000..24e749a425b
--- /dev/null
+++ b/src/osd/mac/window.h
@@ -0,0 +1,134 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont
+//============================================================
+//
+// window.h - SDL window handling
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#ifndef __MACWINDOW__
+#define __MACWINDOW__
+
+#include "osdmac.h"
+#include "video.h"
+
+#include "modules/osdwindow.h"
+
+#include <cstdint>
+#include <memory>
+#include <list>
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class render_target;
+
+typedef uintptr_t HashT;
+
+#define OSDWORK_CALLBACK(name) void *name(void *param, ATTR_UNUSED int threadid)
+
+class mac_window_info : public osd_window_t<void *>
+{
+public:
+ mac_window_info(running_machine &a_machine, int index, std::shared_ptr<osd_monitor_info> a_monitor,
+ const osd_window_config *config);
+
+ ~mac_window_info();
+
+ int window_init();
+
+ void update() override;
+ void toggle_full_screen();
+ void modify_prescale(int dir);
+ void resize(int32_t width, int32_t height);
+ void destroy() override;
+
+ void capture_pointer() override;
+ void release_pointer() override;
+ void show_pointer() override;
+ void hide_pointer() override;
+
+ void notify_changed();
+
+ osd_dim get_size() override;
+
+ int xy_to_render_target(int x, int y, int *xt, int *yt);
+
+ running_machine &machine() const override { return m_machine; }
+ osd_monitor_info *monitor() const override { return m_monitor.get(); }
+ int fullscreen() const override { return m_fullscreen; }
+
+ render_target *target() override { return m_target; }
+
+ int prescale() const { return m_prescale; }
+
+ // Pointer to next window
+ mac_window_info * m_next;
+
+private:
+ // window handle and info
+ char m_title[256];
+ int m_startmaximized;
+
+ // dimensions
+ osd_dim m_minimum_dim;
+ osd_dim m_windowed_dim;
+
+ // rendering info
+ osd_event m_rendered_event;
+ render_target * m_target;
+
+ //int m_extra_flags;
+
+ // returns 0 on success, else 1
+ int complete_create();
+ void complete_destroy();
+
+private:
+ int wnd_extra_width();
+ int wnd_extra_height();
+ void set_starting_view(int index, const char *defview, const char *view);
+ osd_rect constrain_to_aspect_ratio(const osd_rect &rect, int adjustment);
+ osd_dim get_min_bounds(int constrain);
+ osd_dim get_max_bounds(int constrain);
+ void update_cursor_state();
+ osd_dim pick_best_mode();
+ void set_fullscreen(int afullscreen) { m_fullscreen = afullscreen; }
+
+ // Pointer to machine
+ running_machine & m_machine;
+
+ // monitor info
+ std::shared_ptr<osd_monitor_info> m_monitor;
+ int m_fullscreen;
+ bool m_mouse_captured;
+ bool m_mouse_hidden;
+
+ void measure_fps(int update);
+};
+
+struct osd_draw_callbacks
+{
+ osd_renderer *(*create)(osd_window *window);
+};
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+//============================================================
+// PROTOTYPES - drawogl.c
+//============================================================
+
+int drawogl_init(running_machine &machine, osd_draw_callbacks *callbacks);
+
+//============================================================
+// PROTOTYPES - drawbgfx.c
+//============================================================
+
+int drawbgfx_init(running_machine &machine, osd_draw_callbacks *callbacks);
+
+#endif /* __MACWINDOW__ */
diff --git a/src/osd/mac/windowcontroller.h b/src/osd/mac/windowcontroller.h
new file mode 100644
index 00000000000..54f0b3376e1
--- /dev/null
+++ b/src/osd/mac/windowcontroller.h
@@ -0,0 +1,16 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// windowcontroller.mm - our window/fullscreen manager
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import <Cocoa/Cocoa.h>
+#import "oglview.h"
+
+@interface MAMEWindowController : NSWindowController
+
+@end
diff --git a/src/osd/mac/windowcontroller.mm b/src/osd/mac/windowcontroller.mm
new file mode 100644
index 00000000000..396fbc49238
--- /dev/null
+++ b/src/osd/mac/windowcontroller.mm
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+//============================================================
+//
+// windowcontroller.mm - our window/fullscreen manager
+//
+// Mac OSD by R. Belmont
+//
+//============================================================
+
+#import "windowcontroller.h"
+#import "mamefswindow.h"
+
+@interface MAMEWindowController ()
+{
+ MAMEFSWindow *_fullscreenWindow;
+ NSWindow* _standardWindow;
+}
+@end
+
+@implementation MAMEWindowController
+
+- (instancetype)initWithWindow:(NSWindow *)window
+{
+ self = [super initWithWindow:window];
+
+ if (self)
+ {
+ _fullscreenWindow = nil;
+ _standardWindow = window;
+ }
+
+ return self;
+}
+
+- (void) goFullscreen
+{
+ if(_fullscreenWindow)
+ {
+ return;
+ }
+
+ _fullscreenWindow = [[MAMEFSWindow alloc] init];
+
+ NSRect viewRect = [_fullscreenWindow frame];
+ [self.window.contentView setFrameSize: viewRect.size];
+ [_fullscreenWindow setContentView:self.window.contentView];
+
+ _standardWindow = [self window];
+ [_standardWindow orderOut:self];
+
+ [self setWindow:_fullscreenWindow];
+ [_fullscreenWindow makeKeyAndOrderFront:self];
+}
+
+- (void) goWindow
+{
+ if(_fullscreenWindow == nil)
+ {
+ return;
+ }
+
+ NSRect viewRect = [_standardWindow frame];
+ [self.window.contentView setFrame:viewRect];
+
+ [self setWindow:_standardWindow];
+ [[self window] setContentView:_fullscreenWindow.contentView];
+ [[self window] makeKeyAndOrderFront:self];
+
+ _fullscreenWindow = nil;
+}
+
+
+- (void) keyDown:(NSEvent *)event
+{
+// unichar c = [[event charactersIgnoringModifiers] characterAtIndex:0];
+ [super keyDown:event];
+}
+
+- (NSWindow *) getWindow
+{
+ if(_fullscreenWindow == nil)
+ {
+ return _standardWindow;
+ }
+
+ return _fullscreenWindow;
+}
+@end
+
+void *GetOSWindow(void *wincontroller)
+{
+ MAMEWindowController *wc = (MAMEWindowController *)wincontroller;
+
+ return [wc getWindow];
+}
+
+void *CreateMAMEWindow(char *title, int x, int y, int w, int h, bool isFullscreen)
+{
+ NSRect bounds = NSMakeRect(x, y, w, h);
+ NSUInteger style = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
+ NSWindow *window = [NSWindow alloc];
+ MAMEWindowController *controller = [MAMEWindowController alloc];
+
+ dispatch_sync(dispatch_get_main_queue(), ^{
+ [window initWithContentRect:bounds
+ styleMask:style
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ [controller initWithWindow:window];
+ });
+
+ if (isFullscreen)
+ {
+ [controller goFullscreen];
+ }
+
+ [window makeKeyAndOrderFront:nil];
+
+ return (void *)controller;
+}
diff --git a/src/osd/modules/opengl/osd_opengl.h b/src/osd/modules/opengl/osd_opengl.h
index 26f577f343e..47d0b3c429c 100644
--- a/src/osd/modules/opengl/osd_opengl.h
+++ b/src/osd/modules/opengl/osd_opengl.h
@@ -32,6 +32,9 @@
#include "GL/wglext.h"
#endif
#endif
+ #elif defined(OSD_MAC)
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glext.h>
#else
#include <SDL2/SDL_version.h>
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index 0c483d9eb59..3c15bc3cf96 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -15,8 +15,12 @@
#include <SDL2/SDL_syswm.h>
#endif
#else
+#if defined(OSD_MAC)
+extern void *GetOSWindow(void *wincontroller);
+#else
#include <SDL2/SDL_syswm.h>
#endif
+#endif
// MAMEOS headers
#include "emu.h"
@@ -143,6 +147,17 @@ inline void winSetHwnd(::HWND _window)
pd.backBufferDS = NULL;
bgfx::setPlatformData(pd);
}
+#elif defined(OSD_MAC)
+inline void macSetWindow(void *_window)
+{
+ bgfx::PlatformData pd;
+ pd.ndt = NULL;
+ pd.nwh = GetOSWindow(_window);
+ pd.context = NULL;
+ pd.backBuffer = NULL;
+ pd.backBufferDS = NULL;
+ bgfx::setPlatformData(pd);
+}
#elif defined(OSD_SDL)
static void* sdlNativeWindowHandle(SDL_Window* _window)
{
@@ -240,6 +255,8 @@ int renderer_bgfx::create()
#elif defined(OSD_UWP)
winrtSetWindow(AsInspectable(std::static_pointer_cast<uwp_window_info>(win)->platform_window()));
+#elif defined(OSD_MAC)
+ macSetWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window());
#else
sdlSetWindow(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window());
#endif
@@ -296,6 +313,8 @@ int renderer_bgfx::create()
m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), m_width[win->m_index], m_height[win->m_index]);
#elif defined(OSD_UWP)
m_framebuffer = m_targets->create_backbuffer(AsInspectable(std::static_pointer_cast<uwp_window_info>(win)->platform_window()), m_width[win->m_index], m_height[win->m_index]);
+#elif defined(OSD_MAC)
+ m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), m_width[win->m_index], m_height[win->m_index]);
#else
m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), m_width[win->m_index], m_height[win->m_index]);
#endif
@@ -949,6 +968,8 @@ bool renderer_bgfx::update_dimensions()
m_framebuffer = m_targets->create_backbuffer(std::static_pointer_cast<win_window_info>(win)->platform_window(), width, height);
#elif defined(OSD_UWP)
m_framebuffer = m_targets->create_backbuffer(AsInspectable(std::static_pointer_cast<uwp_window_info>(win)->platform_window()), width, height);
+#elif defined(OSD_MAC)
+ m_framebuffer = m_targets->create_backbuffer(GetOSWindow(std::static_pointer_cast<mac_window_info>(win)->platform_window()), width, height);
#else
m_framebuffer = m_targets->create_backbuffer(sdlNativeWindowHandle(std::dynamic_pointer_cast<sdl_window_info>(win)->platform_window()), width, height);
#endif
diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp
index 6c1cb405316..bd4648be474 100644
--- a/src/osd/modules/render/drawogl.cpp
+++ b/src/osd/modules/render/drawogl.cpp
@@ -21,7 +21,11 @@
#include "emu.h"
#include "emuopts.h"
-#ifndef OSD_WINDOWS
+#ifdef OSD_MAC
+#define GL_SILENCE_DEPRECATION (1)
+#endif
+
+#if !defined(OSD_WINDOWS) && !defined(OSD_MAC)
// standard SDL headers
#define TOBEMIGRATED 1
#include <SDL2/SDL.h>
@@ -36,7 +40,7 @@
#include "modules/opengl/gl_shader_tool.h"
#include "modules/opengl/gl_shader_mgr.h"
-#if defined(SDLMAME_MACOSX)
+#if defined(SDLMAME_MACOSX) || defined(OSD_MAC)
#ifndef APIENTRY
#define APIENTRY
#endif
@@ -237,7 +241,7 @@ void renderer_ogl::set_blendmode(int blendmode)
//============================================================
// OGL 1.3
-#ifdef GL_ARB_multitexture
+#if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
static PFNGLACTIVETEXTUREARBPROC pfn_glActiveTexture = nullptr;
#else
static PFNGLACTIVETEXTUREPROC pfn_glActiveTexture = nullptr;
@@ -558,6 +562,9 @@ int renderer_ogl::create()
// create renderer
#if defined(OSD_WINDOWS)
m_gl_context = global_alloc(win_gl_context(std::static_pointer_cast<win_window_info>(win)->platform_window()));
+#elif defined(OSD_MAC)
+// TODO
+// m_gl_context = global_alloc(mac_gl_context(std::static_pointer_cast<mac_window_info>(win)->platform_window()));
#else
m_gl_context = global_alloc(sdl_gl_context(std::static_pointer_cast<sdl_window_info>(win)->platform_window()));
#endif
@@ -886,7 +893,7 @@ void renderer_ogl::loadGLExtensions()
if ( m_useglsl )
{
- #ifdef GL_ARB_multitexture
+ #if defined(GL_ARB_multitexture) && !defined(OSD_MAC)
pfn_glActiveTexture = (PFNGLACTIVETEXTUREARBPROC) m_gl_context->getProcAddress("glActiveTextureARB");
#else
pfn_glActiveTexture = (PFNGLACTIVETEXTUREPROC) m_gl_context->getProcAddress("glActiveTexture");
diff --git a/src/osd/modules/render/drawogl.h b/src/osd/modules/render/drawogl.h
index 5444f203141..525ba0c3ffa 100644
--- a/src/osd/modules/render/drawogl.h
+++ b/src/osd/modules/render/drawogl.h
@@ -15,7 +15,11 @@
// OSD headers
#ifndef OSD_WINDOWS
+#ifdef OSD_MAC
+#include "osdmac.h"
+#else
#include "osdsdl.h"
+#endif
#include "window.h"
#else
#include "../windows/window.h"
@@ -24,6 +28,7 @@ typedef uint64_t HashT;
#if defined(OSD_WINDOWS)
#include "winglcontext.h"
+#elif defined (OSD_MAC)
#else
#include "sdlglcontext.h"
#endif