/* GStreamer * Copyright (C) 2024 Seungha Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #pragma once #include "gstd3d12window.h" #include "gstd3d12window-swapchain.h" #include #include #include #include #include #include #include #include #include struct FullscreenState { std::atomic fullscreen_on_alt_enter = { false }; std::atomic requested_fullscreen = { false }; std::atomic applied_fullscreen = { false }; LONG restore_style = 0; WINDOWPLACEMENT restore_placement = { }; }; class SwapChainProxy { public: SwapChainProxy (GstD3D12Window * window, SIZE_T id); ~SwapChainProxy (); void set_window_handles (HWND parent_hwnd, HWND child_hwnd); HWND get_window_handle (); SIZE_T get_id (); bool has_parent (); void on_destroy (); void set_fullscreen_on_alt_enter (bool enable); void toggle_fullscreen (bool enable); void update_render_rect (); void handle_fullscreen_change (bool is_fullscreen); void handle_syskey_down (); void handle_update_render_rect (); void handle_key_event (UINT msg, WPARAM wparam, LPARAM lparam); void handle_mouse_event (UINT msg, WPARAM wparam, LPARAM lparam); void handle_swapchain_created (); GstFlowReturn setup_swapchain (GstD3D12Device * device, DXGI_FORMAT format, const GstVideoInfo * in_info, const GstVideoInfo * out_info, GstStructure * conv_config); GstFlowReturn resize_buffer (); GstFlowReturn set_buffer (GstBuffer * buffer); GstFlowReturn present (); private: std::shared_ptr get_swapchain (); private: GstD3D12Window *window_ = nullptr; SIZE_T id_ = 0; HWND hwnd_ = nullptr; HWND parent_hwnd_ = nullptr; GThread *window_thread_ = nullptr; FullscreenState fstate_; std::shared_ptr swapchain_; std::recursive_mutex lock_; }; class HwndServer { public: HwndServer(const HwndServer &) = delete; HwndServer& operator=(const HwndServer &) = delete; static HwndServer * get_instance() { static HwndServer *inst = nullptr; GST_D3D12_CALL_ONCE_BEGIN { inst = new HwndServer (); } GST_D3D12_CALL_ONCE_END; return inst; } void register_window (GstD3D12Window * window); void unregister_window (GstD3D12Window * window); void unlock_window (GstD3D12Window * window); void unlock_stop_window (GstD3D12Window * window); GstFlowReturn create_child_hwnd (GstD3D12Window * window, HWND parent_hwnd, SIZE_T & proxy_id); void create_child_hwnd_finish (GstD3D12Window * window, HWND parent_hwnd, SIZE_T proxy_id); SIZE_T create_internal_window (GstD3D12Window * window); void release_proxy (GstD3D12Window * window, SIZE_T proxy_id); void forward_parent_message (HWND parent, UINT msg, WPARAM wparam, LPARAM lparam); void on_parent_destroy (HWND parent_hwnd); void on_proxy_destroy (GstD3D12Window * window, SIZE_T proxy_id); std::shared_ptr get_proxy (GstD3D12Window * window, SIZE_T proxy_id); private: enum CreateState { None, Waiting, Opened, Closed, }; struct State { std::mutex create_lock; std::condition_variable create_cond; std::atomic id = { 0 }; bool flushing = false; CreateState create_state = CreateState::None; std::shared_ptr proxy; }; HwndServer () {} ~HwndServer () {} std::recursive_mutex lock_; std::unordered_map> state_; std::unordered_map> parent_hwnd_map_; };