summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-02-18 23:54:31 +0100
committerCarl Hetherington <cth@carlh.net>2025-12-13 23:19:46 +0100
commit09c8ab5e4cdddc95ef28efa9f39d2c42a8edc6dd (patch)
tree538644ed08628fb6955db6fcf6eefda6cd913933
parent7b48d09b9df654cb24f56de8b95b2952927d8687 (diff)
WIP: Metal backend for macOS.
-rwxr-xr-xrun/dcpomatic4
-rw-r--r--src/lib/config.cc9
-rw-r--r--src/lib/config.h5
-rw-r--r--src/wx/film_viewer.cc8
-rw-r--r--src/wx/full_config_dialog.cc16
-rw-r--r--src/wx/metal_video_view.cc100
-rw-r--r--src/wx/metal_video_view.h64
-rw-r--r--src/wx/metal_video_view.mm9
-rw-r--r--src/wx/player_config_dialog.cc18
-rw-r--r--src/wx/wscript6
-rw-r--r--wscript6
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'
diff --git a/wscript b/wscript
index cbcc9c88e..089226546 100644
--- a/wscript
+++ b/wscript
@@ -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')