| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/dxva_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #if !defined(OS_WIN) | 7 #if !defined(OS_WIN) |
| 8 #error This file should only be built on Windows. | 8 #error This file should only be built on Windows. |
| 9 #endif // !defined(OS_WIN) | 9 #endif // !defined(OS_WIN) |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "base/logging.h" | 26 #include "base/logging.h" |
| 27 #include "base/memory/scoped_ptr.h" | 27 #include "base/memory/scoped_ptr.h" |
| 28 #include "base/memory/shared_memory.h" | 28 #include "base/memory/shared_memory.h" |
| 29 #include "base/message_loop/message_loop.h" | 29 #include "base/message_loop/message_loop.h" |
| 30 #include "base/path_service.h" | 30 #include "base/path_service.h" |
| 31 #include "base/trace_event/trace_event.h" | 31 #include "base/trace_event/trace_event.h" |
| 32 #include "base/win/windows_version.h" | 32 #include "base/win/windows_version.h" |
| 33 #include "content/public/common/content_switches.h" | 33 #include "content/public/common/content_switches.h" |
| 34 #include "media/base/win/mf_initializer.h" | 34 #include "media/base/win/mf_initializer.h" |
| 35 #include "media/video/video_decode_accelerator.h" | 35 #include "media/video/video_decode_accelerator.h" |
| 36 #include "third_party/angle/include/EGL/egl.h" |
| 37 #include "third_party/angle/include/EGL/eglext.h" |
| 36 #include "ui/gl/gl_bindings.h" | 38 #include "ui/gl/gl_bindings.h" |
| 37 #include "ui/gl/gl_context.h" | 39 #include "ui/gl/gl_context.h" |
| 38 #include "ui/gl/gl_surface_egl.h" | 40 #include "ui/gl/gl_surface_egl.h" |
| 39 #include "ui/gl/gl_switches.h" | 41 #include "ui/gl/gl_switches.h" |
| 40 | 42 |
| 41 namespace { | 43 namespace { |
| 42 | 44 |
| 43 // Path is appended on to the PROGRAM_FILES base path. | 45 // Path is appended on to the PROGRAM_FILES base path. |
| 44 const wchar_t kVPXDecoderDLLPath[] = L"Intel\\Media SDK\\"; | 46 const wchar_t kVPXDecoderDLLPath[] = L"Intel\\Media SDK\\"; |
| 45 | 47 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 HRESULT hr = get_class_object( | 271 HRESULT hr = get_class_object( |
| 270 clsid, | 272 clsid, |
| 271 __uuidof(IClassFactory), | 273 __uuidof(IClassFactory), |
| 272 factory.ReceiveVoid()); | 274 factory.ReceiveVoid()); |
| 273 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject failed", hr); | 275 RETURN_ON_HR_FAILURE(hr, "DllGetClassObject failed", hr); |
| 274 | 276 |
| 275 hr = factory->CreateInstance(NULL, iid, object); | 277 hr = factory->CreateInstance(NULL, iid, object); |
| 276 return hr; | 278 return hr; |
| 277 } | 279 } |
| 278 | 280 |
| 281 // Helper function to query the ANGLE device object. The template argument T |
| 282 // identifies the device interface being queried. IDirect3DDevice9Ex for d3d9 |
| 283 // and ID3D11Device for dx11. |
| 284 template<class T> |
| 285 base::win::ScopedComPtr<T> QueryDeviceObjectFromANGLE(int object_type) { |
| 286 base::win::ScopedComPtr<T> device_object; |
| 287 |
| 288 EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay(); |
| 289 intptr_t egl_device = 0; |
| 290 intptr_t device = 0; |
| 291 |
| 292 RETURN_ON_FAILURE( |
| 293 gfx::GLSurfaceEGL::HasEGLExtension("EGL_EXT_device_query"), |
| 294 "EGL_EXT_device_query missing", |
| 295 device_object); |
| 296 |
| 297 PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT = |
| 298 reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(eglGetProcAddress( |
| 299 "eglQueryDisplayAttribEXT")); |
| 300 |
| 301 RETURN_ON_FAILURE( |
| 302 QueryDisplayAttribEXT, |
| 303 "Failed to get the eglQueryDisplayAttribEXT function from ANGLE", |
| 304 device_object); |
| 305 |
| 306 PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT = |
| 307 reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(eglGetProcAddress( |
| 308 "eglQueryDeviceAttribEXT")); |
| 309 |
| 310 RETURN_ON_FAILURE( |
| 311 QueryDeviceAttribEXT, |
| 312 "Failed to get the eglQueryDeviceAttribEXT function from ANGLE", |
| 313 device_object); |
| 314 |
| 315 RETURN_ON_FAILURE( |
| 316 QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device), |
| 317 "The eglQueryDisplayAttribEXT function failed to get the EGL device", |
| 318 device_object); |
| 319 |
| 320 RETURN_ON_FAILURE( |
| 321 egl_device, |
| 322 "Failed to get the EGL device", |
| 323 device_object); |
| 324 |
| 325 RETURN_ON_FAILURE( |
| 326 QueryDeviceAttribEXT( |
| 327 reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device), |
| 328 "The eglQueryDeviceAttribEXT function failed to get the device", |
| 329 device_object); |
| 330 |
| 331 RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object); |
| 332 |
| 333 device_object = reinterpret_cast<T*>(device); |
| 334 return device_object; |
| 335 } |
| 336 |
| 337 |
| 279 // Maintains information about a DXVA picture buffer, i.e. whether it is | 338 // Maintains information about a DXVA picture buffer, i.e. whether it is |
| 280 // available for rendering, the texture information, etc. | 339 // available for rendering, the texture information, etc. |
| 281 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { | 340 struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer { |
| 282 public: | 341 public: |
| 283 static linked_ptr<DXVAPictureBuffer> Create( | 342 static linked_ptr<DXVAPictureBuffer> Create( |
| 284 const DXVAVideoDecodeAccelerator& decoder, | 343 const DXVAVideoDecodeAccelerator& decoder, |
| 285 const media::PictureBuffer& buffer, | 344 const media::PictureBuffer& buffer, |
| 286 EGLConfig egl_config); | 345 EGLConfig egl_config); |
| 287 ~DXVAPictureBuffer(); | 346 ~DXVAPictureBuffer(); |
| 288 | 347 |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 | 713 |
| 655 SetState(kNormal); | 714 SetState(kNormal); |
| 656 | 715 |
| 657 StartDecoderThread(); | 716 StartDecoderThread(); |
| 658 return true; | 717 return true; |
| 659 } | 718 } |
| 660 | 719 |
| 661 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { | 720 bool DXVAVideoDecodeAccelerator::CreateD3DDevManager() { |
| 662 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); | 721 TRACE_EVENT0("gpu", "DXVAVideoDecodeAccelerator_CreateD3DDevManager"); |
| 663 | 722 |
| 664 HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.Receive()); | 723 HRESULT hr = E_FAIL; |
| 724 |
| 725 hr = Direct3DCreate9Ex(D3D_SDK_VERSION, d3d9_.Receive()); |
| 665 RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false); | 726 RETURN_ON_HR_FAILURE(hr, "Direct3DCreate9Ex failed", false); |
| 666 | 727 |
| 667 D3DPRESENT_PARAMETERS present_params = {0}; | 728 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 668 present_params.BackBufferWidth = 1; | 729 switches::kDisableD3D11)) { |
| 669 present_params.BackBufferHeight = 1; | 730 base::win::ScopedComPtr<IDirect3DDevice9> angle_device = |
| 670 present_params.BackBufferFormat = D3DFMT_UNKNOWN; | 731 QueryDeviceObjectFromANGLE<IDirect3DDevice9>(EGL_D3D9_DEVICE_ANGLE); |
| 671 present_params.BackBufferCount = 1; | 732 RETURN_ON_FAILURE( |
| 672 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; | 733 angle_device.get(), |
| 673 present_params.hDeviceWindow = ::GetShellWindow(); | 734 "Failed to query D3D9 device object from ANGLE", |
| 674 present_params.Windowed = TRUE; | 735 false); |
| 675 present_params.Flags = D3DPRESENTFLAG_VIDEO; | |
| 676 present_params.FullScreen_RefreshRateInHz = 0; | |
| 677 present_params.PresentationInterval = 0; | |
| 678 | 736 |
| 679 hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, | 737 hr = d3d9_device_ex_.QueryFrom(angle_device.get()); |
| 680 D3DDEVTYPE_HAL, | 738 RETURN_ON_HR_FAILURE(hr, |
| 681 ::GetShellWindow(), | 739 "QueryInterface for IDirect3DDevice9Ex from angle device failed", |
| 682 D3DCREATE_FPU_PRESERVE | | 740 false); |
| 683 D3DCREATE_SOFTWARE_VERTEXPROCESSING | | 741 } else { |
| 684 D3DCREATE_DISABLE_PSGP_THREADING | | 742 D3DPRESENT_PARAMETERS present_params = {0}; |
| 685 D3DCREATE_MULTITHREADED, | 743 present_params.BackBufferWidth = 1; |
| 686 &present_params, | 744 present_params.BackBufferHeight = 1; |
| 687 NULL, | 745 present_params.BackBufferFormat = D3DFMT_UNKNOWN; |
| 688 d3d9_device_ex_.Receive()); | 746 present_params.BackBufferCount = 1; |
| 689 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false); | 747 present_params.SwapEffect = D3DSWAPEFFECT_DISCARD; |
| 748 present_params.hDeviceWindow = ::GetShellWindow(); |
| 749 present_params.Windowed = TRUE; |
| 750 present_params.Flags = D3DPRESENTFLAG_VIDEO; |
| 751 present_params.FullScreen_RefreshRateInHz = 0; |
| 752 present_params.PresentationInterval = 0; |
| 753 |
| 754 hr = d3d9_->CreateDeviceEx(D3DADAPTER_DEFAULT, |
| 755 D3DDEVTYPE_HAL, |
| 756 ::GetShellWindow(), |
| 757 D3DCREATE_FPU_PRESERVE | |
| 758 D3DCREATE_HARDWARE_VERTEXPROCESSING | |
| 759 D3DCREATE_DISABLE_PSGP_THREADING | |
| 760 D3DCREATE_MULTITHREADED, |
| 761 &present_params, |
| 762 NULL, |
| 763 d3d9_device_ex_.Receive()); |
| 764 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device", false); |
| 765 } |
| 690 | 766 |
| 691 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, | 767 hr = DXVA2CreateDirect3DDeviceManager9(&dev_manager_reset_token_, |
| 692 device_manager_.Receive()); | 768 device_manager_.Receive()); |
| 693 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); | 769 RETURN_ON_HR_FAILURE(hr, "DXVA2CreateDirect3DDeviceManager9 failed", false); |
| 694 | 770 |
| 695 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), | 771 hr = device_manager_->ResetDevice(d3d9_device_ex_.get(), |
| 696 dev_manager_reset_token_); | 772 dev_manager_reset_token_); |
| 697 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); | 773 RETURN_ON_HR_FAILURE(hr, "Failed to reset device", false); |
| 698 | 774 |
| 699 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); | 775 hr = d3d9_device_ex_->CreateQuery(D3DQUERYTYPE_EVENT, query_.Receive()); |
| 700 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); | 776 RETURN_ON_HR_FAILURE(hr, "Failed to create D3D device query", false); |
| 701 // Ensure query_ API works (to avoid an infinite loop later in | 777 // Ensure query_ API works (to avoid an infinite loop later in |
| 702 // CopyOutputSampleDataToPictureBuffer). | 778 // CopyOutputSampleDataToPictureBuffer). |
| 703 hr = query_->Issue(D3DISSUE_END); | 779 hr = query_->Issue(D3DISSUE_END); |
| 704 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); | 780 RETURN_ON_HR_FAILURE(hr, "Failed to issue END test query", false); |
| 705 return true; | 781 return true; |
| 706 } | 782 } |
| 707 | 783 |
| 708 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { | 784 bool DXVAVideoDecodeAccelerator::CreateDX11DevManager() { |
| 709 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, | 785 HRESULT hr = create_dxgi_device_manager_(&dx11_dev_manager_reset_token_, |
| 710 d3d11_device_manager_.Receive()); | 786 d3d11_device_manager_.Receive()); |
| 711 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); | 787 RETURN_ON_HR_FAILURE(hr, "MFCreateDXGIDeviceManager failed", false); |
| 712 | 788 |
| 713 // This array defines the set of DirectX hardware feature levels we support. | 789 base::win::ScopedComPtr<ID3D11Device> angle_device = |
| 714 // The ordering MUST be preserved. All applications are assumed to support | 790 QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE); |
| 715 // 9.1 unless otherwise stated by the application, which is not our case. | 791 RETURN_ON_FAILURE( |
| 716 D3D_FEATURE_LEVEL feature_levels[] = { | 792 angle_device.get(), |
| 717 D3D_FEATURE_LEVEL_11_1, | 793 "Failed to query DX11 device object from ANGLE", |
| 718 D3D_FEATURE_LEVEL_11_0, | 794 false); |
| 719 D3D_FEATURE_LEVEL_10_1, | |
| 720 D3D_FEATURE_LEVEL_10_0, | |
| 721 D3D_FEATURE_LEVEL_9_3, | |
| 722 D3D_FEATURE_LEVEL_9_2, | |
| 723 D3D_FEATURE_LEVEL_9_1 }; | |
| 724 | 795 |
| 725 UINT flags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; | 796 d3d11_device_ = angle_device; |
| 726 | 797 d3d11_device_->GetImmediateContext(d3d11_device_context_.Receive()); |
| 727 #if defined _DEBUG | 798 RETURN_ON_FAILURE( |
| 728 flags |= D3D11_CREATE_DEVICE_DEBUG; | 799 d3d11_device_context_.get(), |
| 729 #endif | 800 "Failed to query DX11 device context from ANGLE device", |
| 730 | 801 false); |
| 731 D3D_FEATURE_LEVEL feature_level_out = D3D_FEATURE_LEVEL_11_0; | |
| 732 hr = D3D11CreateDevice(NULL, | |
| 733 D3D_DRIVER_TYPE_HARDWARE, | |
| 734 NULL, | |
| 735 flags, | |
| 736 feature_levels, | |
| 737 arraysize(feature_levels), | |
| 738 D3D11_SDK_VERSION, | |
| 739 d3d11_device_.Receive(), | |
| 740 &feature_level_out, | |
| 741 d3d11_device_context_.Receive()); | |
| 742 RETURN_ON_HR_FAILURE(hr, "Failed to create DX11 device", false); | |
| 743 | 802 |
| 744 // Enable multithreaded mode on the context. This ensures that accesses to | 803 // Enable multithreaded mode on the context. This ensures that accesses to |
| 745 // context are synchronized across threads. We have multiple threads | 804 // context are synchronized across threads. We have multiple threads |
| 746 // accessing the context, the media foundation decoder threads and the | 805 // accessing the context, the media foundation decoder threads and the |
| 747 // decoder thread via the video format conversion transform. | 806 // decoder thread via the video format conversion transform. |
| 748 base::win::ScopedComPtr<ID3D10Multithread> multi_threaded; | 807 base::win::ScopedComPtr<ID3D10Multithread> multi_threaded; |
| 749 hr = multi_threaded.QueryFrom(d3d11_device_context_.get()); | 808 hr = multi_threaded.QueryFrom(d3d11_device_context_.get()); |
| 750 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); | 809 RETURN_ON_HR_FAILURE(hr, "Failed to query ID3D10Multithread", false); |
| 751 multi_threaded->SetMultithreadProtected(TRUE); | 810 multi_threaded->SetMultithreadProtected(TRUE); |
| 752 | 811 |
| (...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 D3DSURFACE_DESC surface_desc; | 2264 D3DSURFACE_DESC surface_desc; |
| 2206 hr = surface->GetDesc(&surface_desc); | 2265 hr = surface->GetDesc(&surface_desc); |
| 2207 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); | 2266 RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false); |
| 2208 *width = surface_desc.Width; | 2267 *width = surface_desc.Width; |
| 2209 *height = surface_desc.Height; | 2268 *height = surface_desc.Height; |
| 2210 } | 2269 } |
| 2211 return true; | 2270 return true; |
| 2212 } | 2271 } |
| 2213 | 2272 |
| 2214 } // namespace content | 2273 } // namespace content |
| OLD | NEW |