diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/cores/RetroPlayer/guibridge | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/cores/RetroPlayer/guibridge')
20 files changed, 1493 insertions, 0 deletions
diff --git a/xbmc/cores/RetroPlayer/guibridge/CMakeLists.txt b/xbmc/cores/RetroPlayer/guibridge/CMakeLists.txt new file mode 100644 index 0000000..5ba7579 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/CMakeLists.txt @@ -0,0 +1,24 @@ +set(SOURCES GUIGameMessenger.cpp + GUIGameRenderManager.cpp + GUIGameSettings.cpp + GUIGameSettingsHandle.cpp + GUIGameVideoHandle.cpp + GUIRenderHandle.cpp + GUIRenderTarget.cpp + GUIRenderTargetFactory.cpp +) + +set(HEADERS GUIGameMessenger.h + GUIGameRenderManager.h + GUIGameSettings.h + GUIGameSettingsHandle.h + GUIGameVideoHandle.h + GUIRenderHandle.h + GUIRenderTarget.h + GUIRenderTargetFactory.h + IGameCallback.h + IGUIRenderSettings.h + IRenderCallback.h +) + +core_add_library(retroplayer_guibridge) diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.cpp new file mode 100644 index 0000000..ff7efa3 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIGameMessenger.h" + +#include "FileItem.h" +#include "cores/RetroPlayer/process/RPProcessInfo.h" +#include "cores/RetroPlayer/rendering/RenderContext.h" +#include "cores/RetroPlayer/savestates/SavestateDatabase.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIMessage.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/WindowIDs.h" + +using namespace KODI; +using namespace RETRO; + +CGUIGameMessenger::CGUIGameMessenger(CRPProcessInfo& processInfo) + : m_guiComponent(processInfo.GetRenderContext().GUI()) +{ +} + +void CGUIGameMessenger::RefreshSavestates(const std::string& savestatePath /* = "" */, + ISavestate* savestate /* = nullptr */) +{ + if (m_guiComponent != nullptr) + { + CGUIMessage message(GUI_MSG_REFRESH_THUMBS, 0, WINDOW_DIALOG_IN_GAME_SAVES); + + // Add path, if given + if (!savestatePath.empty()) + message.SetStringParam(savestatePath); + + // Add savestate info, if given + if (savestate != nullptr) + { + CFileItemPtr item = std::make_shared<CFileItem>(); + CSavestateDatabase::GetSavestateItem(*savestate, savestatePath, *item); + message.SetItem(std::static_pointer_cast<CGUIListItem>(item)); + } + + // Notify the in-game savestate dialog + m_guiComponent->GetWindowManager().SendThreadMessage(message, WINDOW_DIALOG_IN_GAME_SAVES); + } +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.h b/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.h new file mode 100644 index 0000000..7384f9a --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameMessenger.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <string> + +class CGUIComponent; + +namespace KODI +{ +namespace RETRO +{ +class CRPProcessInfo; +class ISavestate; + +/*! + * \brief Class to send messages to the GUI, if a GUI is present + */ +class CGUIGameMessenger +{ +public: + CGUIGameMessenger(CRPProcessInfo& processInfo); + + /*! + * \brief Refresh savestate GUI elements being displayed + * + * \param savestatePath The savestate to refresh, or empty to refresh all savestates + * \param savestate Optional savestate info to send with the message + */ + void RefreshSavestates(const std::string& savestatePath = "", ISavestate* savestate = nullptr); + +private: + CGUIComponent* const m_guiComponent; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.cpp new file mode 100644 index 0000000..4071d10 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIGameRenderManager.h" + +#include "GUIGameSettingsHandle.h" +#include "GUIGameVideoHandle.h" +#include "GUIRenderHandle.h" +#include "GUIRenderTarget.h" +#include "GUIRenderTargetFactory.h" +#include "IGameCallback.h" +#include "IRenderCallback.h" + +#include <mutex> + +using namespace KODI; +using namespace RETRO; + +CGUIGameRenderManager::~CGUIGameRenderManager() = default; + +void CGUIGameRenderManager::RegisterPlayer(CGUIRenderTargetFactory* factory, + IRenderCallback* callback, + IGameCallback* gameCallback) +{ + // Set factory + { + std::unique_lock<CCriticalSection> lock(m_targetMutex); + m_factory = factory; + UpdateRenderTargets(); + } + + // Set callback + { + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + m_callback = callback; + } + + // Set game callback + { + std::unique_lock<CCriticalSection> lock(m_gameCallbackMutex); + m_gameCallback = gameCallback; + } +} + +void CGUIGameRenderManager::UnregisterPlayer() +{ + // Reset game callback + { + std::unique_lock<CCriticalSection> lock(m_gameCallbackMutex); + m_gameCallback = nullptr; + } + + // Reset callback + { + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + m_callback = nullptr; + } + + // Reset factory + { + std::unique_lock<CCriticalSection> lock(m_targetMutex); + m_factory = nullptr; + UpdateRenderTargets(); + } +} + +std::shared_ptr<CGUIRenderHandle> CGUIGameRenderManager::RegisterControl(CGUIGameControl& control) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + // Create handle for game control + std::shared_ptr<CGUIRenderHandle> renderHandle(new CGUIRenderControlHandle(*this, control)); + + std::shared_ptr<CGUIRenderTarget> renderTarget; + if (m_factory != nullptr) + renderTarget.reset(m_factory->CreateRenderControl(control)); + + m_renderTargets.insert(std::make_pair(renderHandle.get(), std::move(renderTarget))); + + return renderHandle; +} + +std::shared_ptr<CGUIRenderHandle> CGUIGameRenderManager::RegisterWindow( + CGameWindowFullScreen& window) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + // Create handle for game window + std::shared_ptr<CGUIRenderHandle> renderHandle(new CGUIRenderFullScreenHandle(*this, window)); + + std::shared_ptr<CGUIRenderTarget> renderTarget; + if (m_factory != nullptr) + renderTarget.reset(m_factory->CreateRenderFullScreen(window)); + + m_renderTargets.insert(std::make_pair(renderHandle.get(), std::move(renderTarget))); + + return renderHandle; +} + +std::shared_ptr<CGUIGameVideoHandle> CGUIGameRenderManager::RegisterDialog( + GAME::CDialogGameVideoSelect& dialog) +{ + return std::make_shared<CGUIGameVideoHandle>(*this); +} + +std::shared_ptr<CGUIGameSettingsHandle> CGUIGameRenderManager::RegisterGameSettingsDialog() +{ + return std::make_shared<CGUIGameSettingsHandle>(*this); +} + +void CGUIGameRenderManager::UnregisterHandle(CGUIRenderHandle* handle) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + m_renderTargets.erase(handle); +} + +void CGUIGameRenderManager::Render(CGUIRenderHandle* handle) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + auto it = m_renderTargets.find(handle); + if (it != m_renderTargets.end()) + { + const std::shared_ptr<CGUIRenderTarget>& renderTarget = it->second; + if (renderTarget) + renderTarget->Render(); + } +} + +void CGUIGameRenderManager::RenderEx(CGUIRenderHandle* handle) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + auto it = m_renderTargets.find(handle); + if (it != m_renderTargets.end()) + { + const std::shared_ptr<CGUIRenderTarget>& renderTarget = it->second; + if (renderTarget) + renderTarget->RenderEx(); + } +} + +void CGUIGameRenderManager::ClearBackground(CGUIRenderHandle* handle) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + auto it = m_renderTargets.find(handle); + if (it != m_renderTargets.end()) + { + const std::shared_ptr<CGUIRenderTarget>& renderTarget = it->second; + if (renderTarget) + renderTarget->ClearBackground(); + } +} + +bool CGUIGameRenderManager::IsDirty(CGUIRenderHandle* handle) +{ + std::unique_lock<CCriticalSection> lock(m_targetMutex); + + auto it = m_renderTargets.find(handle); + if (it != m_renderTargets.end()) + { + const std::shared_ptr<CGUIRenderTarget>& renderTarget = it->second; + if (renderTarget) + return renderTarget->IsDirty(); + } + + return false; +} + +bool CGUIGameRenderManager::IsPlayingGame() +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + return m_callback != nullptr; +} + +bool CGUIGameRenderManager::SupportsRenderFeature(RENDERFEATURE feature) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_callback != nullptr) + return m_callback->SupportsRenderFeature(feature); + + return false; +} + +bool CGUIGameRenderManager::SupportsScalingMethod(SCALINGMETHOD method) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_callback != nullptr) + return m_callback->SupportsScalingMethod(method); + + return false; +} + +std::string CGUIGameRenderManager::GameClientID() +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + return m_gameCallback->GameClientID(); + + return ""; +} + +std::string CGUIGameRenderManager::GetPlayingGame() +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + return m_gameCallback->GetPlayingGame(); + + return ""; +} + +std::string CGUIGameRenderManager::CreateSavestate(bool autosave) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + return m_gameCallback->CreateSavestate(autosave); + + return ""; +} + +bool CGUIGameRenderManager::UpdateSavestate(const std::string& savestatePath) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + return m_gameCallback->UpdateSavestate(savestatePath); + + return false; +} + +bool CGUIGameRenderManager::LoadSavestate(const std::string& savestatePath) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + return m_gameCallback->LoadSavestate(savestatePath); + + return false; +} + +void CGUIGameRenderManager::FreeSavestateResources(const std::string& savestatePath) +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + m_gameCallback->FreeSavestateResources(savestatePath); +} + +void CGUIGameRenderManager::CloseOSD() +{ + std::unique_lock<CCriticalSection> lock(m_callbackMutex); + + if (m_gameCallback != nullptr) + m_gameCallback->CloseOSDCallback(); +} + +void CGUIGameRenderManager::UpdateRenderTargets() +{ + if (m_factory != nullptr) + { + for (auto& it : m_renderTargets) + { + CGUIRenderHandle* handle = it.first; + std::shared_ptr<CGUIRenderTarget>& renderTarget = it.second; + + if (!renderTarget) + renderTarget.reset(CreateRenderTarget(handle)); + } + } + else + { + for (auto& it : m_renderTargets) + it.second.reset(); + } +} + +CGUIRenderTarget* CGUIGameRenderManager::CreateRenderTarget(CGUIRenderHandle* handle) +{ + switch (handle->Type()) + { + case RENDER_HANDLE::CONTROL: + { + CGUIRenderControlHandle* controlHandle = static_cast<CGUIRenderControlHandle*>(handle); + return m_factory->CreateRenderControl(controlHandle->GetControl()); + } + case RENDER_HANDLE::WINDOW: + { + CGUIRenderFullScreenHandle* fullScreenHandle = + static_cast<CGUIRenderFullScreenHandle*>(handle); + return m_factory->CreateRenderFullScreen(fullScreenHandle->GetWindow()); + } + default: + break; + } + + return nullptr; +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.h b/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.h new file mode 100644 index 0000000..0a974b7 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameRenderManager.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/GameSettings.h" +#include "threads/CriticalSection.h" + +#include <map> +#include <memory> + +namespace KODI +{ +namespace GAME +{ +class CDialogGameAdvancedSettings; +class CDialogGameVideoSelect; +} // namespace GAME + +namespace RETRO +{ +class CGameWindowFullScreen; +class CGUIGameControl; +class CGUIGameSettingsHandle; +class CGUIGameVideoHandle; +class CGUIRenderTargetFactory; +class CGUIRenderHandle; +class CGUIRenderTarget; +class IGameCallback; +class IRenderCallback; +class IPlayback; + +/*! + * \brief Class to safely route commands between the GUI and RetroPlayer + * + * This class is brought up before the GUI and player core factory. It + * provides the GUI with safe access to a registered player. + * + * Access to the player is done through handles. When a handle is no + * longer needed, it should be destroyed. + * + * Three kinds of handles are provided: + * + * - CGUIRenderHandle + * Allows the holder to invoke render events + * + * - CGUIGameVideoHandle + * Allows the holder to query video properties, such as the filter + * or view mode. + * + * - CGUIGameSettingsHandle + * Allows the holder to query game properties, such as the ID of the + * game client or the game's filename. + * + * Each manager fulfills the following design requirements: + * + * 1. No assumption of player lifetimes + * + * 2. No assumption of GUI element lifetimes, as long as handles are + * destroyed before this class is destructed + * + * 3. No limit on the number of handles + */ +class CGUIGameRenderManager +{ + // Classes that call into the protected interface + friend class CGUIGameSettingsHandle; + friend class CGUIGameVideoHandle; + friend class CGUIRenderHandle; + +public: + CGUIGameRenderManager() = default; + ~CGUIGameRenderManager(); + + /*! + * \brief Register a RetroPlayer instance + * + * \param factory The interface for creating render targets exposed to the GUI + * \param callback The interface for querying video properties + * \param gameCallback The interface for querying game properties + */ + void RegisterPlayer(CGUIRenderTargetFactory* factory, + IRenderCallback* callback, + IGameCallback* gameCallback); + + /*! + * \brief Unregister a RetroPlayer instance + */ + void UnregisterPlayer(); + + /*! + * \brief Register a GUI game control ("gamewindow" skin control) + * + * \param control The game control + * + * \return A handle to invoke render events + */ + std::shared_ptr<CGUIRenderHandle> RegisterControl(CGUIGameControl& control); + + /*! + * \brief Register a fullscreen game window ("FullscreenGame" window) + * + * \param window The game window + * + * \return A handle to invoke render events + */ + std::shared_ptr<CGUIRenderHandle> RegisterWindow(CGameWindowFullScreen& window); + + /*! + * \brief Register a video select dialog (for selecting video filters, + * view modes, etc.) + * + * \param dialog The video select dialog + * + * \return A handle to query game and video properties + */ + std::shared_ptr<CGUIGameVideoHandle> RegisterDialog(GAME::CDialogGameVideoSelect& dialog); + + /*! + * \brief Register a game settings dialog + * + * \return A handle to query game properties + */ + std::shared_ptr<CGUIGameSettingsHandle> RegisterGameSettingsDialog(); + +protected: + // Functions exposed to friend class CGUIRenderHandle + void UnregisterHandle(CGUIRenderHandle* handle); + void Render(CGUIRenderHandle* handle); + void RenderEx(CGUIRenderHandle* handle); + void ClearBackground(CGUIRenderHandle* handle); + bool IsDirty(CGUIRenderHandle* handle); + + // Functions exposed to friend class CGUIGameVideoHandle + void UnregisterHandle(CGUIGameVideoHandle* handle) {} + bool IsPlayingGame(); + bool SupportsRenderFeature(RENDERFEATURE feature); + bool SupportsScalingMethod(SCALINGMETHOD method); + + // Functions exposed to CGUIGameSettingsHandle + void UnregisterHandle(CGUIGameSettingsHandle* handle) {} + std::string GameClientID(); + std::string GetPlayingGame(); + std::string CreateSavestate(bool autosave); + bool UpdateSavestate(const std::string& savestatePath); + bool LoadSavestate(const std::string& savestatePath); + void FreeSavestateResources(const std::string& savestatePath); + void CloseOSD(); + +private: + /*! + * \brief Helper function to create or destroy render targets when a + * factory is registered/unregistered + */ + void UpdateRenderTargets(); + + /*! + * \brief Helper function to create a render target + * + * \param handle The handle given to the registered GUI element + * + * \return A target to receive rendering commands + */ + CGUIRenderTarget* CreateRenderTarget(CGUIRenderHandle* handle); + + // Render events + CGUIRenderTargetFactory* m_factory = nullptr; + std::map<CGUIRenderHandle*, std::shared_ptr<CGUIRenderTarget>> m_renderTargets; + CCriticalSection m_targetMutex; + + // Video properties + IRenderCallback* m_callback = nullptr; + CCriticalSection m_callbackMutex; + + // Game properties + IGameCallback* m_gameCallback = nullptr; + CCriticalSection m_gameCallbackMutex; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.cpp new file mode 100644 index 0000000..4b030d8 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIGameSettings.h" + +#include "cores/RetroPlayer/process/RPProcessInfo.h" +#include "cores/RetroPlayer/rendering/RenderContext.h" +#include "settings/GameSettings.h" + +#include <mutex> + +using namespace KODI; +using namespace RETRO; + +CGUIGameSettings::CGUIGameSettings(CRPProcessInfo& processInfo) + : m_processInfo(processInfo), m_guiSettings(processInfo.GetRenderContext().GetGameSettings()) +{ + // Reset game settings + m_guiSettings = m_processInfo.GetRenderContext().GetDefaultGameSettings(); + + UpdateSettings(); + + m_guiSettings.RegisterObserver(this); +} + +CGUIGameSettings::~CGUIGameSettings() +{ + m_guiSettings.UnregisterObserver(this); +} + +CRenderSettings CGUIGameSettings::GetSettings() const +{ + std::unique_lock<CCriticalSection> lock(m_mutex); + + return m_renderSettings; +} + +void CGUIGameSettings::Notify(const Observable& obs, const ObservableMessage msg) +{ + switch (msg) + { + case ObservableMessageSettingsChanged: + { + UpdateSettings(); + break; + } + default: + break; + } +} + +void CGUIGameSettings::UpdateSettings() +{ + std::unique_lock<CCriticalSection> lock(m_mutex); + + // Get settings from GUI + std::string videoFilter = m_guiSettings.VideoFilter(); + STRETCHMODE stretchMode = m_guiSettings.StretchMode(); + unsigned int rotationDegCCW = m_guiSettings.RotationDegCCW(); + + // Save settings for renderer + m_renderSettings.VideoSettings().SetVideoFilter(videoFilter); + m_renderSettings.VideoSettings().SetRenderStretchMode(stretchMode); + m_renderSettings.VideoSettings().SetRenderRotation(rotationDegCCW); +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.h b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.h new file mode 100644 index 0000000..6400b8d --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettings.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "IGUIRenderSettings.h" +#include "cores/RetroPlayer/rendering/RenderSettings.h" +#include "threads/CriticalSection.h" +#include "utils/Observer.h" + +#include <memory> + +class CGameSettings; + +namespace KODI +{ +namespace RETRO +{ +class CRPProcessInfo; + +class CGUIGameSettings : public IGUIRenderSettings, public Observer +{ +public: + CGUIGameSettings(CRPProcessInfo& processInfo); + ~CGUIGameSettings() override; + + // implementation of IGUIRenderSettings + CRenderSettings GetSettings() const override; + + // implementation of Observer + void Notify(const Observable& obs, const ObservableMessage msg) override; + +private: + void UpdateSettings(); + + // Construction parameters + CRPProcessInfo& m_processInfo; + + // GUI parameters + CGameSettings& m_guiSettings; + + // Render parameters + CRenderSettings m_renderSettings; + + // Synchronization parameters + mutable CCriticalSection m_mutex; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.cpp new file mode 100644 index 0000000..9edba41 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIGameSettingsHandle.h" + +#include "GUIGameRenderManager.h" + +using namespace KODI; +using namespace RETRO; + +CGUIGameSettingsHandle::CGUIGameSettingsHandle(CGUIGameRenderManager& renderManager) + : m_renderManager(renderManager) +{ +} + +CGUIGameSettingsHandle::~CGUIGameSettingsHandle() +{ + m_renderManager.UnregisterHandle(this); +} + +std::string CGUIGameSettingsHandle::GameClientID() +{ + return m_renderManager.GameClientID(); +} + +std::string CGUIGameSettingsHandle::GetPlayingGame() +{ + return m_renderManager.GetPlayingGame(); +} + +std::string CGUIGameSettingsHandle::CreateSavestate(bool autosave) +{ + return m_renderManager.CreateSavestate(autosave); +} + +bool CGUIGameSettingsHandle::UpdateSavestate(const std::string& savestatePath) +{ + return m_renderManager.UpdateSavestate(savestatePath); +} + +bool CGUIGameSettingsHandle::LoadSavestate(const std::string& savestatePath) +{ + return m_renderManager.LoadSavestate(savestatePath); +} + +void CGUIGameSettingsHandle::FreeSavestateResources(const std::string& savestatePath) +{ + return m_renderManager.FreeSavestateResources(savestatePath); +} + +void CGUIGameSettingsHandle::CloseOSD() +{ + m_renderManager.CloseOSD(); +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.h b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.h new file mode 100644 index 0000000..beddb90 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameSettingsHandle.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <string> + +namespace KODI +{ +namespace RETRO +{ +class CGUIGameRenderManager; +class IPlayback; + +class CGUIGameSettingsHandle +{ +public: + CGUIGameSettingsHandle(CGUIGameRenderManager& renderManager); + virtual ~CGUIGameSettingsHandle(); + + /*! + * \brief Get the ID of the active game client + * + * \return The ID of the active game client, or empty string if a game is + * not playing + */ + std::string GameClientID(); + + /*! + * \brief Get the full path of the game being played + * + * \return The game's path, or empty string if a game is not playing + */ + std::string GetPlayingGame(); + + /*! + * \brief Create a savestate of the current game being played + * + * \param autosave True if the save was invoked automatically, or false if + * the save was invoked by a player + * + * \return The path to the created savestate file, or empty string on + * failure or if a game is not playing + */ + std::string CreateSavestate(bool autosave); + + /*! + * \brief Update a savestate for the current game being played + * + * \param savestatePath The path to the created savestate file returned by + * CreateSavestate() + * + * \return True if the savestate was updated successfully, false otherwise + */ + bool UpdateSavestate(const std::string& savestatePath); + + /*! + * \brief Load a savestate for the current game being played + * + * \param savestatePath The path to the created savestate file returned by + * CreateSavestate() + * + * \return True if the savestate was loaded successfully, false otherwise + */ + bool LoadSavestate(const std::string& savestatePath); + + /*! + * \brief Clear the video frame stored for the given statestate + * + * Useful to reclaim memory if a savestate has been deleted. + * + * \param savestatePath The path to the savestate file + */ + void FreeSavestateResources(const std::string& savestatePath); + + /*! + * \brief Close the in-game OSD + */ + void CloseOSD(); + +private: + // Construction parameters + CGUIGameRenderManager& m_renderManager; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.cpp new file mode 100644 index 0000000..521cf4b --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIGameVideoHandle.h" + +#include "GUIGameRenderManager.h" + +using namespace KODI; +using namespace RETRO; + +CGUIGameVideoHandle::CGUIGameVideoHandle(CGUIGameRenderManager& renderManager) + : m_renderManager(renderManager) +{ +} + +CGUIGameVideoHandle::~CGUIGameVideoHandle() +{ + m_renderManager.UnregisterHandle(this); +} + +bool CGUIGameVideoHandle::IsPlayingGame() +{ + return m_renderManager.IsPlayingGame(); +} + +bool CGUIGameVideoHandle::SupportsRenderFeature(RENDERFEATURE feature) +{ + return m_renderManager.SupportsRenderFeature(feature); +} + +bool CGUIGameVideoHandle::SupportsScalingMethod(SCALINGMETHOD method) +{ + return m_renderManager.SupportsScalingMethod(method); +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.h b/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.h new file mode 100644 index 0000000..4d26fe4 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIGameVideoHandle.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/GameSettings.h" + +namespace KODI +{ +namespace RETRO +{ +class CGUIGameRenderManager; + +class CGUIGameVideoHandle +{ +public: + CGUIGameVideoHandle(CGUIGameRenderManager& renderManager); + virtual ~CGUIGameVideoHandle(); + + bool IsPlayingGame(); + bool SupportsRenderFeature(RENDERFEATURE feature); + bool SupportsScalingMethod(SCALINGMETHOD method); + +private: + // Construction parameters + CGUIGameRenderManager& m_renderManager; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.cpp new file mode 100644 index 0000000..a4b6403 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIRenderHandle.h" + +#include "GUIGameRenderManager.h" + +using namespace KODI; +using namespace RETRO; + +// --- CGUIRenderHandle -------------------------------------------------------- + +CGUIRenderHandle::CGUIRenderHandle(CGUIGameRenderManager& renderManager, RENDER_HANDLE type) + : m_renderManager(renderManager), m_type(type) +{ +} + +CGUIRenderHandle::~CGUIRenderHandle() +{ + m_renderManager.UnregisterHandle(this); +} + +void CGUIRenderHandle::Render() +{ + m_renderManager.Render(this); +} + +void CGUIRenderHandle::RenderEx() +{ + m_renderManager.RenderEx(this); +} + +bool CGUIRenderHandle::IsDirty() +{ + return m_renderManager.IsDirty(this); +} + +void CGUIRenderHandle::ClearBackground() +{ + m_renderManager.ClearBackground(this); +} + +// --- CGUIRenderControlHandle ------------------------------------------------- + +CGUIRenderControlHandle::CGUIRenderControlHandle(CGUIGameRenderManager& renderManager, + CGUIGameControl& control) + : CGUIRenderHandle(renderManager, RENDER_HANDLE::CONTROL), m_control(control) +{ +} + +// --- CGUIRenderFullScreenHandle ---------------------------------------------- + +CGUIRenderFullScreenHandle::CGUIRenderFullScreenHandle(CGUIGameRenderManager& renderManager, + CGameWindowFullScreen& window) + : CGUIRenderHandle(renderManager, RENDER_HANDLE::WINDOW), m_window(window) +{ +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.h b/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.h new file mode 100644 index 0000000..f5b8d5b --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderHandle.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +namespace KODI +{ +namespace RETRO +{ +class CGameWindowFullScreen; +class CGUIGameControl; +class CGUIGameRenderManager; + +enum class RENDER_HANDLE +{ + CONTROL, + WINDOW, +}; + +// --- CGUIRenderHandle ------------------------------------------------------ + +class CGUIRenderHandle +{ +public: + CGUIRenderHandle(CGUIGameRenderManager& renderManager, RENDER_HANDLE type); + virtual ~CGUIRenderHandle(); + + RENDER_HANDLE Type() const { return m_type; } + + void Render(); + void RenderEx(); + bool IsDirty(); + void ClearBackground(); + +private: + // Construction parameters + CGUIGameRenderManager& m_renderManager; + const RENDER_HANDLE m_type; +}; + +// --- CGUIRenderControlHandle ----------------------------------------------- + +class CGUIRenderControlHandle : public CGUIRenderHandle +{ +public: + CGUIRenderControlHandle(CGUIGameRenderManager& renderManager, CGUIGameControl& control); + ~CGUIRenderControlHandle() override = default; + + CGUIGameControl& GetControl() { return m_control; } + +private: + // Construction parameters + CGUIGameControl& m_control; +}; + +// --- CGUIRenderFullScreenHandle -------------------------------------------- + +class CGUIRenderFullScreenHandle : public CGUIRenderHandle +{ +public: + CGUIRenderFullScreenHandle(CGUIGameRenderManager& renderManager, CGameWindowFullScreen& window); + ~CGUIRenderFullScreenHandle() override = default; + + CGameWindowFullScreen& GetWindow() { return m_window; } + +private: + // Construction parameters + CGameWindowFullScreen& m_window; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.cpp new file mode 100644 index 0000000..15993fc --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIRenderTarget.h" + +#include "cores/RetroPlayer/guicontrols/GUIGameControl.h" +#include "cores/RetroPlayer/guiwindows/GameWindowFullScreen.h" +#include "cores/RetroPlayer/rendering/IRenderManager.h" + +using namespace KODI; +using namespace RETRO; + +// --- CGUIRenderTarget -------------------------------------------------------- + +CGUIRenderTarget::CGUIRenderTarget(IRenderManager* renderManager) : m_renderManager(renderManager) +{ +} + +// --- CGUIRenderControl ------------------------------------------------------- + +CGUIRenderControl::CGUIRenderControl(IRenderManager* renderManager, CGUIGameControl& gameControl) + : CGUIRenderTarget(renderManager), m_gameControl(gameControl) +{ +} + +void CGUIRenderControl::Render() +{ + m_renderManager->RenderControl(true, true, m_gameControl.GetRenderRegion(), + m_gameControl.GetRenderSettings()); +} + +void CGUIRenderControl::RenderEx() +{ + //! @todo + // m_renderManager->RenderControl(false, false, m_gameControl.GetRenderRegion(), + // m_gameControl.GetRenderSettings()); +} + +// --- CGUIRenderFullScreen ---------------------------------------------------- + +CGUIRenderFullScreen::CGUIRenderFullScreen(IRenderManager* renderManager, + CGameWindowFullScreen& window) + : CGUIRenderTarget(renderManager), m_window(window) +{ +} + +void CGUIRenderFullScreen::Render() +{ + m_renderManager->RenderWindow(true, m_window.GetCoordsRes()); +} + +void CGUIRenderFullScreen::RenderEx() +{ + //! @todo + // m_renderManager->RenderWindow(false, m_window.GetCoordsRes()); +} + +void CGUIRenderFullScreen::ClearBackground() +{ + m_renderManager->ClearBackground(); +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.h b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.h new file mode 100644 index 0000000..574a13f --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTarget.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +namespace KODI +{ +namespace RETRO +{ +class CGameWindowFullScreen; +class CGUIGameControl; +class IRenderManager; + +// --- CGUIRenderTarget ------------------------------------------------------ + +/*! + * \brief A target of rendering commands + * + * This class abstracts the destination of rendering commands. As a result, + * controls and windows are given a unified API. + */ +class CGUIRenderTarget +{ +public: + CGUIRenderTarget(IRenderManager* renderManager); + + virtual ~CGUIRenderTarget() = default; + + /*! + * \brief Draw the frame to the rendering area + */ + virtual void Render() = 0; + + /*! + * \brief Draw the frame to the rendering area differently somehow + */ + virtual void RenderEx() = 0; + + /*! + * \brief Clear the background of the rendering area + */ + virtual void ClearBackground() {} //! @todo + + /*! + * \brief Check of the rendering area is dirty + */ + virtual bool IsDirty() { return true; } //! @todo + +protected: + // Construction parameters + IRenderManager* const m_renderManager; +}; + +// --- CGUIRenderControl ----------------------------------------------------- + +class CGUIRenderControl : public CGUIRenderTarget +{ +public: + CGUIRenderControl(IRenderManager* renderManager, CGUIGameControl& gameControl); + ~CGUIRenderControl() override = default; + + // implementation of CGUIRenderTarget + void Render() override; + void RenderEx() override; + +private: + // Construction parameters + CGUIGameControl& m_gameControl; +}; + +// --- CGUIRenderFullScreen -------------------------------------------------- + +class CGUIRenderFullScreen : public CGUIRenderTarget +{ +public: + CGUIRenderFullScreen(IRenderManager* renderManager, CGameWindowFullScreen& window); + ~CGUIRenderFullScreen() override = default; + + // implementation of CGUIRenderTarget + void Render() override; + void RenderEx() override; + void ClearBackground() override; + +private: + // Construction parameters + CGameWindowFullScreen& m_window; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.cpp b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.cpp new file mode 100644 index 0000000..05675c3 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIRenderTargetFactory.h" + +#include "GUIRenderTarget.h" + +using namespace KODI; +using namespace RETRO; + +CGUIRenderTargetFactory::CGUIRenderTargetFactory(IRenderManager* renderManager) + : m_renderManager(renderManager) +{ +} + +CGUIRenderTarget* CGUIRenderTargetFactory::CreateRenderFullScreen(CGameWindowFullScreen& window) +{ + return new CGUIRenderFullScreen(m_renderManager, window); +} + +CGUIRenderTarget* CGUIRenderTargetFactory::CreateRenderControl(CGUIGameControl& gameControl) +{ + return new CGUIRenderControl(m_renderManager, gameControl); +} diff --git a/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.h b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.h new file mode 100644 index 0000000..8066854 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/GUIRenderTargetFactory.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +namespace KODI +{ +namespace RETRO +{ +class CGameWindowFullScreen; +class CGUIGameControl; +class IRenderManager; +class CGUIRenderTarget; + +class CGUIRenderTargetFactory +{ +public: + CGUIRenderTargetFactory(IRenderManager* renderManager); + + /*! + * \brief Create a render target for the fullscreen window + */ + CGUIRenderTarget* CreateRenderFullScreen(CGameWindowFullScreen& window); + + /*! + * \brief Create a render target for a game control + */ + CGUIRenderTarget* CreateRenderControl(CGUIGameControl& gameControl); + +private: + // Construction parameters + IRenderManager* m_renderManager; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/IGUIRenderSettings.h b/xbmc/cores/RetroPlayer/guibridge/IGUIRenderSettings.h new file mode 100644 index 0000000..8fb0fd1 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/IGUIRenderSettings.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/RetroPlayer/rendering/RenderSettings.h" +#include "utils/Geometry.h" + +namespace KODI +{ +namespace RETRO +{ +/*! + * \brief Interface to pass render settings from the GUI to the renderer + */ +class IGUIRenderSettings +{ +public: + virtual ~IGUIRenderSettings() = default; + + /*! + * \brief Returns true if this render target has a video filter set + */ + virtual bool HasVideoFilter() const { return true; } + + /*! + * \brief Returns true if this render target has a stretch mode set + */ + virtual bool HasStretchMode() const { return true; } + + /*! + * \brief Returns true if this render target has a video rotation set + */ + virtual bool HasRotation() const { return true; } + + /*! + * \brief Returns true if this render target has a path to a savestate for + * showing pixel data + */ + virtual bool HasPixels() const { return true; } + + /*! + * \brief Get the settings used to render this target + * + * \return The render settings + */ + virtual CRenderSettings GetSettings() const = 0; + + /*! + * \brief Get the dimensions of this target + * + * Dimensions are ignored for fullscreen windows. + * + * \return The destination dimensions, or unused for fullscreen window + */ + virtual CRect GetDimensions() const { return CRect{}; } +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/IGameCallback.h b/xbmc/cores/RetroPlayer/guibridge/IGameCallback.h new file mode 100644 index 0000000..057dd04 --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/IGameCallback.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include <string> + +namespace KODI +{ +namespace RETRO +{ +class IPlayback; + +class IGameCallback +{ +public: + virtual ~IGameCallback() = default; + + /*! + * \brief Get the game client being used to play the game + * + * \return The game client's ID, or empty if no game is being played + */ + virtual std::string GameClientID() const = 0; + + /*! + * \brief Get the game that is being played + * + * \return The path to the game, or empty if no game is being played + */ + virtual std::string GetPlayingGame() const = 0; + + /*! + * \brief Creates a savestate + * + * \param autosave Whether the save type is auto + * + * \return The path to the created savestate, or empty on error + */ + virtual std::string CreateSavestate(bool autosave) = 0; + + /*! + * \brief Updates a savestate with the current game being played + * + * \param savestatePath The path to the savestate + * + * \return True if the savestate was updated, false on error + */ + virtual bool UpdateSavestate(const std::string& savestatePath) = 0; + + /*! + * \brief Loads a savestate + * + * \param savestatePath The path to the savestate + * + * \return True if the savestate was loaded, false on error + */ + virtual bool LoadSavestate(const std::string& savestatePath) = 0; + + /*! + * \brief Frees resources allocated to the savestate, such as its video thumbnail + * + * \param savestatePath The path to the savestate + */ + virtual void FreeSavestateResources(const std::string& savestatePath) = 0; + + /*! + * \brief Closes the OSD + */ + virtual void CloseOSDCallback() = 0; +}; +} // namespace RETRO +} // namespace KODI diff --git a/xbmc/cores/RetroPlayer/guibridge/IRenderCallback.h b/xbmc/cores/RetroPlayer/guibridge/IRenderCallback.h new file mode 100644 index 0000000..948c6cd --- /dev/null +++ b/xbmc/cores/RetroPlayer/guibridge/IRenderCallback.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "cores/GameSettings.h" + +namespace KODI +{ +namespace RETRO +{ +class IRenderCallback +{ +public: + virtual ~IRenderCallback() = default; + + virtual bool SupportsRenderFeature(RENDERFEATURE feature) const = 0; + virtual bool SupportsScalingMethod(SCALINGMETHOD method) const = 0; +}; +} // namespace RETRO +} // namespace KODI |