
gfx::GpuFenceHandle and gl::GLFence previously only supported POSIX operating systems. This change adds support for Windows for both classes. Bug: 1131616 Change-Id: Iea3bf9ae52c6c7d22527cdb2f48711dd6981dee7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2466515 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Robert Kroeger <rjkroege@chromium.org> Reviewed-by: Klaus Weidner <klausw@chromium.org> Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com> Cr-Commit-Position: refs/heads/master@{#818665}
126 lines
4.9 KiB
C++
126 lines
4.9 KiB
C++
// Copyright 2020 The Chromium Authors. All rights reserved.
|
|
// 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.owned_handle.Set(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.owned_handle.Get(), 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
|