File: gl_fence_win_unittest.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (125 lines) | stat: -rw-r--r-- 4,981 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <d3d11_3.h>

#include "media/base/win/d3d11_mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_fence_win.h"

using ::testing::_;
using ::testing::DoAll;
using ::testing::InSequence;
using ::testing::Return;
using ::testing::SetArgPointee;

namespace gl {

class GLFenceWinTest : public ::testing::Test {
 public:
  void SetUp() override {
    // By default, the D3D11 device, context and fence object will allow
    // successful calls to QueryInterface, GetImmediateContext and GetDevice,
    // and return objects of the latest interfaces. Tests may override this
    // behavior to simulate interfaces which are not available.
    ON_CALL(d3d11_device_, QueryInterface(IID_ID3D11Device5, _))
        .WillByDefault(media::SetComPointeeAndReturnOk<1>(&d3d11_device_));
    ON_CALL(d3d11_device_, GetImmediateContext(_))
        .WillByDefault(media::SetComPointee<0>(&d3d11_device_context_));

    ON_CALL(d3d11_device_context_, QueryInterface(IID_ID3D11DeviceContext4, _))
        .WillByDefault(
            media::SetComPointeeAndReturnOk<1>(&d3d11_device_context_));

    ON_CALL(d3d11_fence_, GetDevice(_))
        .WillByDefault(media::SetComPointee<0>(&d3d11_device_));
  }

 protected:
  media::D3D11DeviceMock d3d11_device_;
  media::D3D11DeviceContextMock d3d11_device_context_;
  media::D3D11FenceMock d3d11_fence_;
};

// Ensure graceful failure when ID3D11Device5 is not available.
TEST_F(GLFenceWinTest, CreateForGpuFenceNoDevice5) {
  EXPECT_CALL(d3d11_device_, QueryInterface(IID_ID3D11Device5, _))
      .WillOnce(Return(E_NOINTERFACE));

  std::unique_ptr<GLFenceWin> gl_fence_win =
      GLFenceWin::CreateForGpuFence(&d3d11_device_);
  EXPECT_EQ(gl_fence_win.get(), nullptr);
}

TEST_F(GLFenceWinTest, CreateForGpuFence) {
  // Ensure created fences are made with the D3D11_FENCE_FLAG_SHARED flag so
  // they can be used across processes.
  EXPECT_CALL(d3d11_device_,
              CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_ID3D11Fence, _))
      .WillOnce(media::SetComPointeeAndReturnOk<3>(&d3d11_fence_));

  // GLFenceWin internally uses base::win::ScopedHandle, which calls global
  // functions like CloseHandle to do its job. To avoid mocking ScopedHandle,
  // have D3D11FenceMock use a real, closeable event.
  const HANDLE mock_handle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);

  // Ensure the share handle is created with the correct read+write flags
  // to be shared across processes.
  EXPECT_CALL(d3d11_fence_, CreateSharedHandle(nullptr,
                                               DXGI_SHARED_RESOURCE_READ |
                                                   DXGI_SHARED_RESOURCE_WRITE,
                                               nullptr, _))
      .WillOnce(DoAll(SetArgPointee<3>(mock_handle), Return(S_OK)));

  // Ensure we signal the fence with 1 to match the wait in ServerWait.
  EXPECT_CALL(d3d11_device_context_, Signal(&d3d11_fence_, 1))
      .WillOnce(Return(S_OK));

  std::unique_ptr<GLFenceWin> gl_fence_win =
      GLFenceWin::CreateForGpuFence(&d3d11_device_);
  EXPECT_NE(gl_fence_win.get(), nullptr);

  std::unique_ptr<gfx::GpuFence> gpu_fence = gl_fence_win->GetGpuFence();
  EXPECT_NE(gpu_fence, nullptr);
  EXPECT_FALSE(gpu_fence->GetGpuFenceHandle().is_null());
}

TEST_F(GLFenceWinTest, CreateFromGpuFence) {
  // GLFenceWin internally uses base::win::ScopedHandle, which calls global
  // functions like CloseHandle to do its job. To avoid mocking ScopedHandle,
  // have gfx::GpuFenceHandle use a real, closeable event.
  const HANDLE mock_handle = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);

  gfx::GpuFenceHandle gpu_fence_handle;
  EXPECT_TRUE(gpu_fence_handle.is_null());
  gpu_fence_handle.Adopt(base::win::ScopedHandle(mock_handle));
  EXPECT_FALSE(gpu_fence_handle.is_null());

  gfx::GpuFence gpu_fence(std::move(gpu_fence_handle));
  EXPECT_TRUE(gpu_fence_handle.is_null());

  const gfx::GpuFenceHandle& fence_handle_ref = gpu_fence.GetGpuFenceHandle();
  EXPECT_EQ(fence_handle_ref.Peek(), mock_handle);
  EXPECT_FALSE(fence_handle_ref.is_null());

  // Ensure that CreateFromGpuFence opens the shared handle.
  EXPECT_CALL(d3d11_device_, OpenSharedFence(_, IID_ID3D11Fence, _))
      .WillOnce(media::SetComPointeeAndReturnOk<2>(&d3d11_fence_));

  std::unique_ptr<GLFenceWin> gl_fence_win =
      GLFenceWin::CreateFromGpuFence(&d3d11_device_, gpu_fence);
  EXPECT_NE(gl_fence_win.get(), nullptr);

  std::unique_ptr<gfx::GpuFence> gpu_fence_out = gl_fence_win->GetGpuFence();
  EXPECT_NE(gpu_fence_out, nullptr);
  EXPECT_FALSE(gpu_fence_out->GetGpuFenceHandle().is_null());

  // Verify that Wait is called with 1 to match the Signal in CreateForGpuFence.
  EXPECT_CALL(d3d11_device_context_, Wait(&d3d11_fence_, 1))
      .WillOnce(Return(S_OK));

  gl_fence_win->ServerWait();
}

}  // namespace gl