1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_ 6 #define MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_ 7 8 #include <d3d11.h> 9 #include <d3d9.h> 10 #include <mfidl.h> 11 #include <wrl/client.h> 12 13 #include <memory> 14 15 #include "media/gpu/windows/d3d11_com_defs.h" 16 #include "media/video/picture.h" 17 #include "third_party/angle/include/EGL/egl.h" 18 #include "third_party/angle/include/EGL/eglext.h" 19 #include "ui/gfx/geometry/rect.h" 20 #include "ui/gl/gl_fence.h" 21 #include "ui/gl/gl_image.h" 22 23 interface IMFSample; 24 25 namespace media { 26 class DXVAVideoDecodeAccelerator; 27 28 // Maintains information about a DXVA picture buffer, i.e. whether it is 29 // available for rendering, the texture information, etc. 30 class DXVAPictureBuffer { 31 public: 32 enum State { UNUSED, BOUND, COPYING, IN_CLIENT, WAITING_TO_REUSE }; 33 static std::unique_ptr<DXVAPictureBuffer> Create( 34 const DXVAVideoDecodeAccelerator& decoder, 35 const PictureBuffer& buffer, 36 EGLConfig egl_config); 37 virtual ~DXVAPictureBuffer(); 38 39 virtual bool ReusePictureBuffer() = 0; 40 virtual void ResetReuseFence(); 41 // Copies the output sample data to the picture buffer provided by the 42 // client. 43 // The dest_surface parameter contains the decoded bits. 44 virtual bool CopyOutputSampleDataToPictureBuffer( 45 DXVAVideoDecodeAccelerator* decoder, 46 IDirect3DSurface9* dest_surface, 47 ID3D11Texture2D* dx11_texture, 48 int input_buffer_id); 49 available()50 bool available() const { return state_ == UNUSED; } state()51 State state() const { return state_; } picture_buffer()52 const PictureBuffer& picture_buffer() const { return picture_buffer_; } 53 id()54 int id() const { return picture_buffer_.id(); } 55 size()56 gfx::Size size() const { return picture_buffer_.size(); } 57 void set_bound(); 58 gl_image()59 scoped_refptr<gl::GLImage> gl_image() { return gl_image_; } 60 visible_rect()61 const gfx::Rect& visible_rect() const { return visible_rect_; } set_visible_rect(const gfx::Rect & visible_rect)62 void set_visible_rect(const gfx::Rect& visible_rect) { 63 visible_rect_ = visible_rect; 64 } 65 color_space()66 const gfx::ColorSpace& color_space() const { return color_space_; } set_color_space(const gfx::ColorSpace & color_space)67 void set_color_space(const gfx::ColorSpace& color_space) { 68 color_space_ = color_space; 69 } 70 71 // Returns true if these could in theory be used as an overlay. May 72 // still be drawn using GL depending on the scene and precise hardware 73 // support. 74 virtual bool AllowOverlay() const = 0; 75 76 // Returns true if BindSampleToTexture should be used. Otherwise 77 // CopyOutputSampleDataToPicture should be used. 78 virtual bool CanBindSamples() const = 0; 79 waiting_to_reuse()80 bool waiting_to_reuse() const { return state_ == WAITING_TO_REUSE; } 81 virtual gl::GLFence* reuse_fence(); 82 83 // Called when the source surface |src_surface| is copied to the destination 84 // |dest_surface| 85 virtual bool CopySurfaceComplete(IDirect3DSurface9* src_surface, 86 IDirect3DSurface9* dest_surface); 87 virtual bool BindSampleToTexture(DXVAVideoDecodeAccelerator* decoder, 88 Microsoft::WRL::ComPtr<IMFSample> sample); 89 90 protected: 91 explicit DXVAPictureBuffer(const PictureBuffer& buffer); 92 93 State state_ = UNUSED; 94 PictureBuffer picture_buffer_; 95 gfx::Rect visible_rect_; 96 gfx::ColorSpace color_space_; 97 scoped_refptr<gl::GLImage> gl_image_; 98 99 DISALLOW_COPY_AND_ASSIGN(DXVAPictureBuffer); 100 }; 101 102 // Copies the video result into an RGBA EGL pbuffer. 103 class PbufferPictureBuffer : public DXVAPictureBuffer { 104 public: 105 explicit PbufferPictureBuffer(const PictureBuffer& buffer); 106 ~PbufferPictureBuffer() override; 107 108 bool Initialize(const DXVAVideoDecodeAccelerator& decoder, 109 EGLConfig egl_config); 110 bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder, 111 bool use_rgb, 112 bool use_fp16); 113 114 bool ReusePictureBuffer() override; 115 void ResetReuseFence() override; 116 bool CopyOutputSampleDataToPictureBuffer(DXVAVideoDecodeAccelerator* decoder, 117 IDirect3DSurface9* dest_surface, 118 ID3D11Texture2D* dx11_texture, 119 int input_buffer_id) override; 120 gl::GLFence* reuse_fence() override; 121 bool CopySurfaceComplete(IDirect3DSurface9* src_surface, 122 IDirect3DSurface9* dest_surface) override; 123 bool AllowOverlay() const override; 124 bool CanBindSamples() const override; 125 126 protected: 127 EGLSurface decoding_surface_; 128 129 std::unique_ptr<gl::GLFence> reuse_fence_; 130 131 HANDLE texture_share_handle_; 132 Microsoft::WRL::ComPtr<IDirect3DTexture9> decoding_texture_; 133 ComD3D11Texture2D dx11_decoding_texture_; 134 135 Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_; 136 Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_; 137 138 // This is the last value that was used to release the keyed mutex. 139 uint64_t keyed_mutex_value_; 140 141 // The following |IDirect3DSurface9| interface pointers are used to hold 142 // references on the surfaces during the course of a StretchRect operation 143 // to copy the source surface to the target. The references are released 144 // when the StretchRect operation i.e. the copy completes. 145 Microsoft::WRL::ComPtr<IDirect3DSurface9> decoder_surface_; 146 Microsoft::WRL::ComPtr<IDirect3DSurface9> target_surface_; 147 148 // This ID3D11Texture2D interface pointer is used to hold a reference to the 149 // decoder texture during the course of a copy operation. This reference is 150 // released when the copy completes. 151 ComD3D11Texture2D decoder_dx11_texture_; 152 153 // Set to true if RGB is supported by the texture. 154 // Defaults to true. 155 bool use_rgb_; 156 }; 157 158 // Shares the decoded texture with ANGLE without copying by using an EGL stream. 159 class EGLStreamPictureBuffer : public DXVAPictureBuffer { 160 public: 161 explicit EGLStreamPictureBuffer(const PictureBuffer& buffer); 162 ~EGLStreamPictureBuffer() override; 163 164 bool Initialize(); 165 bool ReusePictureBuffer() override; 166 bool BindSampleToTexture(DXVAVideoDecodeAccelerator* decoder, 167 Microsoft::WRL::ComPtr<IMFSample> sample) override; 168 bool AllowOverlay() const override; 169 bool CanBindSamples() const override; 170 171 private: 172 EGLStreamKHR stream_; 173 174 Microsoft::WRL::ComPtr<IMFSample> current_d3d_sample_; 175 ComD3D11Texture2D dx11_decoding_texture_; 176 }; 177 178 // Shares the decoded texture with ANGLE without copying by using an EGL stream. 179 class EGLStreamDelayedCopyPictureBuffer : public DXVAPictureBuffer { 180 public: 181 explicit EGLStreamDelayedCopyPictureBuffer(const PictureBuffer& buffer); 182 ~EGLStreamDelayedCopyPictureBuffer() override; 183 184 bool Initialize(const DXVAVideoDecodeAccelerator& decoder); 185 bool ReusePictureBuffer() override; 186 bool BindSampleToTexture(DXVAVideoDecodeAccelerator* decoder, 187 Microsoft::WRL::ComPtr<IMFSample> sample) override; 188 bool AllowOverlay() const override; 189 bool CanBindSamples() const override; 190 191 private: 192 EGLStreamKHR stream_; 193 194 Microsoft::WRL::ComPtr<IMFSample> current_d3d_sample_; 195 ComD3D11Texture2D dx11_decoding_texture_; 196 }; 197 198 // Creates an NV12 texture and copies to it, then shares that with ANGLE. 199 class EGLStreamCopyPictureBuffer : public DXVAPictureBuffer { 200 public: 201 explicit EGLStreamCopyPictureBuffer(const PictureBuffer& buffer); 202 ~EGLStreamCopyPictureBuffer() override; 203 204 bool Initialize(const DXVAVideoDecodeAccelerator& decoder); 205 bool ReusePictureBuffer() override; 206 207 bool CopyOutputSampleDataToPictureBuffer(DXVAVideoDecodeAccelerator* decoder, 208 IDirect3DSurface9* dest_surface, 209 ID3D11Texture2D* dx11_texture, 210 int input_buffer_id) override; 211 bool CopySurfaceComplete(IDirect3DSurface9* src_surface, 212 IDirect3DSurface9* dest_surface) override; 213 bool AllowOverlay() const override; 214 bool CanBindSamples() const override; 215 216 private: 217 EGLStreamKHR stream_; 218 219 // This ID3D11Texture2D interface pointer is used to hold a reference to the 220 // MFT decoder texture during the course of a copy operation. This reference 221 // is released when the copy completes. 222 ComD3D11Texture2D dx11_decoding_texture_; 223 224 Microsoft::WRL::ComPtr<IDXGIKeyedMutex> egl_keyed_mutex_; 225 Microsoft::WRL::ComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_; 226 227 HANDLE texture_share_handle_; 228 // This is the texture (created on ANGLE's device) that will be put in the 229 // EGLStream. 230 ComD3D11Texture2D angle_copy_texture_; 231 // This is another copy of that shared resource that will be copied to from 232 // the decoder. 233 ComD3D11Texture2D decoder_copy_texture_; 234 235 // This is the last value that was used to release the keyed mutex. 236 uint64_t keyed_mutex_value_ = 0; 237 }; 238 239 } // namespace media 240 241 #endif // MEDIA_GPU_WINDOWS_DXVA_PICTURE_BUFFER_WIN_H_ 242