1 // Copyright 2020 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 #include <d3d11.h>
6 #include <mfapi.h>
7 
8 #include "base/win/windows_version.h"
9 #include "media/base/test_helpers.h"
10 #include "media/base/win/mf_helpers.h"
11 #include "media/base/win/mf_initializer.h"
12 
13 namespace media {
14 
15 using Microsoft::WRL::ComPtr;
16 
17 class DXGIDeviceScopedHandleTest : public testing::Test {
18  public:
DXGIDeviceScopedHandleTest()19   DXGIDeviceScopedHandleTest()
20       : test_supported_(base::win::GetVersion() >= base::win::Version::WIN10) {}
21   ~DXGIDeviceScopedHandleTest() override = default;
22 
23  protected:
SetUp()24   void SetUp() override {
25     if (!test_supported_)
26       return;
27 
28     ASSERT_NE(nullptr, session_ = InitializeMediaFoundation());
29 
30     // Get a shared DXGI Device Manager from Media Foundation.
31     ASSERT_HRESULT_SUCCEEDED(
32         MFLockDXGIDeviceManager(&device_reset_token_, &dxgi_device_man_));
33 
34     // |dxgi_device_man_| does not create the device, creates Direct3D device.
35     ComPtr<ID3D11Device> d3d11_device;
36     UINT creation_flags =
37         (D3D11_CREATE_DEVICE_VIDEO_SUPPORT | D3D11_CREATE_DEVICE_BGRA_SUPPORT |
38          D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS);
39     static const D3D_FEATURE_LEVEL feature_levels[] = {
40         D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
41         D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,  D3D_FEATURE_LEVEL_9_2,
42         D3D_FEATURE_LEVEL_9_1};
43     ASSERT_HRESULT_SUCCEEDED(
44         D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, creation_flags,
45                           feature_levels, ARRAYSIZE(feature_levels),
46                           D3D11_SDK_VERSION, &d3d11_device, nullptr, nullptr));
47 
48     ComPtr<ID3D10Multithread> multithreaded_device;
49     ASSERT_HRESULT_SUCCEEDED(d3d11_device.As(&multithreaded_device));
50     multithreaded_device->SetMultithreadProtected(TRUE);
51 
52     // Set Direct3D device to the device manager.
53     ASSERT_HRESULT_SUCCEEDED(
54         dxgi_device_man_->ResetDevice(d3d11_device.Get(), device_reset_token_));
55   }
56 
TearDown()57   void TearDown() override {
58     if (test_supported_) {
59       ASSERT_HRESULT_SUCCEEDED(MFUnlockDXGIDeviceManager());
60     }
61   }
62 
63   MFSessionLifetime session_;
64   Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> dxgi_device_man_ = nullptr;
65   UINT device_reset_token_ = 0;
66   const bool test_supported_;
67 };
68 
TEST_F(DXGIDeviceScopedHandleTest,UseDXGIDeviceScopedHandle)69 TEST_F(DXGIDeviceScopedHandleTest, UseDXGIDeviceScopedHandle) {
70   if (!test_supported_)
71     return;
72 
73   {
74     // Create DXGIDeviceScopedHandle in an inner scope without LockDevice
75     // call.
76     DXGIDeviceScopedHandle device_handle_1(dxgi_device_man_.Get());
77   }
78   {
79     // Create DXGIDeviceScopedHandle in an inner scope with LockDevice call.
80     DXGIDeviceScopedHandle device_handle_2(dxgi_device_man_.Get());
81     ComPtr<ID3D11Device> device2;
82     ASSERT_HRESULT_SUCCEEDED(
83         device_handle_2.LockDevice(IID_PPV_ARGS(&device2)));
84   }
85   // Use the device in an outer scope.
86   DXGIDeviceScopedHandle device_handle_3(dxgi_device_man_.Get());
87   ComPtr<ID3D11Device> device3;
88   ASSERT_HRESULT_SUCCEEDED(device_handle_3.LockDevice(IID_PPV_ARGS(&device3)));
89 }
90 
91 }  // namespace media