// 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 "ui/gl/gl_fence_win.h" #include "base/logging.h" #include "base/notreached.h" #include "ui/gl/gl_angle_util_win.h" #include namespace gl { bool GLFenceWin::IsSupported() { Microsoft::WRL::ComPtr d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device) return false; // Support for ID3D11Device5 implies support for ID3D11DeviceContext4. // No point in letting you create fences if you can't signal or wait on them. Microsoft::WRL::ComPtr d3d11_device5; HRESULT hr = d3d11_device.As(&d3d11_device5); if (FAILED(hr)) { return false; } return true; } std::unique_ptr GLFenceWin::CreateForGpuFence() { Microsoft::WRL::ComPtr d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE(); if (!d3d11_device) { DLOG(ERROR) << "Unable to retrieve ID3D11Device from ANGLE"; return nullptr; } return CreateForGpuFence(d3d11_device.Get()); } std::unique_ptr GLFenceWin::CreateForGpuFence( ID3D11Device* d3d11_device) { Microsoft::WRL::ComPtr d3d11_device5; HRESULT hr = d3d11_device->QueryInterface(IID_PPV_ARGS(&d3d11_device5)); if (FAILED(hr)) { DLOG(ERROR) << "Unable to retrieve ID3D11Device5 interface " << logging::SystemErrorCodeToString(hr); return nullptr; } Microsoft::WRL::ComPtr d3d11_fence; hr = d3d11_device5->CreateFence(0, D3D11_FENCE_FLAG_SHARED, IID_PPV_ARGS(&d3d11_fence)); if (FAILED(hr)) { DLOG(ERROR) << "Unable to create ID3D11Fence " << logging::SystemErrorCodeToString(hr); return nullptr; } HANDLE shared_handle; hr = d3d11_fence->CreateSharedHandle( nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr, &shared_handle); if (FAILED(hr)) { DLOG(ERROR) << "Unable to create shared handle for DXGIResource " << logging::SystemErrorCodeToString(hr); return nullptr; } // Put the shared handle into an RAII object as quickly as possible to // ensure we do not leak it. base::win::ScopedHandle scoped_handle(shared_handle); Microsoft::WRL::ComPtr d3d11_device_context; d3d11_device5->GetImmediateContext(&d3d11_device_context); Microsoft::WRL::ComPtr d3d11_device_context4; hr = d3d11_device_context.As(&d3d11_device_context4); if (FAILED(hr)) { DLOG(ERROR) << "Unable to retrieve ID3D11DeviceContext4 interface " << logging::SystemErrorCodeToString(hr); return nullptr; } hr = d3d11_device_context4->Signal(d3d11_fence.Get(), 1); if (FAILED(hr)) { DLOG(ERROR) << "Unable to Signal D3D11 fence " << logging::SystemErrorCodeToString(hr); return nullptr; } gfx::GpuFenceHandle gpu_fence_handle; gpu_fence_handle.owned_handle = std::move(scoped_handle); return std::make_unique(std::move(d3d11_fence), std::move(gpu_fence_handle)); } std::unique_ptr GLFenceWin::CreateFromGpuFence( const gfx::GpuFence& gpu_fence) { Microsoft::WRL::ComPtr d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE(); return CreateFromGpuFence(d3d11_device.Get(), gpu_fence); } std::unique_ptr GLFenceWin::CreateFromGpuFence( ID3D11Device* d3d11_device, const gfx::GpuFence& gpu_fence) { Microsoft::WRL::ComPtr d3d11_device5; HRESULT hr = d3d11_device->QueryInterface(IID_PPV_ARGS(&d3d11_device5)); if (FAILED(hr)) { DLOG(ERROR) << "Unable to retrieve ID3D11Device5 interface " << logging::SystemErrorCodeToString(hr); return nullptr; } gfx::GpuFenceHandle gpu_fence_handle = gpu_fence.GetGpuFenceHandle().Clone(); Microsoft::WRL::ComPtr d3d11_fence; hr = d3d11_device5->OpenSharedFence(gpu_fence_handle.owned_handle.Get(), IID_PPV_ARGS(&d3d11_fence)); if (FAILED(hr)) { DLOG(ERROR) << "Unable to open a shared fence " << logging::SystemErrorCodeToString(hr); return nullptr; } return std::make_unique(std::move(d3d11_fence), std::move(gpu_fence_handle)); } GLFenceWin::GLFenceWin(Microsoft::WRL::ComPtr d3d11_fence, gfx::GpuFenceHandle gpu_fence_handle) : d3d11_fence_(std::move(d3d11_fence)), gpu_fence_handle_(std::move(gpu_fence_handle)) {} GLFenceWin::~GLFenceWin() = default; bool GLFenceWin::HasCompleted() { NOTREACHED(); return false; } void GLFenceWin::ClientWait() { NOTREACHED(); } void GLFenceWin::ServerWait() { Microsoft::WRL::ComPtr d3d11_device; d3d11_fence_->GetDevice(&d3d11_device); Microsoft::WRL::ComPtr d3d11_device_context; d3d11_device->GetImmediateContext(&d3d11_device_context); Microsoft::WRL::ComPtr d3d11_device_context4; HRESULT hr = d3d11_device_context.As(&d3d11_device_context4); if (FAILED(hr)) { DLOG(ERROR) << "Unable to retrieve ID3D11DeviceContext4 interface " << logging::SystemErrorCodeToString(hr); return; } hr = d3d11_device_context4->Wait(d3d11_fence_.Get(), 1); if (FAILED(hr)) { DLOG(ERROR) << "Unable to Wait on D3D11 fence " << logging::SystemErrorCodeToString(hr); return; } } std::unique_ptr GLFenceWin::GetGpuFence() { return std::make_unique(gpu_fence_handle_.Clone()); } TransferableFence GLFenceWin::Transfer() { return TransferableFence(); } } // namespace gl