From bcf2eed456ace5abfd28f97d36eb0ef86ec8aaf3 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 19 Apr 2025 22:29:04 +0200 Subject: Move GLVideoView thread into GLView. --- src/wx/film_viewer.cc | 10 +++++++- src/wx/film_viewer.h | 2 ++ src/wx/gl_video_view.cc | 68 ++++++++++++------------------------------------- src/wx/gl_video_view.h | 11 +++----- src/wx/gl_view.cc | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/wx/gl_view.h | 20 ++++++++++++++- src/wx/video_view.h | 3 ++- 7 files changed, 118 insertions(+), 63 deletions(-) diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 5e1caa1bf..1cbdb00bd 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -435,7 +435,7 @@ FilmViewer::stop() _video_view->stop(); Stopped(); - _video_view->rethrow(); + rethrow(); return true; } @@ -929,3 +929,11 @@ FilmViewer::dcp() const return {}; } + + +void +FilmViewer::rethrow() +{ + _video_view->rethrow(); +} + diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 31fdbe0c7..8325930a0 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -157,6 +157,8 @@ public: Frame average_latency() const; + void rethrow(); + /** The image we are viewing changed: call last_image() to get the image */ boost::signals2::signal ImageChanged; std::shared_ptr last_image() const; diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index f515b4f53..d2a1d8c36 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -80,7 +80,6 @@ GLVideoView::GLVideoView(FilmViewer* viewer, wxWindow *parent) : VideoView(viewer) , GLView(parent) , _rec2020(false) - , _vsync_enabled(false) , _playing(false) , _one_shot(false) { @@ -99,16 +98,6 @@ GLVideoView::size_changed(wxSizeEvent const& ev) } -GLVideoView::~GLVideoView() -{ - boost::this_thread::disable_interruption dis; - - try { - _thread.interrupt(); - _thread.join(); - } catch (...) {} -} - void GLVideoView::check_for_butler_errors() { @@ -150,9 +139,7 @@ GLVideoView::update() } #endif - if (!_thread.joinable()) { - _thread = boost::thread(boost::bind(&GLVideoView::thread, this)); - } + start_thread_if_required(); request_one_shot(); @@ -865,8 +852,7 @@ GLVideoView::set_image_and_draw() void -GLVideoView::thread() -try +GLVideoView::thread_setup() { start_of_thread("GLVideoView"); @@ -882,40 +868,17 @@ try } #endif -#if defined(DCPOMATIC_LINUX) && defined(DCPOMATIC_HAVE_GLX_SWAP_INTERVAL_EXT) - if (_canvas->IsExtensionSupported("GLX_EXT_swap_control")) { - /* Enable vsync */ - Display* dpy = wxGetX11Display(); - glXSwapIntervalEXT(dpy, DefaultScreen(dpy), 1); - _vsync_enabled = true; - } -#endif - -#ifdef DCPOMATIC_WINDOWS - if (_canvas->IsExtensionSupported("WGL_EXT_swap_control")) { - /* Enable vsync */ - PFNWGLSWAPINTERVALEXTPROC swap = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); - if (swap) { - swap(1); - _vsync_enabled = true; - } - } - -#endif - -#ifdef DCPOMATIC_OSX - /* Enable vsync */ - GLint swapInterval = 1; - CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &swapInterval); - _vsync_enabled = true; -#endif - for (int i = 0; i < 3; ++i) { std::unique_ptr texture(new Texture(_optimisation == Optimisation::JPEG2000 ? 2 : 1, i)); _video_textures.push_back(std::move(texture)); } _subtitle_texture.reset(new Texture(1, 3)); +} + +void +GLVideoView::thread_body() +{ while (true) { boost::mutex::scoped_lock lm(_playing_mutex); while (!_playing && !_one_shot) { @@ -938,14 +901,6 @@ try * without also deleting the wxGLCanvas. */ } -catch (boost::thread_interrupted&) -{ - -} -catch (...) -{ - store_current(); -} VideoView::NextFrameResult @@ -1049,4 +1004,13 @@ Texture::set(shared_ptr image, int component) } } + +void +GLVideoView::rethrow() +{ + GLView::rethrow(); +} + + #endif + diff --git a/src/wx/gl_video_view.h b/src/wx/gl_video_view.h index 87a074d23..8d3509df3 100644 --- a/src/wx/gl_video_view.h +++ b/src/wx/gl_video_view.h @@ -68,7 +68,6 @@ class GLVideoView : public VideoView, public GLView { public: GLVideoView(FilmViewer* viewer, wxWindow* parent); - ~GLVideoView(); wxWindow* get() const override { return _canvas; @@ -76,24 +75,22 @@ public: void update() override; void start() override; void stop() override; + void rethrow() override; NextFrameResult display_next_frame(bool) override; - bool vsync_enabled() const { - return _vsync_enabled; - } - std::map information() const { return _information; } private: void size_changed(wxSizeEvent const &) override; + void thread_setup() override; + void thread_body() override; void set_image(std::shared_ptr pv); void set_image_and_draw(); void draw(); - void thread(); void thread_playing(); void request_one_shot(); void check_for_butler_errors(); @@ -134,8 +131,6 @@ private: std::vector> _video_textures; std::unique_ptr _subtitle_texture; bool _have_subtitle_to_render = false; - bool _vsync_enabled; - boost::thread _thread; boost::mutex _playing_mutex; boost::condition _thread_work_condition; diff --git a/src/wx/gl_view.cc b/src/wx/gl_view.cc index 567057e96..6b691fcd7 100644 --- a/src/wx/gl_view.cc +++ b/src/wx/gl_view.cc @@ -34,6 +34,7 @@ using namespace boost::placeholders; GLView::GLView(wxWindow* parent) : _context(nullptr) + , _vsync_enabled(false) { wxGLAttributes attributes; /* We don't need a depth buffer, and indeed there is apparently a bug with Windows/Intel HD 630 @@ -48,6 +49,17 @@ GLView::GLView(wxWindow* parent) } +GLView::~GLView() +{ + boost::this_thread::disable_interruption dis; + + try { + _thread.interrupt(); + _thread.join(); + } catch (...) {} +} + + void GLView::size_changed(wxSizeEvent const& ev) { @@ -59,5 +71,60 @@ GLView::size_changed(wxSizeEvent const& ev) } +void +GLView::start_thread_if_required() +{ + if (!_thread.joinable()) { + _thread = boost::thread(boost::bind(&GLView::thread, this)); + } +} + + +void +GLView::thread() +try +{ + thread_setup(); + +#if defined(DCPOMATIC_LINUX) && defined(DCPOMATIC_HAVE_GLX_SWAP_INTERVAL_EXT) + if (_canvas->IsExtensionSupported("GLX_EXT_swap_control")) { + /* Enable vsync */ + Display* dpy = wxGetX11Display(); + glXSwapIntervalEXT(dpy, DefaultScreen(dpy), 1); + _vsync_enabled = true; + } +#endif + +#ifdef DCPOMATIC_WINDOWS + if (_canvas->IsExtensionSupported("WGL_EXT_swap_control")) { + /* Enable vsync */ + PFNWGLSWAPINTERVALEXTPROC swap = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT"); + if (swap) { + swap(1); + _vsync_enabled = true; + } + } + +#endif + +#ifdef DCPOMATIC_OSX + /* Enable vsync */ + GLint swapInterval = 1; + CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &swapInterval); + _vsync_enabled = true; +#endif + + thread_body(); +} +catch (boost::thread_interrupted&) +{ + +} +catch (...) +{ + store_current(); +} + + #endif diff --git a/src/wx/gl_view.h b/src/wx/gl_view.h index e7a30021d..cdcf2af88 100644 --- a/src/wx/gl_view.h +++ b/src/wx/gl_view.h @@ -18,12 +18,15 @@ */ + +#include "lib/exception_store.h" #include LIBDCP_DISABLE_WARNINGS #include #include LIBDCP_ENABLE_WARNINGS #include +#include /* The OpenGL API in wxWidgets 3.0.x is sufficiently different to make it awkward to support, @@ -35,21 +38,36 @@ LIBDCP_ENABLE_WARNINGS #if wxCHECK_VERSION(3,1,0) -class GLView +class GLView : public ExceptionStore { public: GLView(wxWindow* parent); + virtual ~GLView(); wxWindow* canvas() const { return _canvas; } + bool vsync_enabled() const { + return _vsync_enabled; + } + protected: virtual void size_changed(wxSizeEvent const& ev); + virtual void thread_setup() = 0; + virtual void thread_body() = 0; + + void start_thread_if_required(); wxGLCanvas* _canvas; boost::atomic _canvas_size; wxGLContext* _context; + +private: + void thread(); + + boost::thread _thread; + bool _vsync_enabled; }; diff --git a/src/wx/video_view.h b/src/wx/video_view.h index 3ea03a5fd..707f43f7d 100644 --- a/src/wx/video_view.h +++ b/src/wx/video_view.h @@ -45,7 +45,7 @@ class PlayerVideo; class wxWindow; -class VideoView : public ExceptionStore, public Signaller +class VideoView : public Signaller { public: VideoView (FilmViewer* viewer); @@ -62,6 +62,7 @@ public: virtual void start (); /** Called when playback stops */ virtual void stop () {} + virtual void rethrow() {} enum NextFrameResult { FAIL, -- cgit v1.2.3