1 /* 2 * Copyright (C) 2005-2018 Team Kodi 3 * This file is part of Kodi - https://kodi.tv 4 * 5 * SPDX-License-Identifier: GPL-2.0-or-later 6 * See LICENSES/README.md for more information. 7 */ 8 9 #pragma once 10 11 #ifdef HAS_DX 12 #include "guilib/D3DResource.h" 13 #include <wrl/client.h> 14 #endif 15 16 #include "threads/Event.h" 17 18 19 enum ECAPTURESTATE 20 { 21 CAPTURESTATE_WORKING, 22 CAPTURESTATE_NEEDSRENDER, 23 CAPTURESTATE_NEEDSREADOUT, 24 CAPTURESTATE_DONE, 25 CAPTURESTATE_FAILED, 26 CAPTURESTATE_NEEDSDELETE 27 }; 28 29 class CRenderCaptureBase 30 { 31 public: 32 CRenderCaptureBase(); 33 virtual ~CRenderCaptureBase(); 34 35 /* \brief Called by the rendermanager to set the state, should not be called by anything else */ SetState(ECAPTURESTATE state)36 void SetState(ECAPTURESTATE state) { m_state = state; } 37 38 /* \brief Called by the rendermanager to get the state, should not be called by anything else */ GetState()39 ECAPTURESTATE GetState() { return m_state;} 40 41 /* \brief Called by the rendermanager to set the userstate, should not be called by anything else */ SetUserState(ECAPTURESTATE state)42 void SetUserState(ECAPTURESTATE state) { m_userState = state; } 43 44 /* \brief Called by the code requesting the capture 45 \return CAPTURESTATE_WORKING when the capture is in progress, 46 CAPTURESTATE_DONE when the capture has succeeded, 47 CAPTURESTATE_FAILED when the capture has failed 48 */ GetUserState()49 ECAPTURESTATE GetUserState() { return m_userState; } 50 51 /* \brief The internal event will be set when the rendermanager has captured and read a videoframe, or when it has failed 52 \return A reference to m_event 53 */ GetEvent()54 CEvent& GetEvent() { return m_event; } 55 56 /* \brief Called by the rendermanager to set the flags, should not be called by anything else */ SetFlags(int flags)57 void SetFlags(int flags) { m_flags = flags; } 58 59 /* \brief Called by the rendermanager to get the flags, should not be called by anything else */ GetFlags()60 int GetFlags() { return m_flags; } 61 62 /* \brief Called by the rendermanager to set the width, should not be called by anything else */ SetWidth(unsigned int width)63 void SetWidth(unsigned int width) { m_width = width; } 64 65 /* \brief Called by the rendermanager to set the height, should not be called by anything else */ SetHeight(unsigned int height)66 void SetHeight(unsigned int height) { m_height = height; } 67 68 /* \brief Called by the code requesting the capture to get the width */ GetWidth()69 unsigned int GetWidth() { return m_width; } 70 71 /* \brief Called by the code requesting the capture to get the height */ GetHeight()72 unsigned int GetHeight() { return m_height; } 73 74 /* \brief Called by the code requesting the capture to get the buffer where the videoframe is stored, 75 the format is BGRA, this buffer is only valid when GetUserState returns CAPTURESTATE_DONE. 76 The size of the buffer is GetWidth() * GetHeight() * 4. 77 */ GetPixels()78 uint8_t* GetPixels() const { return m_pixels; } 79 80 /* \brief Called by the rendermanager to know if the capture is readout async (using dma for example), 81 should not be called by anything else. 82 */ IsAsync()83 bool IsAsync() { return m_asyncSupported; } 84 85 protected: 86 bool UseOcclusionQuery(); 87 88 ECAPTURESTATE m_state; //state for the rendermanager 89 ECAPTURESTATE m_userState; //state for the thread that wants the capture 90 int m_flags; 91 CEvent m_event; 92 93 uint8_t* m_pixels; 94 unsigned int m_width; 95 unsigned int m_height; 96 unsigned int m_bufferSize; 97 98 //this is set after the first render 99 bool m_asyncSupported; 100 bool m_asyncChecked; 101 }; 102 103 #if defined(HAS_GL) || defined(HAS_GLES) 104 #include "system_gl.h" 105 106 class CRenderCaptureGL : public CRenderCaptureBase 107 { 108 public: 109 CRenderCaptureGL(); 110 ~CRenderCaptureGL() override; 111 112 int GetCaptureFormat(); 113 114 void BeginRender(); 115 void EndRender(); 116 void ReadOut(); 117 118 void* GetRenderBuffer(); 119 120 private: 121 void PboToBuffer(); 122 GLuint m_pbo; 123 GLuint m_query; 124 bool m_occlusionQuerySupported; 125 }; 126 127 //used instead of typedef CRenderCaptureGL CRenderCapture 128 //since C++ doesn't allow you to forward declare a typedef 129 class CRenderCapture : public CRenderCaptureGL 130 { 131 public: 132 CRenderCapture() = default; 133 }; 134 135 #elif HAS_DX /*HAS_GL*/ 136 137 class CRenderCaptureDX : public CRenderCaptureBase, public ID3DResource 138 { 139 public: 140 CRenderCaptureDX(); 141 ~CRenderCaptureDX(); 142 143 int GetCaptureFormat(); 144 145 void BeginRender(); 146 void EndRender(); 147 void ReadOut(); 148 149 void OnDestroyDevice(bool fatal) override; OnCreateDevice()150 void OnCreateDevice() override {}; GetTarget()151 CD3DTexture& GetTarget() { return m_renderTex; } 152 153 private: 154 void SurfaceToBuffer(); 155 void CleanupDX(); 156 157 unsigned int m_surfaceWidth; 158 unsigned int m_surfaceHeight; 159 Microsoft::WRL::ComPtr<ID3D11Query> m_query; 160 CD3DTexture m_renderTex; 161 CD3DTexture m_copyTex; 162 }; 163 164 class CRenderCapture : public CRenderCaptureDX 165 { 166 public: CRenderCapture()167 CRenderCapture() {}; 168 }; 169 170 #endif 171