diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-02-18 23:54:31 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-12-13 23:19:46 +0100 |
| commit | 09c8ab5e4cdddc95ef28efa9f39d2c42a8edc6dd (patch) | |
| tree | 538644ed08628fb6955db6fcf6eefda6cd913933 | |
| parent | 7b48d09b9df654cb24f56de8b95b2952927d8687 (diff) | |
WIP: Metal backend for macOS.
| -rwxr-xr-x | run/dcpomatic | 4 | ||||
| -rw-r--r-- | src/lib/config.cc | 9 | ||||
| -rw-r--r-- | src/lib/config.h | 5 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 8 | ||||
| -rw-r--r-- | src/wx/full_config_dialog.cc | 16 | ||||
| -rw-r--r-- | src/wx/metal_video_view.cc | 100 | ||||
| -rw-r--r-- | src/wx/metal_video_view.h | 64 | ||||
| -rw-r--r-- | src/wx/metal_video_view.mm | 9 | ||||
| -rw-r--r-- | src/wx/player_config_dialog.cc | 18 | ||||
| -rw-r--r-- | src/wx/wscript | 6 | ||||
| -rw-r--r-- | wscript | 6 |
11 files changed, 238 insertions, 7 deletions
diff --git a/run/dcpomatic b/run/dcpomatic index e415f426c..61deb4a8d 100755 --- a/run/dcpomatic +++ b/run/dcpomatic @@ -18,7 +18,9 @@ export LD_LIBRARY_PATH=$DIR/../../../lib:$DIR/../../../lib64:$LD_LIBRARY_PATH if [ "$1" == "--debug" ]; then shift if [[ "$(uname)" == Darwin ]]; then - /Applications/Xcode.app/Contents/Developer/usr/bin/lldb $binary $* + # /Applications/Xcode.app/Contents/Developer/usr/bin/lldb $binary $* + /Applications/Xcode/14.3.1/Xcode.app/Contents/Developer/usr/bin/lldb $binary $* + # lldb $binary $* else gdb --args $binary $* fi diff --git a/src/lib/config.cc b/src/lib/config.cc index 267831341..1766fa7b7 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -616,6 +616,10 @@ try _video_view_type = VIDEO_VIEW_OPENGL; } else if (vc && *vc == "simple") { _video_view_type = VIDEO_VIEW_SIMPLE; +#ifdef DCPOMATIC_OSX + } else if (vc && *vc == "metal") { + _video_view_type = VIDEO_VIEW_METAL; +#endif } _respect_kdm_validity_periods = f.optional_bool_child("RespectKDMValidityPeriods").get_value_or(true); _player_debug_log_file = f.optional_string_child("PlayerDebugLogFile"); @@ -1092,6 +1096,11 @@ Config::write_config() const case VIDEO_VIEW_OPENGL: cxml::add_text_child(root, "VideoViewType", "opengl"); break; +#ifdef DCPOMATIC_OSX + case VIDEO_VIEW_METAL: + cxml::add_text_child(root, "VideoViewType", "metal"); + break; +#endif } /* [XML] RespectKDMValidityPeriods 1 to refuse to use KDMs that are out of date, 0 to ignore KDM dates. */ cxml::add_text_child(root, "RespectKDMValidityPeriods", _respect_kdm_validity_periods ? "1" : "0"); diff --git a/src/lib/config.h b/src/lib/config.h index d562481be..8fb29ca19 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -563,7 +563,12 @@ public: enum VideoViewType { VIDEO_VIEW_SIMPLE, +#ifdef DCPOMATIC_OSX + VIDEO_VIEW_OPENGL, + VIDEO_VIEW_METAL +#else VIDEO_VIEW_OPENGL +#endif }; VideoViewType video_view_type() const { diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index dbda1d7f1..1a8621a06 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -28,6 +28,9 @@ #include "closed_captions_dialog.h" #include "film_viewer.h" #include "gl_video_view.h" +#ifdef DCPOMATIC_OSX +#include "metal_video_view.h" +#endif #include "nag_dialog.h" #include "playhead_to_frame_dialog.h" #include "playhead_to_timecode_dialog.h" @@ -97,6 +100,11 @@ FilmViewer::FilmViewer(wxWindow* p, bool wake) case Config::VIDEO_VIEW_SIMPLE: _video_view = std::make_shared<SimpleVideoView>(this, p, wake); break; +#ifdef DCPOMATIC_OSX + case Config::VIDEO_VIEW_METAL: + _video_view = std::make_shared<MetalVideoView>(this, p); + break; +#endif } #else _video_view = std::make_shared<SimpleVideoView>(this, p, wake); diff --git a/src/wx/full_config_dialog.cc b/src/wx/full_config_dialog.cc index eff3fdee2..4937798e7 100644 --- a/src/wx/full_config_dialog.cc +++ b/src/wx/full_config_dialog.cc @@ -1311,7 +1311,10 @@ private: #if wxCHECK_VERSION(3, 1, 0) _video_display_mode->Append(_("OpenGL (faster)")); #endif - _video_display_mode->Bind(wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this)); +#ifdef DCPOMATIC_OSX + _video_display_mode->Append(_("Metal (faster)")); +#endif + _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this)); _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this); _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this); _layout_for_short_screen->bind(&AdvancedPage::layout_for_short_screen_changed, this); @@ -1344,6 +1347,11 @@ private: case Config::VIDEO_VIEW_OPENGL: checked_set(_video_display_mode, 1); break; +#ifdef DCPOMATIC_OSX + case Config::VIDEO_VIEW_METAL: + checked_set(_video_display_mode, 2); + break; +#endif } checked_set(_show_experimental_audio_processors, config->show_experimental_audio_processors()); checked_set(_only_servers_encode, config->only_servers_encode()); @@ -1368,8 +1376,12 @@ private: { if (_video_display_mode->GetSelection() == 0) { Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE); - } else { + } else if (_video_display_mode->GetSelection() == 1) { Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL); +#ifdef DCPOMATIC_OSX + } else if (_video_display_mode->GetSelection() == 2) { + Config::instance()->set_video_view_type(Config::VIDEO_VIEW_METAL); +#endif } } diff --git a/src/wx/metal_video_view.cc b/src/wx/metal_video_view.cc new file mode 100644 index 000000000..1c78ed78c --- /dev/null +++ b/src/wx/metal_video_view.cc @@ -0,0 +1,100 @@ +/* + Copyright (C) 2024 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic 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 Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "metal_video_view.h" +#include <dcp/warnings.h> + +LIBDCP_DISABLE_WARNINGS +#define NS_PRIVATE_IMPLEMENTATION +#define MTL_PRIVATE_IMPLEMENTATION +#define MTK_PRIVATE_IMPLEMENTATION +#define CA_PRIVATE_IMPLEMENTATION +#include <Metal/Metal.hpp> +#include <AppKit/AppKit.hpp> +#include <MetalKit/MetalKit.hpp> +LIBDCP_ENABLE_WARNINGS + + +class ViewDelegate : public MTK::ViewDelegate +{ +public: + ViewDelegate(MTL::Device* device) + : _device(device) + {} + + virtual void drawInMTKView(MTK::View* view) override + { + std::cout << "AWOOGA\n"; + } + +private: + MTL::Device* _device; +}; + + +MetalVideoView::MetalVideoView(FilmViewer* viewer, wxWindow* parent) + : VideoView(viewer, false) + , _canvas(new wxWindow(parent, wxID_ANY)) +{ + _device = MTLCreateSystemDefaultDevice(); + _view = MTK::View::alloc()->init(CGRect{{0, 0}, {512, 512}}, _device); + _view->setColorPixelFormat(MTL::PixelFormat::PixelFormatBGRA8Unorm_sRGB); + _view->setClearColor(MTL::ClearColor::Make(1.0, 0.0, 0.0, 1.0)); + _delegate = new ViewDelegate(_device); + _view->setDelegate(_delegate); + + set_layer(_canvas->GetHandle(), _view->currentDrawable()->layer()); +} + + +MetalVideoView::~MetalVideoView() +{ + _device->release(); +} + + +void +MetalVideoView::update() +{ + +} + + +void +MetalVideoView::start() +{ + +} + + +void +MetalVideoView::stop() +{ + +} + + +VideoView::NextFrameResult +MetalVideoView::display_next_frame(bool non_blocking) +{ + +} + diff --git a/src/wx/metal_video_view.h b/src/wx/metal_video_view.h new file mode 100644 index 000000000..51bdd3132 --- /dev/null +++ b/src/wx/metal_video_view.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2024 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic 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 Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "video_view.h" + + +namespace MTL { + class Device; +} + +namespace MTK { + class View; +} + + +class ViewDelegate; + + +class MetalVideoView : public VideoView +{ +public: + MetalVideoView(FilmViewer* viewer, wxWindow* parent); + ~MetalVideoView(); + + wxWindow* get() const override { + return _canvas; + } + + void update() override; + void start() override; + void stop() override; + + NextFrameResult display_next_frame(bool non_blocking) override; + +private: + wxWindow* _canvas; + MTL::Device* _device; + MTK::View* _view; + ViewDelegate* _delegate; +}; + + +struct NSView; + +void set_layer(NSView* view, void* layer); + diff --git a/src/wx/metal_video_view.mm b/src/wx/metal_video_view.mm new file mode 100644 index 000000000..174303bc7 --- /dev/null +++ b/src/wx/metal_video_view.mm @@ -0,0 +1,9 @@ +#import <AppKit/AppKit.h> +#import <QuartzCore/CAMetalLayer.h> + + +void set_layer(NSView* view, void* layer) +{ +// view.wantsLayer = YES; +// view.layer = [CAMetalLayer layer]; +} diff --git a/src/wx/player_config_dialog.cc b/src/wx/player_config_dialog.cc index 5c0a34940..501b82d76 100644 --- a/src/wx/player_config_dialog.cc +++ b/src/wx/player_config_dialog.cc @@ -125,6 +125,9 @@ private: _video_display_mode = new wxChoice(_panel, wxID_ANY); _video_display_mode->Append(_("Simple (safer)")); _video_display_mode->Append(_("OpenGL (faster)")); +#ifdef DCPOMATIC_OSX + _video_display_mode->Append(_("Metal (faster)")); +#endif table->Add(_video_display_mode, wxGBPosition(r, 1)); ++r; @@ -181,6 +184,11 @@ private: case Config::VIDEO_VIEW_OPENGL: checked_set(_video_display_mode, 1); break; +#ifdef DCPOMATIC_OSX + case Config::VIDEO_VIEW_METAL: + checked_set(_video_display_mode, 2); + break; +#endif } checked_set(_image_display, config->image_display()); @@ -218,10 +226,16 @@ private: void video_display_mode_changed() { - if (_video_display_mode->GetSelection() == 0) { + switch (_video_display_mode->GetSelection()) { + case 0: Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE); - } else { + break; + case 1: Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL); + break; + case 2: + Config::instance()->set_video_view_type(Config::VIDEO_VIEW_METAL); + break; } } diff --git a/src/wx/wscript b/src/wx/wscript index d3f3db88a..22ae2f60a 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -127,6 +127,8 @@ sources = """ markers_panel.cc message_dialog.cc metadata_dialog.cc + metal_video_view.cc + metal_video_view.mm move_to_dialog.cc nag_dialog.cc name_format_editor.cc @@ -335,6 +337,8 @@ def configure(conf): define_name='DCPOMATIC_HAVE_GLX_SWAP_INTERVAL_EXT', mandatory=False) + conf.env.CXXFLAGS.extend(["-I../metal-cpp", "-I../metal-cpp-extensions"]) + def build(bld): if bld.env.STATIC_DCPOMATIC: @@ -353,7 +357,7 @@ def build(bld): obj.uselib += 'WINSOCK2 OLE32 DSOUND WINMM KSUSER GL GLU GLEW ' obj.source += ' i18n_setup_windows.cc' if bld.env.TARGET_OSX: - obj.framework = ['CoreAudio', 'OpenGL'] + obj.framework = ['AppKit', 'CoreAudio', 'Metal', 'OpenGL', 'QuartzCore'] obj.source += ' i18n_setup_osx.cc' obj.use = 'libdcpomatic2' obj.target = 'dcpomatic2-wx' @@ -30,7 +30,7 @@ try: except ImportError: # python 3 from urllib.parse import urlencode -from waflib import Logs, Context +from waflib import Logs, Context, TaskGen APPNAME = 'dcpomatic' libdcp_version = '1.9.22' @@ -50,6 +50,10 @@ if this_version == '': else: VERSION = this_version[1:].strip() +@TaskGen.extension('.mm') +def mm_hook(self, node): + return self.create_compiled_task('cxx', node) + def options(opt): opt.load('compiler_cxx') opt.load('winres') |
