[WASAPI] set stream audio category
[xbmc.git] / xbmc / cores / RetroPlayer / rendering / RPRenderManager.h
blobbd1ebb59e54f7c0f9f3312a5b1a0c1a0f5e72e1d
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #pragma once
11 #include "IRenderManager.h"
12 #include "RenderVideoSettings.h"
13 #include "cores/RetroPlayer/guibridge/IRenderCallback.h"
14 #include "threads/CriticalSection.h"
16 extern "C"
18 #include <libavutil/pixfmt.h>
21 #include <atomic>
22 #include <future>
23 #include <map>
24 #include <memory>
25 #include <set>
26 #include <string>
27 #include <vector>
29 struct SwsContext;
31 namespace KODI
33 namespace RETRO
35 class CGUIRenderTargetFactory;
36 class CRenderContext;
37 class CRenderSettings;
38 class CRPBaseRenderer;
39 class CRPProcessInfo;
40 class IGUIRenderSettings;
41 class IRenderBuffer;
42 class IRenderBufferPool;
43 class ISavestate;
44 struct VideoStreamBuffer;
46 /*!
47 * \brief Renders video frames provided by the game loop
49 * Generally, buffer pools are registered by the windowing subsystem. A buffer
50 * pool provides a software or hardware buffer to store the added frame. When
51 * RenderManager is created, it instantiates all registered buffer pools.
53 * When a frame arrives, it is copied into a buffer from each buffer pool with
54 * a visible renderer. For example, if a GLES and MMAL renderer are both
55 * visible in the GUI, then the frame will be copied into two buffers.
57 * When it is time to render the frame, the GUI control or window calls into
58 * this class through the IRenderManager interface. RenderManager selects an
59 * appropriate renderer to use to render the frame. The renderer is then
60 * given the buffer that came from its buffer pool.
62 * Special behavior is needed when the game is paused. As no new frames are
63 * delivered, a newly created renderer will stay black. For this scenario,
64 * when we detect a pause event, the frame is preemptively cached so that a
65 * newly created renderer will have something to display.
67 class CRPRenderManager : public IRenderManager, public IRenderCallback
69 public:
70 CRPRenderManager(CRPProcessInfo& processInfo);
71 ~CRPRenderManager() override = default;
73 void Initialize();
74 void Deinitialize();
76 /*!
77 * \brief Access the factory for creating GUI render targets
79 CGUIRenderTargetFactory* GetGUIRenderTargetFactory() { return m_renderControlFactory.get(); }
81 // Stream properties, set upon configuration
82 AVPixelFormat GetPixelFormat() const { return m_format; }
83 unsigned int GetNominalWidth() const { return m_nominalWidth; }
84 unsigned int GetNominalHeight() const { return m_nominalHeight; }
85 unsigned int GetMaxWidth() const { return m_maxWidth; }
86 unsigned int GetMaxHeight() const { return m_maxHeight; }
87 float GetPixelAspectRatio() const { return m_pixelAspectRatio; }
89 // Functions called from game loop
90 bool Configure(AVPixelFormat format,
91 unsigned int nominalWidth,
92 unsigned int nominalHeight,
93 unsigned int maxWidth,
94 unsigned int maxHeight,
95 float pixelAspectRatio);
96 bool GetVideoBuffer(unsigned int width, unsigned int height, VideoStreamBuffer& buffer);
97 void AddFrame(const uint8_t* data,
98 size_t size,
99 unsigned int width,
100 unsigned int height,
101 unsigned int orientationDegCW);
102 void Flush();
104 // Functions called from the player
105 void SetSpeed(double speed);
107 // Functions called from render thread
108 void FrameMove();
110 // Implementation of IRenderManager
111 void RenderWindow(bool bClear, const RESOLUTION_INFO& coordsRes) override;
112 void RenderControl(bool bClear,
113 bool bUseAlpha,
114 const CRect& renderRegion,
115 const IGUIRenderSettings* renderSettings) override;
116 void ClearBackground() override;
118 // Implementation of IRenderCallback
119 bool SupportsRenderFeature(RENDERFEATURE feature) const override;
120 bool SupportsScalingMethod(SCALINGMETHOD method) const override;
122 // Savestate functions
123 void SaveThumbnail(const std::string& thumbnailPath);
125 // Savestate functions
126 void CacheVideoFrame(const std::string& savestatePath);
127 void SaveVideoFrame(const std::string& savestatePath, ISavestate& savestate);
128 void ClearVideoFrame(const std::string& savestatePath);
130 private:
132 * \brief Get or create a renderer compatible with the given render settings
134 std::shared_ptr<CRPBaseRenderer> GetRendererForSettings(const IGUIRenderSettings* renderSettings);
137 * \brief Get or create a renderer for the given buffer pool and render settings
139 std::shared_ptr<CRPBaseRenderer> GetRendererForPool(IRenderBufferPool* bufferPool,
140 const CRenderSettings& renderSettings);
143 * \brief Render a frame using the given renderer
145 void RenderInternal(const std::shared_ptr<CRPBaseRenderer>& renderer,
146 IRenderBuffer* renderBuffer,
147 bool bClear,
148 uint32_t alpha);
151 * \brief Return true if we have a render buffer belonging to the specified pool
153 bool HasRenderBuffer(IRenderBufferPool* bufferPool);
156 * \brief Get a render buffer belonging to the specified pool
158 IRenderBuffer* GetRenderBuffer(IRenderBufferPool* bufferPool);
161 * \brief Get a render buffer containing pixels from the specified savestate
163 IRenderBuffer* GetRenderBufferForSavestate(const std::string& savestatePath,
164 const IRenderBufferPool* bufferPool);
167 * \brief Create a render buffer for the specified pool from a cached frame
169 void CreateRenderBuffer(IRenderBufferPool* bufferPool);
172 * \brief Create a render buffer and copy the cached data into it
174 * The cached frame is accessed by both the game and rendering threads,
175 * and therefore requires synchronization.
177 * However, assuming the memory copy is expensive, we must avoid holding
178 * the mutex during the copy.
180 * To allow for this, the function is permitted to invalidate its
181 * cachedFrame parameter, as long as it is restored upon exit. While the
182 * mutex is exited inside this function, cachedFrame is guaranteed to be
183 * empty.
185 * \param cachedFrame The cached frame
186 * \param width The width of the cached frame
187 * \param height The height of the cached frame
188 * \param bufferPool The buffer pool used to create the render buffer
189 * \param mutex The locked mutex, to be unlocked during memory copy
191 * \return The render buffer if one was created from the cached frame,
192 * otherwise nullptr
194 IRenderBuffer* CreateFromCache(std::vector<uint8_t>& cachedFrame,
195 unsigned int width,
196 unsigned int height,
197 IRenderBufferPool* bufferPool,
198 CCriticalSection& mutex);
201 * \brief Utility function to copy a frame and rescale pixels if necessary
203 void CopyFrame(IRenderBuffer* renderBuffer,
204 AVPixelFormat format,
205 const uint8_t* data,
206 size_t size,
207 unsigned int width,
208 unsigned int height);
210 CRenderVideoSettings GetEffectiveSettings(const IGUIRenderSettings* settings) const;
212 void CheckFlush();
214 void GetVideoFrame(IRenderBuffer*& readableBuffer, std::vector<uint8_t>& cachedFrame);
215 void FreeVideoFrame(IRenderBuffer* readableBuffer, std::vector<uint8_t> cachedFrame);
216 void LoadVideoFrameAsync(const std::string& savestatePath);
217 void LoadVideoFrameSync(const std::string& savestatePath);
219 // Construction parameters
220 CRPProcessInfo& m_processInfo;
221 CRenderContext& m_renderContext;
223 // Subsystems
224 std::shared_ptr<IGUIRenderSettings> m_renderSettings;
225 std::shared_ptr<CGUIRenderTargetFactory> m_renderControlFactory;
227 // Stream properties
228 AVPixelFormat m_format = AV_PIX_FMT_NONE;
229 unsigned int m_nominalWidth{0};
230 unsigned int m_nominalHeight{0};
231 unsigned int m_maxWidth = 0;
232 unsigned int m_maxHeight = 0;
233 float m_pixelAspectRatio{1.0f};
235 // Render resources
236 std::set<std::shared_ptr<CRPBaseRenderer>> m_renderers;
237 std::vector<IRenderBuffer*> m_pendingBuffers; // Only access from game thread
238 std::vector<IRenderBuffer*> m_renderBuffers;
239 std::map<AVPixelFormat, std::map<AVPixelFormat, SwsContext*>> m_scalers; // From -> to -> context
240 std::vector<uint8_t> m_cachedFrame;
241 unsigned int m_cachedWidth = 0;
242 unsigned int m_cachedHeight = 0;
243 unsigned int m_cachedRotationCCW{0};
244 std::map<std::string, std::vector<IRenderBuffer*>>
245 m_savestateBuffers; // Render buffers for savestates
246 std::vector<std::future<void>> m_savestateThreads;
248 // State parameters
249 enum class RENDER_STATE
251 UNCONFIGURED,
252 CONFIGURING,
253 CONFIGURED,
255 RENDER_STATE m_state = RENDER_STATE::UNCONFIGURED;
256 bool m_bHasCachedFrame = false; // Invariant: m_cachedFrame is empty if false
257 std::set<std::string> m_failedShaderPresets;
258 std::atomic<bool> m_bFlush = {false};
260 // Windowing state
261 bool m_bDisplayScaleSet = false;
263 // Playback parameters
264 std::atomic<double> m_speed = {1.0};
266 // Synchronization parameters
267 CCriticalSection m_stateMutex;
268 CCriticalSection m_bufferMutex;
270 } // namespace RETRO
271 } // namespace KODI