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:
@@ -30,6 +30,7 @@
|
||||
#include "mozilla/glean/DomMediaPlatformsWmfMetrics.h"
|
||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
@@ -668,10 +669,18 @@ WMFVideoMFTManager::CreateBasicVideoFrame(IMFSample* aSample,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RefPtr<layers::PlanarYCbCrImage> image =
|
||||
new IMFYCbCrImage(buffer, twoDBuffer, mKnowsCompositor, mImageContainer);
|
||||
|
||||
RefPtr<layers::PlanarYCbCrImage> image;
|
||||
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
|
||||
if (XRE_IsGPUProcess() && layers::FenceD3D11::IsSupported(device)) {
|
||||
// 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(
|
||||
mVideoInfo.mDisplay, aStreamOffset, pts, duration, image.forget(), false,
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
# include "gfxWindowsPlatform.h"
|
||||
# include "mozilla/WindowsVersion.h"
|
||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||
# include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
|
||||
# include "mozilla/layers/GpuProcessD3D11TextureMap.h"
|
||||
# include "mozilla/layers/TextureD3D11.h"
|
||||
# include "mozilla/widget/WinCompositorWindowThread.h"
|
||||
@@ -214,6 +215,7 @@ bool GPUParent::Init(mozilla::ipc::UntypedEndpoint&& aEndpoint,
|
||||
#if defined(XP_WIN)
|
||||
gfxWindowsPlatform::InitMemoryReportersForGPUProcess();
|
||||
DeviceManagerDx::Init();
|
||||
GpuProcessD3D11FencesHolderMap::Init();
|
||||
GpuProcessD3D11TextureMap::Init();
|
||||
auto rv = wmf::MediaFoundationInitializer::HasInitialized();
|
||||
if (!rv) {
|
||||
@@ -804,6 +806,7 @@ void GPUParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
|
||||
#if defined(XP_WIN)
|
||||
GpuProcessD3D11TextureMap::Shutdown();
|
||||
GpuProcessD3D11FencesHolderMap::Shutdown();
|
||||
DeviceManagerDx::Shutdown();
|
||||
#endif
|
||||
LayerTreeOwnerTracker::Shutdown();
|
||||
|
||||
@@ -19,50 +19,6 @@ using namespace mozilla::gfx;
|
||||
namespace mozilla {
|
||||
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(
|
||||
const PlanarYCbCrData& aData, TextureFlags aTextureFlags,
|
||||
ID3D11Device* aDevice)
|
||||
@@ -87,8 +43,6 @@ bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
|
||||
}
|
||||
|
||||
ID3D11Texture2D* textureY = dxgiData->GetD3D11Texture(0);
|
||||
ID3D11Texture2D* textureCb = dxgiData->GetD3D11Texture(1);
|
||||
ID3D11Texture2D* textureCr = dxgiData->GetD3D11Texture(2);
|
||||
|
||||
RefPtr<ID3D11Device> device;
|
||||
textureY->GetDevice(getter_AddRefs(device));
|
||||
@@ -96,17 +50,6 @@ bool DXGIYCbCrTextureAllocationHelper::IsCompatible(
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -118,26 +61,13 @@ already_AddRefed<TextureClient> DXGIYCbCrTextureAllocationHelper::Allocate(
|
||||
? DXGI_FORMAT_R8_UNORM
|
||||
: DXGI_FORMAT_R16_UNORM,
|
||||
ySize.width, ySize.height, 1, 1);
|
||||
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
|
||||
D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
|
||||
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());
|
||||
// Use FenceD3D11 for synchronization.
|
||||
newDesc.MiscFlags =
|
||||
D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
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);
|
||||
|
||||
newDesc.Width = cbcrSize.width;
|
||||
|
||||
24
gfx/layers/Fence.cpp
Normal file
24
gfx/layers/Fence.cpp
Normal 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
48
gfx/layers/Fence.h
Normal 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
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "mozilla/layers/CompositableClient.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/layers/D3D11YCbCrImage.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -39,18 +41,6 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
|
||||
DXGIYCbCrTextureData* 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()) {
|
||||
return false;
|
||||
}
|
||||
@@ -59,8 +49,6 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
|
||||
ID3D11Texture2D* textureCb = aTextureData->GetD3D11Texture(1);
|
||||
ID3D11Texture2D* textureCr = aTextureData->GetD3D11Texture(2);
|
||||
|
||||
D3D11MTAutoEnter mtAutoEnter(mt.forget());
|
||||
|
||||
RefPtr<ID3D11DeviceContext> ctx;
|
||||
aDevice->GetImmediateContext(getter_AddRefs(ctx));
|
||||
if (!ctx) {
|
||||
@@ -68,26 +56,12 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
|
||||
return false;
|
||||
}
|
||||
|
||||
// The documentation here seems to suggest using the immediate mode context
|
||||
// on more than one thread is not allowed:
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476891(v=vs.85).aspx
|
||||
// The Debug Layer seems to imply it is though. When the ID3D10Multithread
|
||||
// layer is on. The Enter/Leave of the critical section shouldn't even be
|
||||
// required but were added for extra security.
|
||||
|
||||
{
|
||||
AutoLockD3D11Texture lockY(textureY);
|
||||
AutoLockD3D11Texture lockCr(textureCr);
|
||||
AutoLockD3D11Texture lockCb(textureCb);
|
||||
D3D11MTAutoEnter mtAutoEnter(mt.forget());
|
||||
|
||||
D3D11_BOX box;
|
||||
box.front = box.top = box.left = 0;
|
||||
box.back = 1;
|
||||
box.right = aData.YDataSize().width;
|
||||
box.bottom = aData.YDataSize().height;
|
||||
ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride,
|
||||
0);
|
||||
ctx->UpdateSubresource(textureY, 0, &box, aData.mYChannel, aData.mYStride, 0);
|
||||
|
||||
box.right = aData.CbCrDataSize().width;
|
||||
box.bottom = aData.CbCrDataSize().height;
|
||||
@@ -95,8 +69,17 @@ bool IMFYCbCrImage::CopyDataToTexture(const Data& aData, ID3D11Device* aDevice,
|
||||
aData.mCbCrStride, 0);
|
||||
ctx->UpdateSubresource(textureCr, 0, &box, aData.mCrChannel,
|
||||
aData.mCbCrStride, 0);
|
||||
|
||||
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
|
||||
if (!fenceHolderMap) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return false;
|
||||
}
|
||||
|
||||
aTextureData->mWriteFence->IncrementAndSignal();
|
||||
fenceHolderMap->SetWriteFence(aTextureData->mFencesHolderId,
|
||||
aTextureData->mWriteFence);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -106,6 +89,12 @@ TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* fenceHolderMap = GpuProcessD3D11FencesHolderMap::Get();
|
||||
if (!fenceHolderMap) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetImageDevice();
|
||||
if (!device) {
|
||||
return nullptr;
|
||||
@@ -124,6 +113,10 @@ TextureClient* IMFYCbCrImage::GetD3D11TextureClient(
|
||||
DXGIYCbCrTextureData* data =
|
||||
mTextureClient->GetInternalData()->AsDXGIYCbCrTextureData();
|
||||
|
||||
if (!fenceHolderMap->WaitAllFencesAndForget(data->mFencesHolderId, device)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!CopyDataToTexture(mData, device, data)) {
|
||||
// Failed to copy data
|
||||
mTextureClient = nullptr;
|
||||
|
||||
@@ -86,6 +86,17 @@ GpuProcessTextureId GpuProcessTextureId::GetNext() {
|
||||
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) {
|
||||
switch (aDirection) {
|
||||
case ScrollDirection::eHorizontal:
|
||||
|
||||
@@ -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
|
||||
MOZ_DEFINE_ENUM_CLASS_WITH_BASE(ScrollDirection, uint8_t, (
|
||||
eVertical,
|
||||
|
||||
@@ -223,6 +223,13 @@ DXGITextureHostD3D11* GPUVideoTextureHost::AsDXGITextureHostD3D11() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DXGIYCbCrTextureHostD3D11* GPUVideoTextureHost::AsDXGIYCbCrTextureHostD3D11() {
|
||||
if (EnsureWrappedTextureHost()) {
|
||||
return mWrappedTextureHost->AsDXGIYCbCrTextureHostD3D11();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GPUVideoTextureHost::IsWrappingSurfaceTextureHost() {
|
||||
if (EnsureWrappedTextureHost()) {
|
||||
return EnsureWrappedTextureHost()->IsWrappingSurfaceTextureHost();
|
||||
|
||||
@@ -69,6 +69,8 @@ class GPUVideoTextureHost : public TextureHost {
|
||||
|
||||
DXGITextureHostD3D11* AsDXGITextureHostD3D11() override;
|
||||
|
||||
DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override;
|
||||
|
||||
bool IsWrappingSurfaceTextureHost() override;
|
||||
|
||||
TextureHostType GetTextureHostType() override;
|
||||
|
||||
@@ -63,6 +63,7 @@ class CompositableParentManager;
|
||||
class ReadLockDescriptor;
|
||||
class CompositorBridgeParent;
|
||||
class DXGITextureHostD3D11;
|
||||
class DXGIYCbCrTextureHostD3D11;
|
||||
class SurfaceDescriptor;
|
||||
class HostIPCAllocator;
|
||||
class ISurfaceAllocator;
|
||||
@@ -626,6 +627,10 @@ class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
|
||||
|
||||
virtual DXGITextureHostD3D11* AsDXGITextureHostD3D11() { return nullptr; }
|
||||
|
||||
virtual DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool IsWrappingSurfaceTextureHost() { return false; }
|
||||
|
||||
// Create the corresponding RenderTextureHost type of this texture, and
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <d3d11.h>
|
||||
#include <d3d11_3.h>
|
||||
#include <d3d11_4.h>
|
||||
#include <dxgi1_6.h>
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
@@ -36,7 +37,7 @@ RefPtr<FenceD3D11> FenceD3D11::Create(ID3D11Device* aDevice) {
|
||||
RefPtr<ID3D11Fence> fenceD3D11;
|
||||
d3d11_5->CreateFence(0, D3D11_FENCE_FLAG_SHARED,
|
||||
IID_PPV_ARGS((ID3D11Fence**)getter_AddRefs(fenceD3D11)));
|
||||
if (FAILED(hr)) {
|
||||
if (FAILED(hr) || !fenceD3D11) {
|
||||
gfxCriticalNoteOnce << "Fence creation failed: " << gfx::hexa(hr);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -68,13 +69,45 @@ RefPtr<FenceD3D11> FenceD3D11::CreateFromHandle(
|
||||
|
||||
/* static */
|
||||
bool FenceD3D11::IsSupported(ID3D11Device* aDevice) {
|
||||
MOZ_ASSERT(aDevice);
|
||||
|
||||
if (!aDevice) {
|
||||
return false;
|
||||
}
|
||||
RefPtr<ID3D11Device5> d3d11_5;
|
||||
auto hr =
|
||||
aDevice->QueryInterface(__uuidof(ID3D11Device5), getter_AddRefs(d3d11_5));
|
||||
auto hr = aDevice->QueryInterface((ID3D11Device5**)getter_AddRefs(d3d11_5));
|
||||
if (FAILED(hr)) {
|
||||
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)
|
||||
@@ -84,6 +117,14 @@ FenceD3D11::FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle)
|
||||
|
||||
FenceD3D11::~FenceD3D11() {}
|
||||
|
||||
RefPtr<FenceD3D11> FenceD3D11::CloneFromHandle() {
|
||||
RefPtr<FenceD3D11> fence = FenceD3D11::CreateFromHandle(mHandle);
|
||||
if (fence) {
|
||||
fence->Update(mFenceValue);
|
||||
}
|
||||
return fence;
|
||||
}
|
||||
|
||||
gfx::FenceInfo FenceD3D11::GetFenceInfo() const {
|
||||
return gfx::FenceInfo(mHandle, mFenceValue);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/gfx/FileHandleWrapper.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11Fence;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace layers {
|
||||
|
||||
//
|
||||
@@ -36,17 +35,20 @@ namespace layers {
|
||||
// For waiting fence, Update() is used to update the target value of the
|
||||
// waiting. Wait() is then used to wait for the fence.
|
||||
//
|
||||
class FenceD3D11 final {
|
||||
class FenceD3D11 final : public Fence {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FenceD3D11);
|
||||
|
||||
static RefPtr<FenceD3D11> Create(ID3D11Device* aDevice);
|
||||
static RefPtr<FenceD3D11> CreateFromHandle(
|
||||
RefPtr<gfx::FileHandleWrapper> aHandle);
|
||||
|
||||
FenceD3D11* AsFenceD3D11() override { return this; }
|
||||
|
||||
// Check if ID3D11Device suppors ID3D11Fence creation.
|
||||
static bool IsSupported(ID3D11Device* aDevice);
|
||||
|
||||
RefPtr<FenceD3D11> CloneFromHandle();
|
||||
|
||||
// Updates mSignalFence to incremented value after all previous work has
|
||||
// completed. Used only when FenceD3D11 is created by FenceD3D11::Create().
|
||||
bool IncrementAndSignal();
|
||||
@@ -66,7 +68,7 @@ class FenceD3D11 final {
|
||||
|
||||
protected:
|
||||
explicit FenceD3D11(RefPtr<gfx::FileHandleWrapper>& aHandle);
|
||||
~FenceD3D11();
|
||||
virtual ~FenceD3D11();
|
||||
|
||||
// Device that is used for creating mSignalFence.
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
|
||||
169
gfx/layers/d3d11/GpuProcessD3D11FencesHolderMap.cpp
Normal file
169
gfx/layers/d3d11/GpuProcessD3D11FencesHolderMap.cpp
Normal 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
|
||||
68
gfx/layers/d3d11/GpuProcessD3D11FencesHolderMap.h
Normal file
68
gfx/layers/d3d11/GpuProcessD3D11FencesHolderMap.h
Normal 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 */
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "mozilla/ipc/FileDescriptor.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/D3D11ZeroCopyTextureImage.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11TextureMap.h"
|
||||
#include "mozilla/layers/HelpersD3D11.h"
|
||||
#include "mozilla/layers/VideoProcessorD3D11.h"
|
||||
@@ -661,8 +663,8 @@ DXGIYCbCrTextureData* DXGIYCbCrTextureData::Create(
|
||||
ID3D11Texture2D* aTextureY, ID3D11Texture2D* aTextureCb,
|
||||
ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr,
|
||||
gfx::ColorDepth aColorDepth, YUVColorSpace aYUVColorSpace,
|
||||
gfx::ColorRange aColorRange) {
|
||||
const gfx::ColorDepth aColorDepth, const YUVColorSpace aYUVColorSpace,
|
||||
const gfx::ColorRange aColorRange) {
|
||||
if (!aTextureY || !aTextureCb || !aTextureCr) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -714,13 +716,33 @@ DXGIYCbCrTextureData* DXGIYCbCrTextureData::Create(
|
||||
const RefPtr<gfx::FileHandleWrapper> sharedHandleCr =
|
||||
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<gfx::FileHandleWrapper> handles[3] = {sharedHandleY, sharedHandleCb,
|
||||
sharedHandleCr};
|
||||
|
||||
DXGIYCbCrTextureData* texture =
|
||||
new DXGIYCbCrTextureData(textures, handles, aSize, aSizeY, aSizeCbCr,
|
||||
aColorDepth, aYUVColorSpace, aColorRange);
|
||||
DXGIYCbCrTextureData* texture = new DXGIYCbCrTextureData(
|
||||
textures, handles, aSize, aSizeY, aSizeCbCr, aColorDepth, aYUVColorSpace,
|
||||
aColorRange, fencesHolderId, fence);
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -729,16 +751,29 @@ DXGIYCbCrTextureData::DXGIYCbCrTextureData(
|
||||
RefPtr<gfx::FileHandleWrapper>(aHandles)[3], const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr,
|
||||
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),
|
||||
mSizeY(aSizeY),
|
||||
mSizeCbCr(aSizeCbCr),
|
||||
mColorDepth(aColorDepth),
|
||||
mYUVColorSpace(aYUVColorSpace),
|
||||
mColorRange(aColorRange),
|
||||
mFencesHolderId(aFencesHolderId),
|
||||
mWriteFence(aWriteFence),
|
||||
mD3D11Textures{aD3D11Textures[0], aD3D11Textures[1], aD3D11Textures[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 {
|
||||
aInfo.size = mSize;
|
||||
aInfo.format = gfx::SurfaceFormat::YUV420;
|
||||
@@ -748,9 +783,9 @@ void DXGIYCbCrTextureData::FillInfo(TextureData::Info& aInfo) const {
|
||||
|
||||
void DXGIYCbCrTextureData::SerializeSpecific(
|
||||
SurfaceDescriptorDXGIYCbCr* const aOutDesc) {
|
||||
*aOutDesc = SurfaceDescriptorDXGIYCbCr(mHandles[0], mHandles[1], mHandles[2],
|
||||
mSize, mSizeY, mSizeCbCr, mColorDepth,
|
||||
mYUVColorSpace, mColorRange);
|
||||
*aOutDesc = SurfaceDescriptorDXGIYCbCr(
|
||||
mHandles[0], mHandles[1], mHandles[2], mSize, mSizeY, mSizeCbCr,
|
||||
mColorDepth, mYUVColorSpace, mColorRange, mFencesHolderId);
|
||||
}
|
||||
|
||||
bool DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) {
|
||||
@@ -1325,10 +1360,10 @@ DXGIYCbCrTextureHostD3D11::DXGIYCbCrTextureHostD3D11(
|
||||
mSize(aDescriptor.size()),
|
||||
mSizeY(aDescriptor.sizeY()),
|
||||
mSizeCbCr(aDescriptor.sizeCbCr()),
|
||||
mIsLocked(false),
|
||||
mColorDepth(aDescriptor.colorDepth()),
|
||||
mYUVColorSpace(aDescriptor.yUVColorSpace()),
|
||||
mColorRange(aDescriptor.colorRange()) {
|
||||
mColorRange(aDescriptor.colorRange()),
|
||||
mFencesHolderId(aDescriptor.fencesHolderId()) {
|
||||
mHandles[0] = aDescriptor.handleY();
|
||||
mHandles[1] = aDescriptor.handleCb();
|
||||
mHandles[2] = aDescriptor.handleCr();
|
||||
@@ -1339,7 +1374,8 @@ void DXGIYCbCrTextureHostD3D11::CreateRenderTexture(
|
||||
MOZ_ASSERT(mExternalImageId.isSome());
|
||||
|
||||
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,
|
||||
texture.forget());
|
||||
@@ -1418,6 +1454,30 @@ bool DXGIYCbCrTextureHostD3D11::SupportsExternalCompositing(
|
||||
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,
|
||||
nsIntRegion* aDestRegion,
|
||||
IntPoint* aSrcOffset,
|
||||
|
||||
@@ -35,6 +35,8 @@ class GLBlitHelper;
|
||||
|
||||
namespace layers {
|
||||
|
||||
class FenceD3D11;
|
||||
|
||||
gfx::DeviceResetReason DXGIErrorToDeviceResetReason(HRESULT aError);
|
||||
|
||||
already_AddRefed<TextureHost> CreateTextureHostD3D11(
|
||||
@@ -164,12 +166,15 @@ class DXGIYCbCrTextureData : public TextureData {
|
||||
friend class gl::GLBlitHelper;
|
||||
|
||||
public:
|
||||
static DXGIYCbCrTextureData* Create(
|
||||
ID3D11Texture2D* aTextureCb, ID3D11Texture2D* aTextureY,
|
||||
ID3D11Texture2D* aTextureCr, const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aSizeY, const gfx::IntSize& aSizeCbCr,
|
||||
gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace,
|
||||
gfx::ColorRange aColorRange);
|
||||
static DXGIYCbCrTextureData* Create(ID3D11Texture2D* aTextureCb,
|
||||
ID3D11Texture2D* aTextureY,
|
||||
ID3D11Texture2D* aTextureCr,
|
||||
const gfx::IntSize& aSize,
|
||||
const gfx::IntSize& aSizeY,
|
||||
const gfx::IntSize& aSizeCbCr,
|
||||
const gfx::ColorDepth aColorDepth,
|
||||
const gfx::YUVColorSpace aYUVColorSpace,
|
||||
const gfx::ColorRange aColorRange);
|
||||
|
||||
bool Lock(OpenMode) override { return true; }
|
||||
|
||||
@@ -203,6 +208,8 @@ class DXGIYCbCrTextureData : public TextureData {
|
||||
const gfx::ColorDepth mColorDepth;
|
||||
const gfx::YUVColorSpace mYUVColorSpace;
|
||||
const gfx::ColorRange mColorRange;
|
||||
const GpuProcessFencesHolderId mFencesHolderId;
|
||||
const RefPtr<FenceD3D11> mWriteFence;
|
||||
|
||||
protected:
|
||||
DXGIYCbCrTextureData(RefPtr<ID3D11Texture2D> (&aD3D11Textures)[3],
|
||||
@@ -211,7 +218,10 @@ class DXGIYCbCrTextureData : public TextureData {
|
||||
const gfx::IntSize& aSizeCbCr,
|
||||
const gfx::ColorDepth aColorDepth,
|
||||
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<gfx::FileHandleWrapper> mHandles[3];
|
||||
@@ -435,19 +445,28 @@ class DXGIYCbCrTextureHostD3D11 : public TextureHost {
|
||||
|
||||
bool SupportsExternalCompositing(WebRenderBackend aBackend) override;
|
||||
|
||||
protected:
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
void NotifyNotUsed() override;
|
||||
|
||||
gfx::IntSize mSize;
|
||||
gfx::IntSize mSizeY;
|
||||
gfx::IntSize mSizeCbCr;
|
||||
DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override {
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
// destroyed.
|
||||
RefPtr<gfx::FileHandleWrapper> mHandles[3];
|
||||
bool mIsLocked;
|
||||
gfx::ColorDepth mColorDepth;
|
||||
gfx::YUVColorSpace mYUVColorSpace;
|
||||
gfx::ColorRange mColorRange;
|
||||
bool mIsLocked = false;
|
||||
RefPtr<FenceD3D11> mReadFence;
|
||||
};
|
||||
|
||||
class CompositingRenderTargetD3D11 : public CompositingRenderTarget,
|
||||
|
||||
@@ -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 <>
|
||||
struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
: BitfieldHelper<mozilla::layers::FrameMetrics> {
|
||||
|
||||
@@ -30,6 +30,7 @@ using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
||||
[RefCounted] using mozilla::layers::GpuFence from "mozilla/layers/GpuFence.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::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
||||
using mozilla::layers::SurfaceDescriptorRemoteDecoderId from "mozilla/layers/LayersTypes.h";
|
||||
@@ -60,6 +61,7 @@ namespace layers {
|
||||
ColorDepth colorDepth;
|
||||
YUVColorSpace yUVColorSpace;
|
||||
ColorRange colorRange;
|
||||
GpuProcessFencesHolderId fencesHolderId;
|
||||
};
|
||||
|
||||
[Comparable] struct SurfaceDescriptorMacIOSurface {
|
||||
|
||||
@@ -38,6 +38,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
||||
"d3d11/CompositorD3D11.h",
|
||||
"d3d11/DeviceAttachmentsD3D11.h",
|
||||
"d3d11/FenceD3D11.h",
|
||||
"d3d11/GpuProcessD3D11FencesHolderMap.h",
|
||||
"d3d11/GpuProcessD3D11TextureMap.h",
|
||||
"d3d11/HelpersD3D11.h",
|
||||
"d3d11/ShaderDefinitionsD3D11.h",
|
||||
@@ -47,6 +48,7 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
"d3d11/FenceD3D11.cpp",
|
||||
"d3d11/GpuProcessD3D11FencesHolderMap.cpp",
|
||||
"d3d11/GpuProcessD3D11TextureMap.cpp",
|
||||
"d3d11/TextureD3D11.cpp",
|
||||
"d3d11/TextureHostWrapperD3D11.cpp",
|
||||
@@ -143,6 +145,7 @@ EXPORTS.mozilla.layers += [
|
||||
"D3D11ZeroCopyTextureImage.h",
|
||||
"DirectionUtils.h",
|
||||
"Effects.h",
|
||||
"Fence.h",
|
||||
"GpuFence.h",
|
||||
"ImageDataSerializer.h",
|
||||
"ipc/ActiveResource.h",
|
||||
@@ -368,6 +371,7 @@ UNIFIED_SOURCES += [
|
||||
"CompositorAnimationStorage.cpp",
|
||||
"CompositorTypes.cpp",
|
||||
"Effects.cpp",
|
||||
"Fence.cpp",
|
||||
"FrameMetrics.cpp",
|
||||
"GLImages.cpp",
|
||||
"ImageDataSerializer.cpp",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/layers/AsyncImagePipelineOp.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/layers/RemoteTextureHostWrapper.h"
|
||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||
#include "mozilla/layers/WebRenderImageHost.h"
|
||||
@@ -27,6 +28,11 @@
|
||||
# include "mozilla/layers/TextureHostOGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/layers/FenceD3D11.h"
|
||||
# include "mozilla/layers/TextureD3D11.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@@ -658,7 +664,7 @@ void AsyncImagePipelineManager::HoldExternalImage(
|
||||
void AsyncImagePipelineManager::NotifyPipelinesUpdated(
|
||||
RefPtr<const wr::WebRenderPipelineInfo> aInfo,
|
||||
wr::RenderedFrameId aLatestFrameId,
|
||||
wr::RenderedFrameId aLastCompletedFrameId, UniqueFileHandle&& aFenceFd) {
|
||||
wr::RenderedFrameId aLastCompletedFrameId, RefPtr<Fence>&& aFence) {
|
||||
MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
|
||||
MOZ_ASSERT(mLastCompletedFrameId <= aLastCompletedFrameId.mId);
|
||||
MOZ_ASSERT(aLatestFrameId.IsValid());
|
||||
@@ -673,7 +679,7 @@ void AsyncImagePipelineManager::NotifyPipelinesUpdated(
|
||||
// Move the pending updates into the submitted ones.
|
||||
mRenderSubmittedUpdates.emplace_back(
|
||||
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.
|
||||
@@ -705,7 +711,7 @@ void AsyncImagePipelineManager::ProcessPipelineUpdates() {
|
||||
auto& holder = update.second;
|
||||
const auto& info = holder.mInfo->Raw();
|
||||
|
||||
mReleaseFenceFd = std::move(holder.mFenceFd);
|
||||
mReleaseFence = std::move(holder.mFence);
|
||||
|
||||
for (auto& epoch : info.epochs) {
|
||||
ProcessPipelineRendered(epoch.pipeline_id, epoch.epoch, update.first);
|
||||
@@ -736,8 +742,10 @@ void AsyncImagePipelineManager::ProcessPipelineRendered(
|
||||
for (auto it = holder->mTextureHostsUntilRenderSubmitted.begin();
|
||||
it != firstSubmittedHostToKeep; ++it) {
|
||||
const auto& entry = it;
|
||||
if (entry->mTexture->GetAndroidHardwareBuffer() && mReleaseFenceFd) {
|
||||
entry->mTexture->SetReleaseFence(DuplicateFileHandle(mReleaseFenceFd));
|
||||
if (entry->mTexture->GetAndroidHardwareBuffer() && mReleaseFence &&
|
||||
mReleaseFence->AsFenceFileHandle()) {
|
||||
entry->mTexture->SetReleaseFence(
|
||||
mReleaseFence->AsFenceFileHandle()->DuplicateFileHandle());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -753,6 +761,18 @@ void AsyncImagePipelineManager::ProcessPipelineRendered(
|
||||
holder->mTextureHostsUntilRenderCompleted.begin(),
|
||||
holder->mTextureHostsUntilRenderCompleted.end(),
|
||||
[&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 !=
|
||||
holder->mTextureHostsUntilRenderCompleted.begin()) {
|
||||
std::vector<UniquePtr<ForwardingTextureHost>> hostsUntilCompleted(
|
||||
@@ -824,8 +844,8 @@ wr::Epoch AsyncImagePipelineManager::GetNextImageEpoch() {
|
||||
|
||||
AsyncImagePipelineManager::WebRenderPipelineInfoHolder::
|
||||
WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo,
|
||||
UniqueFileHandle&& aFenceFd)
|
||||
: mInfo(aInfo), mFenceFd(std::move(aFenceFd)) {}
|
||||
RefPtr<Fence>&& aFence)
|
||||
: mInfo(aInfo), mFence(std::move(aFence)) {}
|
||||
|
||||
AsyncImagePipelineManager::WebRenderPipelineInfoHolder::
|
||||
~WebRenderPipelineInfoHolder() = default;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace layers {
|
||||
|
||||
class CompositableHost;
|
||||
class CompositorVsyncScheduler;
|
||||
class Fence;
|
||||
class WebRenderImageHost;
|
||||
class WebRenderTextureHost;
|
||||
|
||||
@@ -71,7 +72,7 @@ class AsyncImagePipelineManager final {
|
||||
void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo,
|
||||
wr::RenderedFrameId aLatestFrameId,
|
||||
wr::RenderedFrameId aLastCompletedFrameId,
|
||||
UniqueFileHandle&& aFenceFd);
|
||||
RefPtr<Fence>&& aFence);
|
||||
|
||||
// This is run on the compositor thread to process mRenderSubmittedUpdates. We
|
||||
// make this public because we need to invoke it from other places.
|
||||
@@ -277,11 +278,11 @@ class AsyncImagePipelineManager final {
|
||||
|
||||
struct WebRenderPipelineInfoHolder {
|
||||
WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo,
|
||||
UniqueFileHandle&& aFenceFd);
|
||||
RefPtr<Fence>&& aFence);
|
||||
~WebRenderPipelineInfoHolder();
|
||||
WebRenderPipelineInfoHolder(WebRenderPipelineInfoHolder&&) = default;
|
||||
RefPtr<const wr::WebRenderPipelineInfo> mInfo;
|
||||
UniqueFileHandle mFenceFd;
|
||||
RefPtr<Fence> mFence;
|
||||
};
|
||||
|
||||
std::vector<std::pair<wr::RenderedFrameId, WebRenderPipelineInfoHolder>>
|
||||
@@ -292,7 +293,7 @@ class AsyncImagePipelineManager final {
|
||||
std::vector<std::pair<wr::RenderedFrameId,
|
||||
std::vector<UniquePtr<ForwardingTextureHost>>>>
|
||||
mTexturesInUseByGPU;
|
||||
UniqueFileHandle mReleaseFenceFd;
|
||||
RefPtr<Fence> mReleaseFence;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
# include "mozilla/layers/TextureHostOGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "mozilla/layers/TextureD3D11.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::layers {
|
||||
|
||||
class ScheduleHandleRenderTextureOps : public wr::NotificationHandler {
|
||||
@@ -119,6 +123,11 @@ void WebRenderTextureHost::NotifyNotUsed() {
|
||||
mWrappedTextureHost->AsTextureHostWrapperD3D11()) {
|
||||
mWrappedTextureHost->NotifyNotUsed();
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
if (auto* host = AsDXGIYCbCrTextureHostD3D11()) {
|
||||
host->NotifyNotUsed();
|
||||
}
|
||||
#endif
|
||||
TextureHost::NotifyNotUsed();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ class WebRenderTextureHost : public TextureHost {
|
||||
return mWrappedTextureHost->AsDXGITextureHostD3D11();
|
||||
}
|
||||
|
||||
DXGIYCbCrTextureHostD3D11* AsDXGIYCbCrTextureHostD3D11() override {
|
||||
return mWrappedTextureHost->AsDXGIYCbCrTextureHostD3D11();
|
||||
}
|
||||
|
||||
bool IsWrappingSurfaceTextureHost() override;
|
||||
|
||||
virtual void PrepareForUse() override;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "Units.h"
|
||||
|
||||
@@ -202,13 +203,7 @@ class RenderCompositor {
|
||||
}
|
||||
virtual bool MaybeProcessScreenshotQueue() { return false; }
|
||||
|
||||
// Returns FileDescriptor of release fence.
|
||||
// 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 RefPtr<layers::Fence> GetAndResetReleaseFence() { return nullptr; }
|
||||
|
||||
virtual bool IsPaused() { return false; }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/StackArray.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
#include "mozilla/layers/HelpersD3D11.h"
|
||||
#include "mozilla/layers/SyncObject.h"
|
||||
@@ -124,11 +125,14 @@ bool RenderCompositorANGLE::Initialize(nsACString& aError) {
|
||||
MOZ_ASSERT(mEGLConfig);
|
||||
|
||||
mDevice = GetDeviceOfEGLDisplay(aError);
|
||||
|
||||
if (!mDevice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layers::FenceD3D11::IsSupported(mDevice)) {
|
||||
mFence = layers::FenceD3D11::Create(mDevice);
|
||||
}
|
||||
|
||||
mDevice->GetImmediateContext(getter_AddRefs(mCtx));
|
||||
if (!mCtx) {
|
||||
aError.Assign("RcANGLE(get immediate context failed)"_ns);
|
||||
@@ -462,6 +466,10 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
|
||||
RenderedFrameId frameId = GetNextRenderFrameId();
|
||||
InsertGraphicsCommandsFinishedWaitQuery(frameId);
|
||||
|
||||
if (mFence) {
|
||||
mFence->IncrementAndSignal();
|
||||
}
|
||||
|
||||
if (!UseCompositor()) {
|
||||
auto start = TimeStamp::Now();
|
||||
if (auto* fxrHandler = mWidget->AsWindows()->GetFxrOutputHandler()) {
|
||||
@@ -564,6 +572,14 @@ RenderedFrameId RenderCompositorANGLE::EndFrame(
|
||||
return frameId;
|
||||
}
|
||||
|
||||
RefPtr<layers::Fence> RenderCompositorANGLE::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> fence;
|
||||
if (mFence) {
|
||||
fence = mFence->CloneFromHandle();
|
||||
}
|
||||
return fence.forget();
|
||||
}
|
||||
|
||||
bool RenderCompositorANGLE::WaitForGPU() {
|
||||
// Note: this waits on the query we inserted in the previous frame,
|
||||
// not the one we just inserted now. Example:
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace gl {
|
||||
class GLLibraryEGL;
|
||||
} // namespace gl
|
||||
|
||||
namespace layers {
|
||||
class FenceD3D11;
|
||||
} // namespace layers
|
||||
|
||||
namespace wr {
|
||||
|
||||
class DCLayerTree;
|
||||
@@ -113,6 +117,8 @@ class RenderCompositorANGLE final : public RenderCompositor {
|
||||
bool RequestFullRender() override;
|
||||
uint32_t GetMaxPartialPresentRects() override;
|
||||
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence() override;
|
||||
|
||||
bool MaybeReadback(const gfx::IntSize& aReadbackSize,
|
||||
const wr::ImageFormat& aReadbackFormat,
|
||||
const Range<uint8_t>& aReadbackBuffer,
|
||||
@@ -169,6 +175,7 @@ class RenderCompositorANGLE final : public RenderCompositor {
|
||||
bool mFirstPresent = true;
|
||||
// Wether we're currently using alpha.
|
||||
bool mSwapChainUsingAlpha = false;
|
||||
RefPtr<layers::FenceD3D11> mFence;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -123,7 +123,7 @@ RenderedFrameId RenderCompositorEGL::EndFrame(
|
||||
if (sync) {
|
||||
int fenceFd = egl->fDupNativeFenceFDANDROID(sync);
|
||||
if (fenceFd >= 0) {
|
||||
mReleaseFenceFd = UniqueFileHandle(fenceFd);
|
||||
mReleaseFence = new layers::FenceFileHandle(UniqueFileHandle(fenceFd));
|
||||
}
|
||||
egl->fDestroySync(sync);
|
||||
sync = nullptr;
|
||||
@@ -259,12 +259,12 @@ void RenderCompositorEGL::DestroyEGLSurface() {
|
||||
}
|
||||
}
|
||||
|
||||
UniqueFileHandle RenderCompositorEGL::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> RenderCompositorEGL::GetAndResetReleaseFence() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFenceFd);
|
||||
return std::move(mReleaseFenceFd);
|
||||
MOZ_ASSERT(!layers::AndroidHardwareBufferApi::Get() || mReleaseFence);
|
||||
return mReleaseFence.forget();
|
||||
#else
|
||||
return UniqueFileHandle();
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class RenderCompositorEGL : public RenderCompositor {
|
||||
void SetBufferDamageRegion(const wr::DeviceIntRect* aRects,
|
||||
size_t aNumRects) override;
|
||||
|
||||
UniqueFileHandle GetAndResetReleaseFence() override;
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence() override;
|
||||
|
||||
protected:
|
||||
EGLSurface CreateEGLSurface();
|
||||
@@ -66,7 +66,7 @@ class RenderCompositorEGL : public RenderCompositor {
|
||||
// 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.
|
||||
UniqueFileHandle mReleaseFenceFd;
|
||||
RefPtr<layers::Fence> mReleaseFence;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/layers/FenceD3D11.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11TextureMap.h"
|
||||
#include "mozilla/layers/GpuProcessD3D11FencesHolderMap.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -472,8 +473,10 @@ bool RenderDXGITextureHost::SyncObjectNeeded() {
|
||||
|
||||
RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
|
||||
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
|
||||
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth,
|
||||
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr)
|
||||
const gfx::YUVColorSpace aYUVColorSpace, const gfx::ColorDepth aColorDepth,
|
||||
const gfx::ColorRange aColorRange, const gfx::IntSize aSizeY,
|
||||
const gfx::IntSize aSizeCbCr,
|
||||
const layers::GpuProcessFencesHolderId aFencesHolderId)
|
||||
: mHandles{aHandles[0], aHandles[1], aHandles[2]},
|
||||
mSurfaces{0},
|
||||
mStreams{0},
|
||||
@@ -483,7 +486,7 @@ RenderDXGIYCbCrTextureHost::RenderDXGIYCbCrTextureHost(
|
||||
mColorRange(aColorRange),
|
||||
mSizeY(aSizeY),
|
||||
mSizeCbCr(aSizeCbCr),
|
||||
mLocked(false) {
|
||||
mFencesHolderId(aFencesHolderId) {
|
||||
MOZ_COUNT_CTOR_INHERITED(RenderDXGIYCbCrTextureHost, RenderTextureHost);
|
||||
// Assume the chroma planes are rounded up if the luma plane is odd sized.
|
||||
MOZ_ASSERT((mSizeCbCr.width == mSizeY.width ||
|
||||
@@ -631,25 +634,20 @@ bool RenderDXGIYCbCrTextureHost::EnsureD3D11Texture2D(ID3D11Device* aDevice) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mTextures[i]->QueryInterface(
|
||||
(IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutexs[i]));
|
||||
}
|
||||
mDevice = aDevice;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderDXGIYCbCrTextureHost::LockInternal() {
|
||||
if (!mLocked) {
|
||||
if (mKeyedMutexs[0]) {
|
||||
for (const auto& mutex : mKeyedMutexs) {
|
||||
HRESULT hr = mutex->AcquireSync(0, 10000);
|
||||
if (hr != S_OK) {
|
||||
gfxCriticalError()
|
||||
<< "RenderDXGIYCbCrTextureHost AcquireSync timeout, hr="
|
||||
<< gfx::hexa(hr);
|
||||
auto* fenceHolderMap = layers::GpuProcessD3D11FencesHolderMap::Get();
|
||||
if (!fenceHolderMap) {
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!fenceHolderMap->WaitWriteFence(mFencesHolderId, mDevice)) {
|
||||
return false;
|
||||
}
|
||||
mLocked = true;
|
||||
}
|
||||
@@ -688,11 +686,6 @@ wr::WrExternalImage RenderDXGIYCbCrTextureHost::Lock(uint8_t aChannelIndex,
|
||||
|
||||
void RenderDXGIYCbCrTextureHost::Unlock() {
|
||||
if (mLocked) {
|
||||
if (mKeyedMutexs[0]) {
|
||||
for (const auto& mutex : mKeyedMutexs) {
|
||||
mutex->ReleaseSync(0);
|
||||
}
|
||||
}
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
@@ -736,7 +729,6 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mTextureHandles[i] = 0;
|
||||
mTextures[i] = nullptr;
|
||||
mKeyedMutexs[i] = nullptr;
|
||||
|
||||
if (mSurfaces[i]) {
|
||||
egl->fDestroySurface(mSurfaces[i]);
|
||||
@@ -748,6 +740,7 @@ void RenderDXGIYCbCrTextureHost::DeleteTextureHandle() {
|
||||
}
|
||||
}
|
||||
}
|
||||
mDevice = nullptr;
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -139,8 +139,10 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
public:
|
||||
explicit RenderDXGIYCbCrTextureHost(
|
||||
RefPtr<gfx::FileHandleWrapper> (&aHandles)[3],
|
||||
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorDepth aColorDepth,
|
||||
gfx::ColorRange aColorRange, gfx::IntSize aSizeY, gfx::IntSize aSizeCbCr);
|
||||
const gfx::YUVColorSpace aYUVColorSpace,
|
||||
const gfx::ColorDepth aColorDepth, const gfx::ColorRange aColorRange,
|
||||
const gfx::IntSize aSizeY, const gfx::IntSize aSizeCbCr,
|
||||
const layers::GpuProcessFencesHolderId aFencesHolderId);
|
||||
|
||||
RenderDXGIYCbCrTextureHost* AsRenderDXGIYCbCrTextureHost() override {
|
||||
return this;
|
||||
@@ -200,7 +202,7 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
|
||||
RefPtr<gfx::FileHandleWrapper> mHandles[3];
|
||||
RefPtr<ID3D11Texture2D> mTextures[3];
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutexs[3];
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
|
||||
EGLSurface mSurfaces[3];
|
||||
EGLStreamKHR mStreams[3];
|
||||
@@ -212,13 +214,14 @@ class RenderDXGIYCbCrTextureHost final : public RenderTextureHostSWGL {
|
||||
RefPtr<ID3D11DeviceContext> mDeviceContext;
|
||||
RefPtr<ID3D11Texture2D> mCpuTexture[3];
|
||||
|
||||
gfx::YUVColorSpace mYUVColorSpace;
|
||||
gfx::ColorDepth mColorDepth;
|
||||
gfx::ColorRange mColorRange;
|
||||
gfx::IntSize mSizeY;
|
||||
gfx::IntSize mSizeCbCr;
|
||||
const gfx::YUVColorSpace mYUVColorSpace;
|
||||
const gfx::ColorDepth mColorDepth;
|
||||
const gfx::ColorRange mColorRange;
|
||||
const gfx::IntSize mSizeY;
|
||||
const gfx::IntSize mSizeCbCr;
|
||||
const layers::GpuProcessFencesHolderId mFencesHolderId;
|
||||
|
||||
bool mLocked;
|
||||
bool mLocked = false;
|
||||
};
|
||||
|
||||
} // namespace wr
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorManagerParent.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/layers/WebRenderBridgeParent.h"
|
||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||
#include "mozilla/layers/SurfacePool.h"
|
||||
@@ -866,10 +867,10 @@ void RenderThread::UpdateAndRender(
|
||||
renderer->GetCompositorBridge(), info, aStartId,
|
||||
aStartTime, start, end, aRender, *aStats));
|
||||
|
||||
UniqueFileHandle fenceFd;
|
||||
RefPtr<layers::Fence> fence;
|
||||
|
||||
if (latestFrameId.IsValid()) {
|
||||
fenceFd = renderer->GetAndResetReleaseFence();
|
||||
fence = renderer->GetAndResetReleaseFence();
|
||||
|
||||
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
||||
// 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.
|
||||
MOZ_ASSERT(pipelineMgr);
|
||||
pipelineMgr->NotifyPipelinesUpdated(info, latestFrameId, lastCompletedFrameId,
|
||||
std::move(fenceFd));
|
||||
std::move(fence));
|
||||
}
|
||||
|
||||
void RenderThread::Pause(wr::WindowId aWindowId) {
|
||||
|
||||
@@ -36,6 +36,7 @@ class GLContext;
|
||||
} // namespace gl
|
||||
namespace layers {
|
||||
class CompositorBridgeParent;
|
||||
class Fence;
|
||||
class ShaderProgramOGLsHolder;
|
||||
class SurfacePool;
|
||||
} // namespace layers
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/layers/CompositorBridgeParent.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/Fence.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/ProfilerScreenshots.h"
|
||||
#include "mozilla/webrender/RenderCompositor.h"
|
||||
@@ -280,7 +281,7 @@ void RendererOGL::WaitForGPU() {
|
||||
}
|
||||
}
|
||||
|
||||
UniqueFileHandle RendererOGL::GetAndResetReleaseFence() {
|
||||
RefPtr<layers::Fence> RendererOGL::GetAndResetReleaseFence() {
|
||||
return mCompositor->GetAndResetReleaseFence();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ class GLContext;
|
||||
|
||||
namespace layers {
|
||||
class CompositorBridgeParent;
|
||||
class Fence;
|
||||
class SyncObjectHost;
|
||||
} // namespace layers
|
||||
|
||||
@@ -70,7 +71,7 @@ class RendererOGL {
|
||||
void WaitForGPU();
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
UniqueFileHandle GetAndResetReleaseFence();
|
||||
RefPtr<layers::Fence> GetAndResetReleaseFence();
|
||||
|
||||
/// This can be called on the render thread only.
|
||||
RenderedFrameId GetLastCompletedFrameId();
|
||||
|
||||
Reference in New Issue
Block a user