Bug 1957001 - Use FenceD3D11 for shnchronization in DXGIYCbCrTextureData r=media-playback-reviewers,gfx-reviewers,alwu,lsalzman

DXGIYCbCrTextureData uses keyed mutex for synchronization. But it is inefficient than FenceD3D11. And it caused the performance problem when DXGIYCbCrTextureData has multiple users like Bug 1956305

Differential Revision: https://phabricator.services.mozilla.com/D243622
This commit is contained in:
sotaro
2025-04-04 05:27:37 +00:00
parent b9e693610c
commit ceeb8ba7b7
35 changed files with 709 additions and 218 deletions

View File

@@ -30,6 +30,7 @@
#include "mozilla/glean/DomMediaPlatformsWmfMetrics.h" #include "mozilla/glean/DomMediaPlatformsWmfMetrics.h"
#include "mozilla/gfx/DeviceManagerDx.h" #include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
@@ -668,10 +669,18 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
return S_OK; return S_OK;
} }
RefPtr<layers::PlanarYCbCrImage> image = RefPtr<layers::PlanarYCbCrImage> image;
new IMFYCbCrImage(buffer, twoDBuffer, mKnowsCompositor, mImageContainer); RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
if (XRE_IsGPUProcess() && layers::FenceD3D11::IsSupported(device)) {
VideoData::SetVideoDataToImage(image, mVideoInfo, b, pictureRegion, false); // Store YCbCr to 3 ID3D11Texture2Ds
image = new IMFYCbCrImage(buffer, twoDBuffer, mKnowsCompositor,
mImageContainer);
VideoData::SetVideoDataToImage(image, mVideoInfo, b, pictureRegion, false);
} else {
// Store YCbCr to shmem
image = mImageContainer->CreatePlanarYCbCrImage();
VideoData::SetVideoDataToImage(image, mVideoInfo, b, pictureRegion, true);
}
RefPtr<VideoData> v = VideoData::CreateFromImage( RefPtr<VideoData> v = VideoData::CreateFromImage(
mVideoInfo.mDisplay, aStreamOffset, pts, duration, image.forget(), false, mVideoInfo.mDisplay, aStreamOffset, pts, duration, image.forget(), false,

View File

@@ -74,6 +74,7 @@
# include "gfxWindowsPlatform.h" # include "gfxWindowsPlatform.h"
# include "mozilla/WindowsVersion.h" # include "mozilla/WindowsVersion.h"
# include "mozilla/gfx/DeviceManagerDx.h" # include "mozilla/gfx/DeviceManagerDx.h"
# include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
# include "mozilla/layers/GpuProcessD3D11TextureMap.h" # include "mozilla/layers/GpuProcessD3D11TextureMap.h"
# include "mozilla/layers/TextureD3D11.h" # include "mozilla/layers/TextureD3D11.h"
# include "mozilla/widget/WinCompositorWindowThread.h" # include "mozilla/widget/WinCompositorWindowThread.h"
@@ -214,6 +215,7 @@ bool GPUParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
#if defined(XP_WIN) #if defined(XP_WIN)
gfxWindowsPlatform::InitMemoryReportersForGPUProcess(); gfxWindowsPlatform::InitMemoryReportersForGPUProcess();
DeviceManagerDx::Init(); DeviceManagerDx::Init();
GpuProcessD3D11FencesHolderMap::Init();
GpuProcessD3D11TextureMap::Init(); GpuProcessD3D11TextureMap::Init();
auto rv = wmf::MediaFoundationInitializer::HasInitialized(); auto rv = wmf::MediaFoundationInitializer::HasInitialized();
if (!rv) { if (!rv) {
@@ -804,6 +806,7 @@ void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
#if defined(XP_WIN) #if defined(XP_WIN)
GpuProcessD3D11TextureMap::Shutdown(); GpuProcessD3D11TextureMap::Shutdown();
GpuProcessD3D11FencesHolderMap::Shutdown();
DeviceManagerDx::Shutdown(); DeviceManagerDx::Shutdown();
#endif #endif
LayerTreeOwnerTracker::Shutdown(); LayerTreeOwnerTracker::Shutdown();

View File

@@ -19,50 +19,6 @@ using namespace mozilla::gfx;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
class AutoCheckLockD3D11Texture final {
public:
explicit AutoCheckLockD3D11Texture(ID3D11Texture2D* aTexture)
: mIsLocked(false) {
aTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mMutex));
if (!mMutex) {
// If D3D11Texture does not have keyed mutex, we think that the
// D3D11Texture could be locked.
mIsLocked = true;
return;
}
// Test to see if the keyed mutex has been released
HRESULT hr = mMutex->AcquireSync(0, 0);
if (hr == S_OK || hr == WAIT_ABANDONED) {
mIsLocked = true;
// According to Microsoft documentation:
// WAIT_ABANDONED - The shared surface and keyed mutex are no longer in a
// consistent state. If AcquireSync returns this value, you should release
// and recreate both the keyed mutex and the shared surface
// So even if we do get WAIT_ABANDONED, the keyed mutex will have to be
// released.
mSyncAcquired = true;
}
}
~AutoCheckLockD3D11Texture() {
if (!mSyncAcquired) {
return;
}
HRESULT hr = mMutex->ReleaseSync(0);
if (FAILED(hr)) {
NS_WARNING("Failed to unlock the texture");
}
}
bool IsLocked() const { return mIsLocked; }
private:
bool mIsLocked;
bool mSyncAcquired = false;
RefPtr<IDXGIKeyedMutex> mMutex;
};
DXGIYCbCrTextureAllocationHelper::DXGIYCbCrTextureAllocationHelper( DXGIYCbCrTextureAllocationHelper::DXGIYCbCrTextureAllocationHelper(
const PlanarYCbCrData& aData, TextureFlags aTextureFlags, const PlanarYCbCrData& aData, TextureFlags aTextureFlags,
ID3D11Device* aDevice) ID3D11Device* aDevice)
@@ -87,8 +43,6 @@ bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
} }
ID3D11Texture2D* textureY = dxgiData->GetD3D11Texture(0); ID3D11Texture2D* textureY = dxgiData->GetD3D11Texture(0);
ID3D11Texture2D* textureCb = dxgiData->GetD3D11Texture(1);
ID3D11Texture2D* textureCr = dxgiData->GetD3D11Texture(2);
RefPtr<ID3D11Device> device; RefPtr<ID3D11Device> device;
textureY->GetDevice(getter_AddRefs(device)); textureY->GetDevice(getter_AddRefs(device));
@@ -96,17 +50,6 @@ bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
return false; return false;
} }
// Test to see if the keyed mutex has been released.
// If D3D11Texture failed to lock, do not recycle the DXGIYCbCrTextureData.
AutoCheckLockD3D11Texture lockY(textureY);
AutoCheckLockD3D11Texture lockCr(textureCr);
AutoCheckLockD3D11Texture lockCb(textureCb);
if (!lockY.IsLocked() || !lockCr.IsLocked() || !lockCb.IsLocked()) {
return false;
}
return true; return true;
} }
@@ -118,26 +61,13 @@ already_AddRefed<TextureClient> DXGIYCbCrTextureAllocationHelper::Allocate(
? DXGI_FORMAT_R8_UNORM ? DXGI_FORMAT_R8_UNORM
: DXGI_FORMAT_R16_UNORM, : DXGI_FORMAT_R16_UNORM,
ySize.width, ySize.height, 1, 1); ySize.width, ySize.height, 1, 1);
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE | // Use FenceD3D11 for synchronization.
D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; newDesc.MiscFlags =
D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED;
RefPtr<ID3D10Multithread> mt;
HRESULT hr = mDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
if (FAILED(hr) || !mt) {
gfxCriticalError() << "Multithread safety interface not supported. " << hr;
return nullptr;
}
if (!mt->GetMultithreadProtected()) {
gfxCriticalError() << "Device used not marked as multithread-safe.";
return nullptr;
}
D3D11MTAutoEnter mtAutoEnter(mt.forget());
RefPtr<ID3D11Texture2D> textureY; RefPtr<ID3D11Texture2D> textureY;
hr = mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY)); HRESULT hr =
mDevice->CreateTexture2D(&newDesc, nullptr, getter_AddRefs(textureY));
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr); NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
newDesc.Width = cbcrSize.width; newDesc.Width = cbcrSize.width;

24
gfx/layers/Fence.cpp Normal file
View File

@@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Fence.h"
namespace mozilla {
namespace layers {
FenceFileHandle::FenceFileHandle(UniqueFileHandle&& aFileHandle)
: mFileHandle(std::move(aFileHandle)) {
MOZ_ASSERT(mFileHandle);
}
FenceFileHandle::~FenceFileHandle() = default;
UniqueFileHandle FenceFileHandle::DuplicateFileHandle() {
return mozilla::DuplicateFileHandle(mFileHandle);
}
} // namespace layers
} // namespace mozilla

48
gfx/layers/Fence.h Normal file
View File

@@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_Fence_H
#define MOZILLA_GFX_Fence_H
#include "mozilla/gfx/FileHandleWrapper.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace layers {
class FenceD3D11;
class FenceFileHandle;
class Fence {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Fence);
virtual FenceD3D11* AsFenceD3D11() { return nullptr; }
virtual FenceFileHandle* AsFenceFileHandle() { return nullptr; }
protected:
virtual ~Fence() = default;
};
class FenceFileHandle final : public Fence {
public:
explicit FenceFileHandle(UniqueFileHandle&& aFileHandle);
FenceFileHandle* AsFenceFileHandle() override { return this; }
UniqueFileHandle DuplicateFileHandle();
protected:
virtual ~FenceFileHandle();
UniqueFileHandle mFileHandle;
};
} // namespace layers
} // namespace mozilla
#endif // MOZILLA_GFX_Fence_H

View File

@@ -12,6 +12,8 @@
#include "mozilla/layers/CompositableClient.h" #include "mozilla/layers/CompositableClient.h"
#include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/D3D11YCbCrImage.h" #include "mozilla/layers/D3D11YCbCrImage.h"
#include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
#include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TextureClient.h"
namespace mozilla { namespace mozilla {
@@ -39,18 +41,6 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
DXGIYCbCrTextureData* aTextureData) { DXGIYCbCrTextureData* aTextureData) {
MOZ_ASSERT(aTextureData); MOZ_ASSERT(aTextureData);
HRESULT hr;
RefPtr<ID3D10Multithread> mt;
hr = aDevice->QueryInterface((ID3D10Multithread**)getter_AddRefs(mt));
if (FAILED(hr)) {
return false;
}
if (!mt->GetMultithreadProtected()) {
return false;
}
if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) { if (!gfx::DeviceManagerDx::Get()->CanInitializeKeyedMutexTextures()) {
return false; return false;
} }
@@ -59,8 +49,6 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1); ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1);
ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2); ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2);
D3D11MTAutoEnter mtAutoEnter(mt.forget());
RefPtr<ID3D11DeviceContext> ctx; RefPtr<ID3D11DeviceContext> ctx;
aDevice->GetImmediateContext(getter_AddRefs(ctx)); aDevice->GetImmediateContext(getter_AddRefs(ctx));
if (!ctx) { if (!ctx) {
@@ -68,35 +56,30 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
return false; return false;
} }
// The documentation here seems to suggest using the immediate mode context D3D11_BOX box;
// on more than one thread is not allowed: box.front = box.top = box.left = 0;
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476891(v=vs.85).aspx box.back = 1;
// The Debug Layer seems to imply it is though. When the ID3D10Multithread box.right = aData.YDataSize().width;
// layer is on. The Enter/Leave of the critical section shouldn't even be box.bottom = aData.YDataSize().height;
// required but were added for extra security. ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride, 0);
{ box.right = aData.CbCrDataSize().width;
AutoLockD3D11Texture lockY(textureY); box.bottom = aData.CbCrDataSize().height;
AutoLockD3D11Texture lockCr(textureCr); ctx->UpdateSubresource(textureCb, 0, &box, aData.mCbChannel,
AutoLockD3D11Texture lockCb(textureCb); aData.mCbCrStride, 0);
D3D11MTAutoEnter mtAutoEnter(mt.forget()); ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel,
aData.mCbCrStride, 0);
D3D11_BOX box; auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
box.front = box.top = box.left = 0; if (!fenceHolderMap) {
box.back = 1; MOZ_ASSERT_UNREACHABLE("unexpected to be called");
box.right = aData.YDataSize().width; return false;
box.bottom = aData.YDataSize().height;
ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride,
0);
box.right = aData.CbCrDataSize().width;
box.bottom = aData.CbCrDataSize().height;
ctx->UpdateSubresource(textureCb, 0, &box, aData.mCbChannel,
aData.mCbCrStride, 0);
ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel,
aData.mCbCrStride, 0);
} }
aTextureData->mWriteFence->IncrementAndSignal();
fenceHolderMap->SetWriteFence(aTextureData->mFencesHolderId,
aTextureData->mWriteFence);
return true; return true;
} }
@@ -106,6 +89,12 @@ TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
return nullptr; return nullptr;
} }
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
if (!fenceHolderMap) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice(); RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
if (!device) { if (!device) {
return nullptr; return nullptr;
@@ -124,6 +113,10 @@ TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
DXGIYCbCrTextureData* data = DXGIYCbCrTextureData* data =
mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData(); mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
if (!fenceHolderMap->WaitAllFencesAndForget(data->mFencesHolderId, device)) {
return nullptr;
}
if (!CopyDataToTexture(mData, device, data)) { if (!CopyDataToTexture(mData, device, data)) {
// Failed to copy data // Failed to copy data
mTextureClient = nullptr; mTextureClient = nullptr;

View File

@@ -86,6 +86,17 @@ GpuProcessTextureId GpuProcessTextureId::GetNext() {
return GpuProcessTextureId{++sCounter}; return GpuProcessTextureId{++sCounter};
} }
/* static */
GpuProcessFencesHolderId GpuProcessFencesHolderId::GetNext() {
if (!XRE_IsGPUProcess()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return GpuProcessFencesHolderId{};
}
static std::atomic<uint64_t> sCounter = 0;
return GpuProcessFencesHolderId{++sCounter};
}
std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection) { std::ostream& operator<<(std::ostream& os, ScrollDirection aDirection) {
switch (aDirection) { switch (aDirection) {
case ScrollDirection::eHorizontal: case ScrollDirection::eHorizontal:

View File

@@ -464,6 +464,36 @@ struct GpuProcessTextureId {
}; };
}; };
// FencesHolderId allocated in GPU process
struct GpuProcessFencesHolderId {
uint64_t mId = 0;
static GpuProcessFencesHolderId GetNext();
bool IsValid() const { return mId != 0; }
// Allow explicit cast to a uint64_t for now
explicit operator uint64_t() const { return mId; }
bool operator==(const GpuProcessFencesHolderId& aOther) const {
return mId == aOther.mId;
}
bool operator!=(const GpuProcessFencesHolderId& aOther) const {
return !(*this == aOther);
}
// Helper struct that allow this class to be used as a key in
// std::unordered_map like so:
// std::unordered_map<GpuProcessQueryId, ValueType,
// GpuProcessQueryId::HashFn> myMap;
struct HashFn {
std::size_t operator()(const GpuProcessFencesHolderId aKey) const {
return std::hash<uint64_t>{}(aKey.mId);
}
};
};
// clang-format off // clang-format off
MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, ( MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, (
eVertical, eVertical,

View File

@@ -223,6 +223,13 @@ DXGITextureHostD3D11* GPUVideoTextureHost::AsDXGITextureHostD3D11() {
return nullptr; return nullptr;
} }
DXGIYCbCrTextureHostD3D11* GPUVideoTextureHost::AsDXGIYCbCrTextureHostD3D11() {
if (EnsureWrappedTextureHost()) {
return mWrappedTextureHost->AsDXGIYCbCrTextureHostD3D11();
}
return nullptr;
}
bool GPUVideoTextureHost::IsWrappingSurfaceTextureHost() { bool GPUVideoTextureHost::IsWrappingSurfaceTextureHost() {
if (EnsureWrappedTextureHost()) { if (EnsureWrappedTextureHost()) {
return EnsureWrappedTextureHost()->IsWrappingSurfaceTextureHost(); return EnsureWrappedTextureHost()->IsWrappingSurfaceTextureHost();

View File

@@ -69,6 +69,8 @@ class GPUVideoTextureHost : public TextureHost {
DXGITextureHostD3D11* AsDXGITextureHostD3D11() override; DXGITextureHostD3D11* AsDXGITextureHostD3D11() override;
DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override;
bool IsWrappingSurfaceTextureHost() override; bool IsWrappingSurfaceTextureHost() override;
TextureHostType GetTextureHostType() override; TextureHostType GetTextureHostType() override;

View File

@@ -63,6 +63,7 @@ class CompositableParentManager;
class ReadLockDescriptor; class ReadLockDescriptor;
class CompositorBridgeParent; class CompositorBridgeParent;
class DXGITextureHostD3D11; class DXGITextureHostD3D11;
class DXGIYCbCrTextureHostD3D11;
class SurfaceDescriptor; class SurfaceDescriptor;
class HostIPCAllocator; class HostIPCAllocator;
class ISurfaceAllocator; class ISurfaceAllocator;
@@ -626,6 +627,10 @@ class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
virtual DXGITextureHostD3D11* AsDXGITextureHostD3D11() { return nullptr; } virtual DXGITextureHostD3D11* AsDXGITextureHostD3D11() { return nullptr; }
virtual DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() {
return nullptr;
}
virtual bool IsWrappingSurfaceTextureHost() { return false; } virtual bool IsWrappingSurfaceTextureHost() { return false; }
// Create the corresponding RenderTextureHost type of this texture, and // Create the corresponding RenderTextureHost type of this texture, and

View File

@@ -9,6 +9,7 @@
#include <d3d11.h> #include <d3d11.h>
#include <d3d11_3.h> #include <d3d11_3.h>
#include <d3d11_4.h> #include <d3d11_4.h>
#include <dxgi1_6.h>
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
@@ -36,7 +37,7 @@ RefPtr<FenceD3D11> FenceD3D11::Create(ID3D11Device* aDevice) {
RefPtr<ID3D11Fence> fenceD3D11; RefPtr<ID3D11Fence> fenceD3D11;
d3d11_5->CreateFence(0, D3D11_FENCE_FLAG_SHARED, d3d11_5->CreateFence(0, D3D11_FENCE_FLAG_SHARED,
IID_PPV_ARGS((ID3D11Fence**)getter_AddRefs(fenceD3D11))); IID_PPV_ARGS((ID3D11Fence**)getter_AddRefs(fenceD3D11)));
if (FAILED(hr)) { if (FAILED(hr) || !fenceD3D11) {
gfxCriticalNoteOnce << "Fence creation failed: " << gfx::hexa(hr); gfxCriticalNoteOnce << "Fence creation failed: " << gfx::hexa(hr);
return nullptr; return nullptr;
} }
@@ -68,13 +69,45 @@ RefPtr<FenceD3D11> FenceD3D11::CreateFromHandle(
/* static */ /* static */
bool FenceD3D11::IsSupported(ID3D11Device* aDevice) { bool FenceD3D11::IsSupported(ID3D11Device* aDevice) {
MOZ_ASSERT(aDevice);
if (!aDevice) {
return false;
}
RefPtr<ID3D11Device5> d3d11_5; RefPtr<ID3D11Device5> d3d11_5;
auto hr = auto hr = aDevice->QueryInterface((ID3D11Device5**)getter_AddRefs(d3d11_5));
aDevice->QueryInterface(__uuidof(ID3D11Device5), getter_AddRefs(d3d11_5));
if (FAILED(hr)) { if (FAILED(hr)) {
return false; return false;
} }
return true;
// Check for IDXGIAdapter4:
RefPtr<IDXGIDevice> dxgiDevice;
aDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(dxgiDevice));
if (FAILED(hr)) {
return false;
}
RefPtr<IDXGIAdapter> dxgiAdapter;
hr = dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
if (FAILED(hr)) {
return false;
}
RefPtr<IDXGIAdapter4> dxgiAdapter4;
dxgiAdapter->QueryInterface((IDXGIAdapter4**)getter_AddRefs(dxgiAdapter4));
if (FAILED(hr)) {
gfxCriticalNoteOnce << "Failed to get IDXGIAdapter4: " << gfx::hexa(hr);
return false;
}
DXGI_ADAPTER_DESC3 adapterDesc;
hr = dxgiAdapter4->GetDesc3(&adapterDesc);
if (FAILED(hr)) {
return false;
}
// The adapter must support monitored fences.
return adapterDesc.Flags & DXGI_ADAPTER_FLAG3_SUPPORT_MONITORED_FENCES;
} }
FenceD3D11::FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle) FenceD3D11::FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle)
@@ -84,6 +117,14 @@ FenceD3D11::FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle)
FenceD3D11::~FenceD3D11() {} FenceD3D11::~FenceD3D11() {}
RefPtr<FenceD3D11> FenceD3D11::CloneFromHandle() {
RefPtr<FenceD3D11> fence = FenceD3D11::CreateFromHandle(mHandle);
if (fence) {
fence->Update(mFenceValue);
}
return fence;
}
gfx::FenceInfo FenceD3D11::GetFenceInfo() const { gfx::FenceInfo FenceD3D11::GetFenceInfo() const {
return gfx::FenceInfo(mHandle, mFenceValue); return gfx::FenceInfo(mHandle, mFenceValue);
} }

View File

@@ -10,13 +10,12 @@
#include <unordered_map> #include <unordered_map>
#include "mozilla/gfx/FileHandleWrapper.h" #include "mozilla/gfx/FileHandleWrapper.h"
#include "nsISupportsImpl.h" #include "mozilla/layers/Fence.h"
struct ID3D11Device; struct ID3D11Device;
struct ID3D11Fence; struct ID3D11Fence;
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
// //
@@ -36,17 +35,20 @@ namespace layers {
// For waiting fence, Update() is used to update the target value of the // For waiting fence, Update() is used to update the target value of the
// waiting. Wait() is then used to wait for the fence. // waiting. Wait() is then used to wait for the fence.
// //
class FenceD3D11 final { class FenceD3D11 final : public Fence {
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FenceD3D11);
static RefPtr<FenceD3D11> Create(ID3D11Device* aDevice); static RefPtr<FenceD3D11> Create(ID3D11Device* aDevice);
static RefPtr<FenceD3D11> CreateFromHandle( static RefPtr<FenceD3D11> CreateFromHandle(
RefPtr<gfx::FileHandleWrapper> aHandle); RefPtr<gfx::FileHandleWrapper> aHandle);
FenceD3D11* AsFenceD3D11() override { return this; }
// Check if ID3D11Device suppors ID3D11Fence creation. // Check if ID3D11Device suppors ID3D11Fence creation.
static bool IsSupported(ID3D11Device* aDevice); static bool IsSupported(ID3D11Device* aDevice);
RefPtr<FenceD3D11> CloneFromHandle();
// Updates mSignalFence to incremented value after all previous work has // Updates mSignalFence to incremented value after all previous work has
// completed. Used only when FenceD3D11 is created by FenceD3D11::Create(). // completed. Used only when FenceD3D11 is created by FenceD3D11::Create().
bool IncrementAndSignal(); bool IncrementAndSignal();
@@ -66,7 +68,7 @@ class FenceD3D11 final {
protected: protected:
explicit FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle); explicit FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle);
~FenceD3D11(); virtual ~FenceD3D11();
// Device that is used for creating mSignalFence. // Device that is used for creating mSignalFence.
RefPtr<ID3D11Device> mDevice; RefPtr<ID3D11Device> mDevice;

View File

@@ -0,0 +1,169 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GpuProcessD3D11FencesHolderMap.h"
#include "mozilla/layers/FenceD3D11.h"
namespace mozilla {
namespace layers {
StaticAutoPtr<GpuProcessD3D11FencesHolderMap>
GpuProcessD3D11FencesHolderMap::sInstance;
/* static */
void GpuProcessD3D11FencesHolderMap::Init() {
MOZ_ASSERT(XRE_IsGPUProcess());
sInstance = new GpuProcessD3D11FencesHolderMap();
}
/* static */
void GpuProcessD3D11FencesHolderMap::Shutdown() {
MOZ_ASSERT(XRE_IsGPUProcess());
sInstance = nullptr;
}
GpuProcessD3D11FencesHolderMap::GpuProcessD3D11FencesHolderMap()
: mMonitor("GpuProcessD3D11FencesHolderMap::mMonitor") {}
GpuProcessD3D11FencesHolderMap::~GpuProcessD3D11FencesHolderMap() {}
void GpuProcessD3D11FencesHolderMap::Register(
GpuProcessFencesHolderId aHolderId) {
MonitorAutoLock lock(mMonitor);
mFencesHolderById[aHolderId] = MakeUnique<FencesHolder>();
}
void GpuProcessD3D11FencesHolderMap::Unregister(
GpuProcessFencesHolderId aHolderId) {
MonitorAutoLock lock(mMonitor);
auto it = mFencesHolderById.find(aHolderId);
if (it == mFencesHolderById.end()) {
return;
}
mFencesHolderById.erase(it);
}
void GpuProcessD3D11FencesHolderMap::SetWriteFence(
GpuProcessFencesHolderId aHolderId, RefPtr<FenceD3D11> aWriteFence) {
MOZ_ASSERT(aWriteFence);
if (!aWriteFence) {
return;
}
MonitorAutoLock lock(mMonitor);
auto it = mFencesHolderById.find(aHolderId);
if (it == mFencesHolderById.end()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
RefPtr<FenceD3D11> fence = aWriteFence->CloneFromHandle();
if (!fence) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
MOZ_ASSERT(!it->second->mWriteFence);
MOZ_ASSERT(it->second->mReadFences.empty());
it->second->mWriteFence = fence;
}
void GpuProcessD3D11FencesHolderMap::SetReadFence(
GpuProcessFencesHolderId aHolderId, RefPtr<FenceD3D11> aReadFence) {
MOZ_ASSERT(aReadFence);
if (!aReadFence) {
return;
}
MonitorAutoLock lock(mMonitor);
auto it = mFencesHolderById.find(aHolderId);
if (it == mFencesHolderById.end()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
RefPtr<FenceD3D11> fence = aReadFence->CloneFromHandle();
if (!fence) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
it->second->mReadFences.push_back(fence);
}
bool GpuProcessD3D11FencesHolderMap::WaitWriteFence(
GpuProcessFencesHolderId aHolderId, ID3D11Device* aDevice) {
MOZ_ASSERT(aDevice);
if (!aDevice) {
return false;
}
RefPtr<FenceD3D11> writeFence;
{
MonitorAutoLock lock(mMonitor);
auto it = mFencesHolderById.find(aHolderId);
if (it == mFencesHolderById.end()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return false;
}
writeFence = it->second->mWriteFence;
}
if (!writeFence) {
return true;
}
return writeFence->Wait(aDevice);
}
bool GpuProcessD3D11FencesHolderMap::WaitAllFencesAndForget(
GpuProcessFencesHolderId aHolderId, ID3D11Device* aDevice) {
MOZ_ASSERT(aDevice);
if (!aDevice) {
return false;
}
RefPtr<FenceD3D11> writeFence;
std::vector<RefPtr<FenceD3D11>> readFences;
{
MonitorAutoLock lock(mMonitor);
auto it = mFencesHolderById.find(aHolderId);
if (it == mFencesHolderById.end()) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return false;
}
writeFence = it->second->mWriteFence.forget();
readFences.swap(it->second->mReadFences);
MOZ_ASSERT(!it->second->mWriteFence);
MOZ_ASSERT(it->second->mReadFences.empty());
}
if (writeFence) {
writeFence->Wait(aDevice);
}
for (auto& fence : readFences) {
fence->Wait(aDevice);
}
return true;
}
} // namespace layers
} // namespace mozilla

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_GpuProcessD3D11FencesHolderMap_H
#define MOZILLA_GFX_GpuProcessD3D11FencesHolderMap_H
#include <d3d11.h>
#include <vector>
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/Maybe.h"
#include "mozilla/Monitor.h"
#include "mozilla/StaticPtr.h"
namespace mozilla {
namespace layers {
class FenceD3D11;
/**
* A class to manage FenceD3D11 that is shared in GPU process.
*/
class GpuProcessD3D11FencesHolderMap {
public:
static void Init();
static void Shutdown();
static GpuProcessD3D11FencesHolderMap* Get() { return sInstance; }
GpuProcessD3D11FencesHolderMap();
~GpuProcessD3D11FencesHolderMap();
void Register(GpuProcessFencesHolderId aHolderId);
void Unregister(GpuProcessFencesHolderId aHolderId);
void SetWriteFence(GpuProcessFencesHolderId aHolderId,
RefPtr<FenceD3D11> aWriteFence);
void SetReadFence(GpuProcessFencesHolderId aHolderId,
RefPtr<FenceD3D11> aReadFence);
bool WaitWriteFence(GpuProcessFencesHolderId aHolderId,
ID3D11Device* aDevice);
bool WaitAllFencesAndForget(GpuProcessFencesHolderId aHolderId,
ID3D11Device* aDevice);
private:
struct FencesHolder {
FencesHolder() = default;
RefPtr<FenceD3D11> mWriteFence;
std::vector<RefPtr<FenceD3D11>> mReadFences;
};
mutable Monitor mMonitor MOZ_UNANNOTATED;
std::unordered_map<GpuProcessFencesHolderId, UniquePtr<FencesHolder>,
GpuProcessFencesHolderId::HashFn>
mFencesHolderById;
static StaticAutoPtr<GpuProcessD3D11FencesHolderMap> sInstance;
};
} // namespace layers
} // namespace mozilla
#endif /* MOZILLA_GFX_GpuProcessD3D11FencesHolderMap_H */

View File

@@ -23,6 +23,8 @@
#include "mozilla/ipc/FileDescriptor.h" #include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/D3D11ZeroCopyTextureImage.h" #include "mozilla/layers/D3D11ZeroCopyTextureImage.h"
#include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
#include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/GpuProcessD3D11TextureMap.h"
#include "mozilla/layers/HelpersD3D11.h" #include "mozilla/layers/HelpersD3D11.h"
#include "mozilla/layers/VideoProcessorD3D11.h" #include "mozilla/layers/VideoProcessorD3D11.h"
@@ -661,8 +663,8 @@ DXGIYCbCrTextureData* DXGIYCbCrTextureData::Create(
ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureCb, ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureCb,
ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize, ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize,
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr, const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr,
gfx::ColorDepth aColorDepth, YUVColorSpace aYUVColorSpace, const gfx::ColorDepth aColorDepth, const YUVColorSpace aYUVColorSpace,
gfx::ColorRange aColorRange) { const gfx::ColorRange aColorRange) {
if (!aTextureY || !aTextureCb || !aTextureCr) { if (!aTextureY || !aTextureCb || !aTextureCr) {
return nullptr; return nullptr;
} }
@@ -714,13 +716,33 @@ DXGIYCbCrTextureData* DXGIYCbCrTextureData::Create(
const RefPtr<gfx::FileHandleWrapper> sharedHandleCr = const RefPtr<gfx::FileHandleWrapper> sharedHandleCr =
new gfx::FileHandleWrapper(UniqueFileHandle(handleCr)); new gfx::FileHandleWrapper(UniqueFileHandle(handleCr));
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
if (!fenceHolderMap) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return nullptr;
}
RefPtr<ID3D11Device> device;
aTextureY->GetDevice(getter_AddRefs(device));
if (!device) {
return nullptr;
}
RefPtr<FenceD3D11> fence = FenceD3D11::Create(device);
if (!fence) {
return nullptr;
}
auto fencesHolderId = GpuProcessFencesHolderId::GetNext();
fenceHolderMap->Register(fencesHolderId);
RefPtr<ID3D11Texture2D> textures[3] = {aTextureY, aTextureCb, aTextureCr}; RefPtr<ID3D11Texture2D> textures[3] = {aTextureY, aTextureCb, aTextureCr};
RefPtr<gfx::FileHandleWrapper> handles[3] = {sharedHandleY, sharedHandleCb, RefPtr<gfx::FileHandleWrapper> handles[3] = {sharedHandleY, sharedHandleCb,
sharedHandleCr}; sharedHandleCr};
DXGIYCbCrTextureData* texture = DXGIYCbCrTextureData* texture = new DXGIYCbCrTextureData(
new DXGIYCbCrTextureData(textures, handles, aSize, aSizeY, aSizeCbCr, textures, handles, aSize, aSizeY, aSizeCbCr, aColorDepth, aYUVColorSpace,
aColorDepth, aYUVColorSpace, aColorRange); aColorRange, fencesHolderId, fence);
return texture; return texture;
} }
@@ -729,16 +751,29 @@ DXGIYCbCrTextureData::DXGIYCbCrTextureData(
RefPtr<gfx::FileHandleWrapper>(aHandles)[3], const gfx::IntSize& aSize, RefPtr<gfx::FileHandleWrapper>(aHandles)[3], const gfx::IntSize& aSize,
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr, const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr,
const gfx::ColorDepth aColorDepth, const gfx::YUVColorSpace aYUVColorSpace, const gfx::ColorDepth aColorDepth, const gfx::YUVColorSpace aYUVColorSpace,
const gfx::ColorRange aColorRange) const gfx::ColorRange aColorRange,
const GpuProcessFencesHolderId aFencesHolderId,
const RefPtr<FenceD3D11> aWriteFence)
: mSize(aSize), : mSize(aSize),
mSizeY(aSizeY), mSizeY(aSizeY),
mSizeCbCr(aSizeCbCr), mSizeCbCr(aSizeCbCr),
mColorDepth(aColorDepth), mColorDepth(aColorDepth),
mYUVColorSpace(aYUVColorSpace), mYUVColorSpace(aYUVColorSpace),
mColorRange(aColorRange), mColorRange(aColorRange),
mFencesHolderId(aFencesHolderId),
mWriteFence(aWriteFence),
mD3D11Textures{aD3D11Textures[0], aD3D11Textures[1], aD3D11Textures[2]}, mD3D11Textures{aD3D11Textures[0], aD3D11Textures[1], aD3D11Textures[2]},
mHandles{aHandles[0], aHandles[1], aHandles[2]} {} mHandles{aHandles[0], aHandles[1], aHandles[2]} {}
DXGIYCbCrTextureData::~DXGIYCbCrTextureData() {
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
if (!fenceHolderMap) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
fenceHolderMap->Unregister(mFencesHolderId);
}
void DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const { void DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const {
aInfo.size = mSize; aInfo.size = mSize;
aInfo.format = gfx::SurfaceFormat::YUV420; aInfo.format = gfx::SurfaceFormat::YUV420;
@@ -748,9 +783,9 @@ void DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const {
void DXGIYCbCrTextureData::SerializeSpecific( void DXGIYCbCrTextureData::SerializeSpecific(
SurfaceDescriptorDXGIYCbCr* const aOutDesc) { SurfaceDescriptorDXGIYCbCr* const aOutDesc) {
*aOutDesc = SurfaceDescriptorDXGIYCbCr(mHandles[0], mHandles[1], mHandles[2], *aOutDesc = SurfaceDescriptorDXGIYCbCr(
mSize, mSizeY, mSizeCbCr, mColorDepth, mHandles[0], mHandles[1], mHandles[2], mSize, mSizeY, mSizeCbCr,
mYUVColorSpace, mColorRange); mColorDepth, mYUVColorSpace, mColorRange, mFencesHolderId);
} }
bool DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) { bool DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
@@ -1325,10 +1360,10 @@ DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(
mSize(aDescriptor.size()), mSize(aDescriptor.size()),
mSizeY(aDescriptor.sizeY()), mSizeY(aDescriptor.sizeY()),
mSizeCbCr(aDescriptor.sizeCbCr()), mSizeCbCr(aDescriptor.sizeCbCr()),
mIsLocked(false),
mColorDepth(aDescriptor.colorDepth()), mColorDepth(aDescriptor.colorDepth()),
mYUVColorSpace(aDescriptor.yUVColorSpace()), mYUVColorSpace(aDescriptor.yUVColorSpace()),
mColorRange(aDescriptor.colorRange()) { mColorRange(aDescriptor.colorRange()),
mFencesHolderId(aDescriptor.fencesHolderId()) {
mHandles[0] = aDescriptor.handleY(); mHandles[0] = aDescriptor.handleY();
mHandles[1] = aDescriptor.handleCb(); mHandles[1] = aDescriptor.handleCb();
mHandles[2] = aDescriptor.handleCr(); mHandles[2] = aDescriptor.handleCr();
@@ -1339,7 +1374,8 @@ void DXGIYCbCrTextureHostD3D11::CreateRenderTexture(
MOZ_ASSERT(mExternalImageId.isSome()); MOZ_ASSERT(mExternalImageId.isSome());
RefPtr<wr::RenderTextureHost> texture = new wr::RenderDXGIYCbCrTextureHost( RefPtr<wr::RenderTextureHost> texture = new wr::RenderDXGIYCbCrTextureHost(
mHandles, mYUVColorSpace, mColorDepth, mColorRange, mSizeY, mSizeCbCr); mHandles, mYUVColorSpace, mColorDepth, mColorRange, mSizeY, mSizeCbCr,
mFencesHolderId);
wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId, wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId,
texture.forget()); texture.forget());
@@ -1418,6 +1454,30 @@ bool DXGIYCbCrTextureHostD3D11::SupportsExternalCompositing(
return aBackend == WebRenderBackend::SOFTWARE; return aBackend == WebRenderBackend::SOFTWARE;
} }
void DXGIYCbCrTextureHostD3D11::NotifyNotUsed() {
if (!mReadFence) {
return;
}
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
if (!fenceHolderMap) {
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return;
}
fenceHolderMap->SetReadFence(mFencesHolderId, mReadFence);
mReadFence = nullptr;
}
void DXGIYCbCrTextureHostD3D11::SetReadFence(RefPtr<FenceD3D11> aReadFence) {
MOZ_ASSERT(aReadFence);
if (!aReadFence) {
return;
}
mReadFence = aReadFence;
}
bool DataTextureSourceD3D11::Update(DataSourceSurface* aSurface, bool DataTextureSourceD3D11::Update(DataSourceSurface* aSurface,
nsIntRegion* aDestRegion, nsIntRegion* aDestRegion,
IntPoint* aSrcOffset, IntPoint* aSrcOffset,

View File

@@ -35,6 +35,8 @@ class GLBlitHelper;
namespace layers { namespace layers {
class FenceD3D11;
gfx::DeviceResetReason DXGIErrorToDeviceResetReason(HRESULT aError); gfx::DeviceResetReason DXGIErrorToDeviceResetReason(HRESULT aError);
already_AddRefed<TextureHost> CreateTextureHostD3D11( already_AddRefed<TextureHost> CreateTextureHostD3D11(
@@ -164,12 +166,15 @@ class DXGIYCbCrTextureData : public TextureData {
friend class gl::GLBlitHelper; friend class gl::GLBlitHelper;
public: public:
static DXGIYCbCrTextureData* Create( static DXGIYCbCrTextureData* Create(ID3D11Texture2D* aTextureCb,
ID3D11Texture2D* aTextureCb, ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureY,
ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize, ID3D11Texture2D* aTextureCr,
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr, const gfx::IntSize& aSize,
gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace, const gfx::IntSize& aSizeY,
gfx::ColorRange aColorRange); const gfx::IntSize& aSizeCbCr,
const gfx::ColorDepth aColorDepth,
const gfx::YUVColorSpace aYUVColorSpace,
const gfx::ColorRange aColorRange);
bool Lock(OpenMode) override { return true; } bool Lock(OpenMode) override { return true; }
@@ -203,6 +208,8 @@ class DXGIYCbCrTextureData : public TextureData {
const gfx::ColorDepth mColorDepth; const gfx::ColorDepth mColorDepth;
const gfx::YUVColorSpace mYUVColorSpace; const gfx::YUVColorSpace mYUVColorSpace;
const gfx::ColorRange mColorRange; const gfx::ColorRange mColorRange;
const GpuProcessFencesHolderId mFencesHolderId;
const RefPtr<FenceD3D11> mWriteFence;
protected: protected:
DXGIYCbCrTextureData(RefPtr<ID3D11Texture2D> (&aD3D11Textures)[3], DXGIYCbCrTextureData(RefPtr<ID3D11Texture2D> (&aD3D11Textures)[3],
@@ -211,7 +218,10 @@ class DXGIYCbCrTextureData : public TextureData {
const gfx::IntSize& aSizeCbCr, const gfx::IntSize& aSizeCbCr,
const gfx::ColorDepth aColorDepth, const gfx::ColorDepth aColorDepth,
const gfx::YUVColorSpace aYUVColorSpace, const gfx::YUVColorSpace aYUVColorSpace,
const gfx::ColorRange aColorRange); const gfx::ColorRange aColorRange,
const GpuProcessFencesHolderId aFencesHolderId,
const RefPtr<FenceD3D11> aWriteFence);
virtual ~DXGIYCbCrTextureData();
RefPtr<ID3D11Texture2D> mD3D11Textures[3]; RefPtr<ID3D11Texture2D> mD3D11Textures[3];
RefPtr<gfx::FileHandleWrapper> mHandles[3]; RefPtr<gfx::FileHandleWrapper> mHandles[3];
@@ -435,19 +445,28 @@ class DXGIYCbCrTextureHostD3D11 : public TextureHost {
bool SupportsExternalCompositing(WebRenderBackend aBackend) override; bool SupportsExternalCompositing(WebRenderBackend aBackend) override;
protected: void NotifyNotUsed() override;
RefPtr<ID3D11Texture2D> mTextures[3];
gfx::IntSize mSize; DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override {
gfx::IntSize mSizeY; return this;
gfx::IntSize mSizeCbCr; }
void SetReadFence(RefPtr<FenceD3D11> aReadFence);
const gfx::IntSize mSize;
const gfx::IntSize mSizeY;
const gfx::IntSize mSizeCbCr;
const gfx::ColorDepth mColorDepth;
const gfx::YUVColorSpace mYUVColorSpace;
const gfx::ColorRange mColorRange;
const GpuProcessFencesHolderId mFencesHolderId;
protected:
// Handles will be closed automatically when `UniqueFileHandle` gets // Handles will be closed automatically when `UniqueFileHandle` gets
// destroyed. // destroyed.
RefPtr<gfx::FileHandleWrapper> mHandles[3]; RefPtr<gfx::FileHandleWrapper> mHandles[3];
bool mIsLocked; bool mIsLocked = false;
gfx::ColorDepth mColorDepth; RefPtr<FenceD3D11> mReadFence;
gfx::YUVColorSpace mYUVColorSpace;
gfx::ColorRange mColorRange;
}; };
class CompositingRenderTargetD3D11 : public CompositingRenderTarget, class CompositingRenderTargetD3D11 : public CompositingRenderTarget,

View File

@@ -262,6 +262,18 @@ struct ParamTraits<mozilla::layers::GpuProcessTextureId> {
} }
}; };
template <>
struct ParamTraits<mozilla::layers::GpuProcessFencesHolderId> {
typedef mozilla::layers::GpuProcessFencesHolderId paramType;
static void Write(MessageWriter* writer, const paramType& param) {
WriteParam(writer, param.mId);
}
static bool Read(MessageReader* reader, paramType* result) {
return ReadParam(reader, &result->mId);
}
};
template <> template <>
struct ParamTraits<mozilla::layers::FrameMetrics> struct ParamTraits<mozilla::layers::FrameMetrics>
: BitfieldHelper<mozilla::layers::FrameMetrics> { : BitfieldHelper<mozilla::layers::FrameMetrics> {

View File

@@ -30,6 +30,7 @@ using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
[RefCounted] using mozilla::layers::GpuFence from "mozilla/layers/GpuFence.h"; [RefCounted] using mozilla::layers::GpuFence from "mozilla/layers/GpuFence.h";
using mozilla::layers::GpuProcessTextureId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::GpuProcessTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::GpuProcessFencesHolderId from "mozilla/layers/LayersTypes.h";
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h"; using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h"; using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h";
@@ -60,6 +61,7 @@ namespace layers {
ColorDepth colorDepth; ColorDepth colorDepth;
YUVColorSpace yUVColorSpace; YUVColorSpace yUVColorSpace;
ColorRange colorRange; ColorRange colorRange;
GpuProcessFencesHolderId fencesHolderId;
}; };
[Comparable] struct SurfaceDescriptorMacIOSurface { [Comparable] struct SurfaceDescriptorMacIOSurface {

View File

@@ -38,6 +38,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
"d3d11/CompositorD3D11.h", "d3d11/CompositorD3D11.h",
"d3d11/DeviceAttachmentsD3D11.h", "d3d11/DeviceAttachmentsD3D11.h",
"d3d11/FenceD3D11.h", "d3d11/FenceD3D11.h",
"d3d11/GpuProcessD3D11FencesHolderMap.h",
"d3d11/GpuProcessD3D11TextureMap.h", "d3d11/GpuProcessD3D11TextureMap.h",
"d3d11/HelpersD3D11.h", "d3d11/HelpersD3D11.h",
"d3d11/ShaderDefinitionsD3D11.h", "d3d11/ShaderDefinitionsD3D11.h",
@@ -47,6 +48,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
] ]
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"d3d11/FenceD3D11.cpp", "d3d11/FenceD3D11.cpp",
"d3d11/GpuProcessD3D11FencesHolderMap.cpp",
"d3d11/GpuProcessD3D11TextureMap.cpp", "d3d11/GpuProcessD3D11TextureMap.cpp",
"d3d11/TextureD3D11.cpp", "d3d11/TextureD3D11.cpp",
"d3d11/TextureHostWrapperD3D11.cpp", "d3d11/TextureHostWrapperD3D11.cpp",
@@ -143,6 +145,7 @@ EXPORTS.mozilla.layers += [
"D3D11ZeroCopyTextureImage.h", "D3D11ZeroCopyTextureImage.h",
"DirectionUtils.h", "DirectionUtils.h",
"Effects.h", "Effects.h",
"Fence.h",
"GpuFence.h", "GpuFence.h",
"ImageDataSerializer.h", "ImageDataSerializer.h",
"ipc/ActiveResource.h", "ipc/ActiveResource.h",
@@ -368,6 +371,7 @@ UNIFIED_SOURCES += [
"CompositorAnimationStorage.cpp", "CompositorAnimationStorage.cpp",
"CompositorTypes.cpp", "CompositorTypes.cpp",
"Effects.cpp", "Effects.cpp",
"Fence.cpp",
"FrameMetrics.cpp", "FrameMetrics.cpp",
"GLImages.cpp", "GLImages.cpp",
"ImageDataSerializer.cpp", "ImageDataSerializer.cpp",

View File

@@ -14,6 +14,7 @@
#include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/AsyncImagePipelineOp.h" #include "mozilla/layers/AsyncImagePipelineOp.h"
#include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/Fence.h"
#include "mozilla/layers/RemoteTextureHostWrapper.h" #include "mozilla/layers/RemoteTextureHostWrapper.h"
#include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/layers/WebRenderImageHost.h" #include "mozilla/layers/WebRenderImageHost.h"
@@ -27,6 +28,11 @@
# include "mozilla/layers/TextureHostOGL.h" # include "mozilla/layers/TextureHostOGL.h"
#endif #endif
#ifdef XP_WIN
# include "mozilla/layers/FenceD3D11.h"
# include "mozilla/layers/TextureD3D11.h"
#endif
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@@ -658,7 +664,7 @@ void AsyncImagePipelineManager::HoldExternalImage(
void AsyncImagePipelineManager::NotifyPipelinesUpdated( void AsyncImagePipelineManager::NotifyPipelinesUpdated(
RefPtr<const wr::WebRenderPipelineInfo> aInfo, RefPtr<const wr::WebRenderPipelineInfo> aInfo,
wr::RenderedFrameId aLatestFrameId, wr::RenderedFrameId aLatestFrameId,
wr::RenderedFrameId aLastCompletedFrameId, UniqueFileHandle&& aFenceFd) { wr::RenderedFrameId aLastCompletedFrameId, RefPtr<Fence>&& aFence) {
MOZ_ASSERT(wr::RenderThread::IsInRenderThread()); MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
MOZ_ASSERT(mLastCompletedFrameId <= aLastCompletedFrameId.mId); MOZ_ASSERT(mLastCompletedFrameId <= aLastCompletedFrameId.mId);
MOZ_ASSERT(aLatestFrameId.IsValid()); MOZ_ASSERT(aLatestFrameId.IsValid());
@@ -673,7 +679,7 @@ void AsyncImagePipelineManager::NotifyPipelinesUpdated(
// Move the pending updates into the submitted ones. // Move the pending updates into the submitted ones.
mRenderSubmittedUpdates.emplace_back( mRenderSubmittedUpdates.emplace_back(
aLatestFrameId, aLatestFrameId,
WebRenderPipelineInfoHolder(std::move(aInfo), std::move(aFenceFd))); WebRenderPipelineInfoHolder(std::move(aInfo), std::move(aFence)));
} }
// Queue a runnable on the compositor thread to process the updates. // Queue a runnable on the compositor thread to process the updates.
@@ -705,7 +711,7 @@ void AsyncImagePipelineManager::ProcessPipelineUpdates() {
auto& holder = update.second; auto& holder = update.second;
const auto& info = holder.mInfo->Raw(); const auto& info = holder.mInfo->Raw();
mReleaseFenceFd = std::move(holder.mFenceFd); mReleaseFence = std::move(holder.mFence);
for (auto& epoch : info.epochs) { for (auto& epoch : info.epochs) {
ProcessPipelineRendered(epoch.pipeline_id, epoch.epoch, update.first); ProcessPipelineRendered(epoch.pipeline_id, epoch.epoch, update.first);
@@ -736,8 +742,10 @@ void AsyncImagePipelineManager::ProcessPipelineRendered(
for (auto it = holder->mTextureHostsUntilRenderSubmitted.begin(); for (auto it = holder->mTextureHostsUntilRenderSubmitted.begin();
it != firstSubmittedHostToKeep; ++it) { it != firstSubmittedHostToKeep; ++it) {
const auto& entry = it; const auto& entry = it;
if (entry->mTexture->GetAndroidHardwareBuffer() && mReleaseFenceFd) { if (entry->mTexture->GetAndroidHardwareBuffer() && mReleaseFence &&
entry->mTexture->SetReleaseFence(DuplicateFileHandle(mReleaseFenceFd)); mReleaseFence->AsFenceFileHandle()) {
entry->mTexture->SetReleaseFence(
mReleaseFence->AsFenceFileHandle()->DuplicateFileHandle());
} }
} }
#endif #endif
@@ -753,6 +761,18 @@ void AsyncImagePipelineManager::ProcessPipelineRendered(
holder->mTextureHostsUntilRenderCompleted.begin(), holder->mTextureHostsUntilRenderCompleted.begin(),
holder->mTextureHostsUntilRenderCompleted.end(), holder->mTextureHostsUntilRenderCompleted.end(),
[&aEpoch](const auto& entry) { return aEpoch <= entry->mEpoch; }); [&aEpoch](const auto& entry) { return aEpoch <= entry->mEpoch; });
#ifdef XP_WIN
for (auto it = holder->mTextureHostsUntilRenderCompleted.begin();
it != firstCompletedHostToKeep; ++it) {
const auto& entry = *it;
auto* host = entry->mTexture->AsDXGIYCbCrTextureHostD3D11();
if (host && mReleaseFence && mReleaseFence->AsFenceD3D11()) {
host->SetReadFence(mReleaseFence->AsFenceD3D11());
}
}
#endif
if (firstCompletedHostToKeep != if (firstCompletedHostToKeep !=
holder->mTextureHostsUntilRenderCompleted.begin()) { holder->mTextureHostsUntilRenderCompleted.begin()) {
std::vector<UniquePtr<ForwardingTextureHost>> hostsUntilCompleted( std::vector<UniquePtr<ForwardingTextureHost>> hostsUntilCompleted(
@@ -824,8 +844,8 @@ wr::Epoch AsyncImagePipelineManager::GetNextImageEpoch() {
AsyncImagePipelineManager::WebRenderPipelineInfoHolder:: AsyncImagePipelineManager::WebRenderPipelineInfoHolder::
WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo, WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo,
UniqueFileHandle&& aFenceFd) RefPtr<Fence>&& aFence)
: mInfo(aInfo), mFenceFd(std::move(aFenceFd)) {} : mInfo(aInfo), mFence(std::move(aFence)) {}
AsyncImagePipelineManager::WebRenderPipelineInfoHolder:: AsyncImagePipelineManager::WebRenderPipelineInfoHolder::
~WebRenderPipelineInfoHolder() = default; ~WebRenderPipelineInfoHolder() = default;

View File

@@ -32,6 +32,7 @@ namespace layers {
class CompositableHost; class CompositableHost;
class CompositorVsyncScheduler; class CompositorVsyncScheduler;
class Fence;
class WebRenderImageHost; class WebRenderImageHost;
class WebRenderTextureHost; class WebRenderTextureHost;
@@ -71,7 +72,7 @@ class AsyncImagePipelineManager final {
void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo, void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo,
wr::RenderedFrameId aLatestFrameId, wr::RenderedFrameId aLatestFrameId,
wr::RenderedFrameId aLastCompletedFrameId, wr::RenderedFrameId aLastCompletedFrameId,
UniqueFileHandle&& aFenceFd); RefPtr<Fence>&& aFence);
// This is run on the compositor thread to process mRenderSubmittedUpdates. We // This is run on the compositor thread to process mRenderSubmittedUpdates. We
// make this public because we need to invoke it from other places. // make this public because we need to invoke it from other places.
@@ -277,11 +278,11 @@ class AsyncImagePipelineManager final {
struct WebRenderPipelineInfoHolder { struct WebRenderPipelineInfoHolder {
WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo, WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo,
UniqueFileHandle&& aFenceFd); RefPtr<Fence>&& aFence);
~WebRenderPipelineInfoHolder(); ~WebRenderPipelineInfoHolder();
WebRenderPipelineInfoHolder(WebRenderPipelineInfoHolder&&) = default; WebRenderPipelineInfoHolder(WebRenderPipelineInfoHolder&&) = default;
RefPtr<const wr::WebRenderPipelineInfo> mInfo; RefPtr<const wr::WebRenderPipelineInfo> mInfo;
UniqueFileHandle mFenceFd; RefPtr<Fence> mFence;
}; };
std::vector<std::pair<wr::RenderedFrameId, WebRenderPipelineInfoHolder>> std::vector<std::pair<wr::RenderedFrameId, WebRenderPipelineInfoHolder>>
@@ -292,7 +293,7 @@ class AsyncImagePipelineManager final {
std::vector<std::pair<wr::RenderedFrameId, std::vector<std::pair<wr::RenderedFrameId,
std::vector<UniquePtr<ForwardingTextureHost>>>> std::vector<UniquePtr<ForwardingTextureHost>>>>
mTexturesInUseByGPU; mTexturesInUseByGPU;
UniqueFileHandle mReleaseFenceFd; RefPtr<Fence> mReleaseFence;
}; };
} // namespace layers } // namespace layers

View File

@@ -16,6 +16,10 @@
# include "mozilla/layers/TextureHostOGL.h" # include "mozilla/layers/TextureHostOGL.h"
#endif #endif
#ifdef XP_WIN
# include "mozilla/layers/TextureD3D11.h"
#endif
namespace mozilla::layers { namespace mozilla::layers {
class ScheduleHandleRenderTextureOps : public wr::NotificationHandler { class ScheduleHandleRenderTextureOps : public wr::NotificationHandler {
@@ -119,6 +123,11 @@ void WebRenderTextureHost::NotifyNotUsed() {
mWrappedTextureHost->AsTextureHostWrapperD3D11()) { mWrappedTextureHost->AsTextureHostWrapperD3D11()) {
mWrappedTextureHost->NotifyNotUsed(); mWrappedTextureHost->NotifyNotUsed();
} }
#ifdef XP_WIN
if (auto* host = AsDXGIYCbCrTextureHostD3D11()) {
host->NotifyNotUsed();
}
#endif
TextureHost::NotifyNotUsed(); TextureHost::NotifyNotUsed();
} }

View File

@@ -72,6 +72,10 @@ class WebRenderTextureHost : public TextureHost {
return mWrappedTextureHost->AsDXGITextureHostD3D11(); return mWrappedTextureHost->AsDXGITextureHostD3D11();
} }
DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override {
return mWrappedTextureHost->AsDXGIYCbCrTextureHostD3D11();
}
bool IsWrappingSurfaceTextureHost() override; bool IsWrappingSurfaceTextureHost() override;
virtual void PrepareForUse() override; virtual void PrepareForUse() override;

View File

@@ -10,6 +10,7 @@
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h" #include "mozilla/UniquePtrExtensions.h"
#include "mozilla/layers/Fence.h"
#include "mozilla/webrender/WebRenderTypes.h" #include "mozilla/webrender/WebRenderTypes.h"
#include "Units.h" #include "Units.h"
@@ -202,13 +203,7 @@ class RenderCompositor {
} }
virtual bool MaybeProcessScreenshotQueue() { return false; } virtual bool MaybeProcessScreenshotQueue() { return false; }
// Returns FileDescriptor of release fence. virtual RefPtr<layers::Fence> GetAndResetReleaseFence() { return nullptr; }
// Release fence is a fence that is used for waiting until usage/composite of
// AHardwareBuffer is ended. The fence is delivered to client side via
// ImageBridge. It is used only on android.
virtual UniqueFileHandle GetAndResetReleaseFence() {
return UniqueFileHandle();
}
virtual bool IsPaused() { return false; } virtual bool IsPaused() { return false; }

View File

@@ -13,6 +13,7 @@
#include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/StackArray.h" #include "mozilla/gfx/StackArray.h"
#include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/TextureD3D11.h" #include "mozilla/layers/TextureD3D11.h"
#include "mozilla/layers/HelpersD3D11.h" #include "mozilla/layers/HelpersD3D11.h"
#include "mozilla/layers/SyncObject.h" #include "mozilla/layers/SyncObject.h"
@@ -124,11 +125,14 @@ bool RenderCompositorANGLE::Initialize(nsACString& aError) {
MOZ_ASSERT(mEGLConfig); MOZ_ASSERT(mEGLConfig);
mDevice = GetDeviceOfEGLDisplay(aError); mDevice = GetDeviceOfEGLDisplay(aError);
if (!mDevice) { if (!mDevice) {
return false; return false;
} }
if (layers::FenceD3D11::IsSupported(mDevice)) {
mFence = layers::FenceD3D11::Create(mDevice);
}
mDevice->GetImmediateContext(getter_AddRefs(mCtx)); mDevice->GetImmediateContext(getter_AddRefs(mCtx));
if (!mCtx) { if (!mCtx) {
aError.Assign("RcANGLE(get immediate context failed)"_ns); aError.Assign("RcANGLE(get immediate context failed)"_ns);
@@ -462,6 +466,10 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
RenderedFrameId frameId = GetNextRenderFrameId(); RenderedFrameId frameId = GetNextRenderFrameId();
InsertGraphicsCommandsFinishedWaitQuery(frameId); InsertGraphicsCommandsFinishedWaitQuery(frameId);
if (mFence) {
mFence->IncrementAndSignal();
}
if (!UseCompositor()) { if (!UseCompositor()) {
auto start = TimeStamp::Now(); auto start = TimeStamp::Now();
if (auto* fxrHandler = mWidget->AsWindows()->GetFxrOutputHandler()) { if (auto* fxrHandler = mWidget->AsWindows()->GetFxrOutputHandler()) {
@@ -564,6 +572,14 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
return frameId; return frameId;
} }
RefPtr<layers::Fence> RenderCompositorANGLE::GetAndResetReleaseFence() {
RefPtr<layers::Fence> fence;
if (mFence) {
fence = mFence->CloneFromHandle();
}
return fence.forget();
}
bool RenderCompositorANGLE::WaitForGPU() { bool RenderCompositorANGLE::WaitForGPU() {
// Note: this waits on the query we inserted in the previous frame, // Note: this waits on the query we inserted in the previous frame,
// not the one we just inserted now. Example: // not the one we just inserted now. Example:

View File

@@ -28,6 +28,10 @@ namespace gl {
class GLLibraryEGL; class GLLibraryEGL;
} // namespace gl } // namespace gl
namespace layers {
class FenceD3D11;
} // namespace layers
namespace wr { namespace wr {
class DCLayerTree; class DCLayerTree;
@@ -113,6 +117,8 @@ class RenderCompositorANGLE final : public RenderCompositor {
bool RequestFullRender() override; bool RequestFullRender() override;
uint32_t GetMaxPartialPresentRects() override; uint32_t GetMaxPartialPresentRects() override;
RefPtr<layers::Fence> GetAndResetReleaseFence() override;
bool MaybeReadback(const gfx::IntSize& aReadbackSize, bool MaybeReadback(const gfx::IntSize& aReadbackSize,
const wr::ImageFormat& aReadbackFormat, const wr::ImageFormat& aReadbackFormat,
const Range<uint8_t>& aReadbackBuffer, const Range<uint8_t>& aReadbackBuffer,
@@ -169,6 +175,7 @@ class RenderCompositorANGLE final : public RenderCompositor {
bool mFirstPresent = true; bool mFirstPresent = true;
// Wether we're currently using alpha. // Wether we're currently using alpha.
bool mSwapChainUsingAlpha = false; bool mSwapChainUsingAlpha = false;
RefPtr<layers::FenceD3D11> mFence;
}; };
} // namespace wr } // namespace wr

View File

@@ -123,7 +123,7 @@ RenderedFrameId RenderCompositorEGL::EndFrame(
if (sync) { if (sync) {
int fenceFd = egl->fDupNativeFenceFDANDROID(sync); int fenceFd = egl->fDupNativeFenceFDANDROID(sync);
if (fenceFd >= 0) { if (fenceFd >= 0) {
mReleaseFenceFd = UniqueFileHandle(fenceFd); mReleaseFence = new layers::FenceFileHandle(UniqueFileHandle(fenceFd));
} }
egl->fDestroySync(sync); egl->fDestroySync(sync);
sync = nullptr; sync = nullptr;
@@ -259,12 +259,12 @@ void RenderCompositorEGL::DestroyEGLSurface() {
} }
} }
UniqueFileHandle RenderCompositorEGL::GetAndResetReleaseFence() { RefPtr<layers::Fence> RenderCompositorEGL::GetAndResetReleaseFence() {
#ifdef MOZ_WIDGET_ANDROID #ifdef MOZ_WIDGET_ANDROID
MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFenceFd); MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFence);
return std::move(mReleaseFenceFd); return mReleaseFence.forget();
#else #else
return UniqueFileHandle(); return nullptr;
#endif #endif
} }

View File

@@ -46,7 +46,7 @@ class RenderCompositorEGL : public RenderCompositor {
void SetBufferDamageRegion(const wr::DeviceIntRect* aRects, void SetBufferDamageRegion(const wr::DeviceIntRect* aRects,
size_t aNumRects) override; size_t aNumRects) override;
UniqueFileHandle GetAndResetReleaseFence() override; RefPtr<layers::Fence> GetAndResetReleaseFence() override;
protected: protected:
EGLSurface CreateEGLSurface(); EGLSurface CreateEGLSurface();
@@ -66,7 +66,7 @@ class RenderCompositorEGL : public RenderCompositor {
// Release fence is a fence that is used for waiting until usage/composite of // Release fence is a fence that is used for waiting until usage/composite of
// AHardwareBuffer is ended. The fence is delivered to client side via // AHardwareBuffer is ended. The fence is delivered to client side via
// ImageBridge. It is used only on android. // ImageBridge. It is used only on android.
UniqueFileHandle mReleaseFenceFd; RefPtr<layers::Fence> mReleaseFence;
}; };
} // namespace wr } // namespace wr

View File

@@ -18,6 +18,7 @@
#include "mozilla/gfx/Logging.h" #include "mozilla/gfx/Logging.h"
#include "mozilla/layers/FenceD3D11.h" #include "mozilla/layers/FenceD3D11.h"
#include "mozilla/layers/GpuProcessD3D11TextureMap.h" #include "mozilla/layers/GpuProcessD3D11TextureMap.h"
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
#include "mozilla/layers/TextureD3D11.h" #include "mozilla/layers/TextureD3D11.h"
namespace mozilla { namespace mozilla {
@@ -472,8 +473,10 @@ bool RenderDXGITextureHost::SyncObjectNeeded() {
RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost( RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3], RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth, const gfx::YUVColorSpace aYUVColorSpace, const gfx::ColorDepth aColorDepth,
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr) const gfx::ColorRange aColorRange, const gfx::IntSize aSizeY,
const gfx::IntSize aSizeCbCr,
const layers::GpuProcessFencesHolderId aFencesHolderId)
: mHandles{aHandles[0], aHandles[1], aHandles[2]}, : mHandles{aHandles[0], aHandles[1], aHandles[2]},
mSurfaces{0}, mSurfaces{0},
mStreams{0}, mStreams{0},
@@ -483,7 +486,7 @@ RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
mColorRange(aColorRange), mColorRange(aColorRange),
mSizeY(aSizeY), mSizeY(aSizeY),
mSizeCbCr(aSizeCbCr), mSizeCbCr(aSizeCbCr),
mLocked(false) { mFencesHolderId(aFencesHolderId) {
MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost); MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
// Assume the chroma planes are rounded up if the luma plane is odd sized. // Assume the chroma planes are rounded up if the luma plane is odd sized.
MOZ_ASSERT((mSizeCbCr.width == mSizeY.width || MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
@@ -631,25 +634,20 @@ bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
} }
} }
for (int i = 0; i < 3; ++i) { mDevice = aDevice;
mTextures[i]->QueryInterface(
(IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
}
return true; return true;
} }
bool RenderDXGIYCbCrTextureHost::LockInternal() { bool RenderDXGIYCbCrTextureHost::LockInternal() {
if (!mLocked) { if (!mLocked) {
if (mKeyedMutexs[0]) { auto* fenceHolderMap = layers::GpuProcessD3D11FencesHolderMap::Get();
for (const auto& mutex : mKeyedMutexs) { if (!fenceHolderMap) {
HRESULT hr = mutex->AcquireSync(0, 10000); MOZ_ASSERT_UNREACHABLE("unexpected to be called");
if (hr != S_OK) { return false;
gfxCriticalError() }
<< "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr=" if (!fenceHolderMap->WaitWriteFence(mFencesHolderId, mDevice)) {
<< gfx::hexa(hr); return false;
return false;
}
}
} }
mLocked = true; mLocked = true;
} }
@@ -688,11 +686,6 @@ wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(uint8_t aChannelIndex,
void RenderDXGIYCbCrTextureHost::Unlock() { void RenderDXGIYCbCrTextureHost::Unlock() {
if (mLocked) { if (mLocked) {
if (mKeyedMutexs[0]) {
for (const auto& mutex : mKeyedMutexs) {
mutex->ReleaseSync(0);
}
}
mLocked = false; mLocked = false;
} }
} }
@@ -736,7 +729,6 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
mTextureHandles[i] = 0; mTextureHandles[i] = 0;
mTextures[i] = nullptr; mTextures[i] = nullptr;
mKeyedMutexs[i] = nullptr;
if (mSurfaces[i]) { if (mSurfaces[i]) {
egl->fDestroySurface(mSurfaces[i]); egl->fDestroySurface(mSurfaces[i]);
@@ -748,6 +740,7 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
} }
} }
} }
mDevice = nullptr;
} }
} // namespace wr } // namespace wr

View File

@@ -139,8 +139,10 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
public: public:
explicit RenderDXGIYCbCrTextureHost( explicit RenderDXGIYCbCrTextureHost(
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3], RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth, const gfx::YUVColorSpace aYUVColorSpace,
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr); const gfx::ColorDepth aColorDepth, const gfx::ColorRange aColorRange,
const gfx::IntSize aSizeY, const gfx::IntSize aSizeCbCr,
const layers::GpuProcessFencesHolderId aFencesHolderId);
RenderDXGIYCbCrTextureHost* AsRenderDXGIYCbCrTextureHost() override { RenderDXGIYCbCrTextureHost* AsRenderDXGIYCbCrTextureHost() override {
return this; return this;
@@ -200,7 +202,7 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
RefPtr<gfx::FileHandleWrapper> mHandles[3]; RefPtr<gfx::FileHandleWrapper> mHandles[3];
RefPtr<ID3D11Texture2D> mTextures[3]; RefPtr<ID3D11Texture2D> mTextures[3];
RefPtr<IDXGIKeyedMutex> mKeyedMutexs[3]; RefPtr<ID3D11Device> mDevice;
EGLSurface mSurfaces[3]; EGLSurface mSurfaces[3];
EGLStreamKHR mStreams[3]; EGLStreamKHR mStreams[3];
@@ -212,13 +214,14 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
RefPtr<ID3D11DeviceContext> mDeviceContext; RefPtr<ID3D11DeviceContext> mDeviceContext;
RefPtr<ID3D11Texture2D> mCpuTexture[3]; RefPtr<ID3D11Texture2D> mCpuTexture[3];
gfx::YUVColorSpace mYUVColorSpace; const gfx::YUVColorSpace mYUVColorSpace;
gfx::ColorDepth mColorDepth; const gfx::ColorDepth mColorDepth;
gfx::ColorRange mColorRange; const gfx::ColorRange mColorRange;
gfx::IntSize mSizeY; const gfx::IntSize mSizeY;
gfx::IntSize mSizeCbCr; const gfx::IntSize mSizeCbCr;
const layers::GpuProcessFencesHolderId mFencesHolderId;
bool mLocked; bool mLocked = false;
}; };
} // namespace wr } // namespace wr

View File

@@ -21,6 +21,7 @@
#include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/CompositorBridgeParent.h" #include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorManagerParent.h" #include "mozilla/layers/CompositorManagerParent.h"
#include "mozilla/layers/Fence.h"
#include "mozilla/layers/WebRenderBridgeParent.h" #include "mozilla/layers/WebRenderBridgeParent.h"
#include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/layers/SurfacePool.h" #include "mozilla/layers/SurfacePool.h"
@@ -866,10 +867,10 @@ void RenderThread::UpdateAndRender(
renderer->GetCompositorBridge(), info, aStartId, renderer->GetCompositorBridge(), info, aStartId,
aStartTime, start, end, aRender, *aStats)); aStartTime, start, end, aRender, *aStats));
UniqueFileHandle fenceFd; RefPtr<layers::Fence> fence;
if (latestFrameId.IsValid()) { if (latestFrameId.IsValid()) {
fenceFd = renderer->GetAndResetReleaseFence(); fence = renderer->GetAndResetReleaseFence();
// Wait for GPU after posting NotifyDidRender, since the wait is not // Wait for GPU after posting NotifyDidRender, since the wait is not
// necessary for the NotifyDidRender. // necessary for the NotifyDidRender.
@@ -898,7 +899,7 @@ void RenderThread::UpdateAndRender(
// this code at all; it would bail out at the mRenderers.find check above. // this code at all; it would bail out at the mRenderers.find check above.
MOZ_ASSERT(pipelineMgr); MOZ_ASSERT(pipelineMgr);
pipelineMgr->NotifyPipelinesUpdated(info, latestFrameId, lastCompletedFrameId, pipelineMgr->NotifyPipelinesUpdated(info, latestFrameId, lastCompletedFrameId,
std::move(fenceFd)); std::move(fence));
} }
void RenderThread::Pause(wr::WindowId aWindowId) { void RenderThread::Pause(wr::WindowId aWindowId) {

View File

@@ -36,6 +36,7 @@ class GLContext;
} // namespace gl } // namespace gl
namespace layers { namespace layers {
class CompositorBridgeParent; class CompositorBridgeParent;
class Fence;
class ShaderProgramOGLsHolder; class ShaderProgramOGLsHolder;
class SurfacePool; class SurfacePool;
} // namespace layers } // namespace layers

View File

@@ -13,6 +13,7 @@
#include "mozilla/gfx/Types.h" #include "mozilla/gfx/Types.h"
#include "mozilla/layers/CompositorBridgeParent.h" #include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/Fence.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/ProfilerScreenshots.h" #include "mozilla/layers/ProfilerScreenshots.h"
#include "mozilla/webrender/RenderCompositor.h" #include "mozilla/webrender/RenderCompositor.h"
@@ -280,7 +281,7 @@ void RendererOGL::WaitForGPU() {
} }
} }
UniqueFileHandle RendererOGL::GetAndResetReleaseFence() { RefPtr<layers::Fence> RendererOGL::GetAndResetReleaseFence() {
return mCompositor->GetAndResetReleaseFence(); return mCompositor->GetAndResetReleaseFence();
} }

View File

@@ -27,6 +27,7 @@ class GLContext;
namespace layers { namespace layers {
class CompositorBridgeParent; class CompositorBridgeParent;
class Fence;
class SyncObjectHost; class SyncObjectHost;
} // namespace layers } // namespace layers
@@ -70,7 +71,7 @@ class RendererOGL {
void WaitForGPU(); void WaitForGPU();
/// This can be called on the render thread only. /// This can be called on the render thread only.
UniqueFileHandle GetAndResetReleaseFence(); RefPtr<layers::Fence> GetAndResetReleaseFence();
/// This can be called on the render thread only. /// This can be called on the render thread only.
RenderedFrameId GetLastCompletedFrameId(); RenderedFrameId GetLastCompletedFrameId();