Bug 1357299 - P9: Do the refactoring for SyncObject. v2. r=mattwoodrow,dvander

The MLGDeviceD3D11, CompositorD3D11 and TextureClient use the same synchronization mechanism.
Create the new SyncObjectClient/Host types for reusing code.

Add SyncObject.cpp/h and create two new data types: SyncObjectClient and SyncObjectHost.
The SyncObjectClient is used for the TextureClient synchronization at client side.
The SyncObjectHost is used for the TextureHost synchronization in renderers such
as MLGDeviceD3D11 and CompositorD3D11.

MozReview-Commit-ID: 3l56WK1aZ15
This commit is contained in:
JerryShih 2017-08-07 18:15:23 +08:00
parent 384661a8d6
commit 50bd333891
7 changed files with 260 additions and 86 deletions

49
gfx/layers/SyncObject.cpp Normal file
View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "SyncObject.h"
#ifdef XP_WIN
#include "mozilla/layers/TextureD3D11.h"
#endif
namespace mozilla {
namespace layers {
already_AddRefed<SyncObjectHost>
SyncObjectHost::CreateSyncObjectHost(
#ifdef XP_WIN
ID3D11Device* aDevice
#endif
)
{
#ifdef XP_WIN
return MakeAndAddRef<SyncObjectD3D11Host>(aDevice);
#else
return nullptr;
#endif
}
already_AddRefed<SyncObjectClient>
SyncObjectClient::CreateSyncObjectClient(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice
#endif
)
{
if (!aHandle) {
return nullptr;
}
#ifdef XP_WIN
return MakeAndAddRef<SyncObjectD3D11Client>(aHandle, aDevice);
#else
MOZ_ASSERT_UNREACHABLE();
return nullptr;
#endif
}
} // namespace layers
} // namespace mozilla

73
gfx/layers/SyncObject.h Normal file
View File

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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_LAYERS_SYNCOBJECT_H
#define MOZILLA_GFX_LAYERS_SYNCOBJECT_H
#include "mozilla/RefCounted.h"
struct ID3D11Device;
namespace mozilla {
namespace layers {
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
class SyncObjectHost : public RefCounted<SyncObjectHost>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectHost)
virtual ~SyncObjectHost() { }
static already_AddRefed<SyncObjectHost> CreateSyncObjectHost(
#ifdef XP_WIN
ID3D11Device* aDevice = nullptr
#endif
);
virtual bool Init() = 0;
virtual SyncHandle GetSyncHandle() = 0;
virtual bool Synchronize() = 0;
protected:
SyncObjectHost() { }
};
class SyncObjectClient : public RefCounted<SyncObjectClient>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObjectClient)
virtual ~SyncObjectClient() { }
static already_AddRefed<SyncObjectClient> CreateSyncObjectClient(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice = nullptr
#endif
);
enum class SyncType {
D3D11,
};
virtual SyncType GetSyncType() = 0;
virtual void Synchronize() = 0;
virtual bool IsSyncObjectValid() = 0;
protected:
SyncObjectClient() { }
};
} // namespace layers
} // namespace mozilla
#endif //MOZILLA_GFX_LAYERS_SYNCOBJECT_H

View File

@ -1745,25 +1745,6 @@ UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData)
return true;
}
already_AddRefed<SyncObject>
SyncObject::CreateSyncObject(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice
#endif
)
{
if (!aHandle) {
return nullptr;
}
#ifdef XP_WIN
return MakeAndAddRef<SyncObjectD3D11>(aHandle, aDevice);
#else
MOZ_ASSERT_UNREACHABLE();
return nullptr;
#endif
}
already_AddRefed<TextureClient>
TextureClient::CreateWithData(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
{

View File

@ -93,36 +93,6 @@ enum TextureAllocationFlags {
ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
};
#ifdef XP_WIN
typedef void* SyncHandle;
#else
typedef uintptr_t SyncHandle;
#endif // XP_WIN
class SyncObject : public RefCounted<SyncObject>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SyncObject)
virtual ~SyncObject() { }
static already_AddRefed<SyncObject> CreateSyncObject(SyncHandle aHandle
#ifdef XP_WIN
, ID3D11Device* aDevice = nullptr
#endif
);
enum class SyncType {
D3D11,
};
virtual SyncType GetSyncType() = 0;
virtual void FinalizeFrame() = 0;
virtual bool IsSyncObjectValid() = 0;
protected:
SyncObject() { }
};
/**
* This class may be used to asynchronously receive an update when the content
* drawn to this texture client is available for reading in CPU memory. This

View File

@ -1525,17 +1525,6 @@ CompositingRenderTargetD3D11::GetSize() const
return TextureSourceD3D11::GetSize();
}
SyncObjectD3D11::SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice)
: mSyncHandle(aSyncHandle)
{
if (!aDevice) {
mD3D11Device = DeviceManagerDx::Get()->GetContentDevice();
return;
}
mD3D11Device = aDevice;
}
static inline bool
ShouldDevCrashOnSyncInitFailure()
{
@ -1551,18 +1540,107 @@ ShouldDevCrashOnSyncInitFailure()
!DeviceManagerDx::Get()->HasDeviceReset();
}
SyncObjectD3D11Host::SyncObjectD3D11Host(ID3D11Device* aDevice)
: mSyncHandle(0)
, mDevice(aDevice)
{
MOZ_ASSERT(aDevice);
}
bool
SyncObjectD3D11::Init()
SyncObjectD3D11Host::Init()
{
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, 1, 1, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> texture;
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture));
if (FAILED(hr) || !texture) {
gfxWarning() << "Could not create a sync texture: " << gfx::hexa(hr);
return false;
}
hr = texture->QueryInterface((IDXGIResource**)getter_AddRefs(mSyncTexture));
if (FAILED(hr) || !mSyncTexture) {
gfxWarning() << "Could not QI sync texture: " << gfx::hexa(hr);
return false;
}
hr = mSyncTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
if (FAILED(hr) || !mKeyedMutex) {
gfxWarning() << "Could not QI keyed-mutex: " << gfx::hexa(hr);
return false;
}
hr = mSyncTexture->GetSharedHandle(&mSyncHandle);
if (FAILED(hr) || !mSyncHandle) {
NS_DispatchToMainThread(NS_NewRunnableFunction("layers::SyncObjectD3D11Renderer::Init",
[] () -> void {
Accumulate(Telemetry::D3D11_SYNC_HANDLE_FAILURE, 1);
}));
gfxWarning() << "Could not get sync texture shared handle: " << gfx::hexa(hr);
return false;
}
return true;
}
SyncHandle
SyncObjectD3D11Host::GetSyncHandle()
{
return mSyncHandle;
}
bool
SyncObjectD3D11Host::Synchronize()
{
HRESULT hr;
AutoTextureLock lock(mKeyedMutex, hr, 10000);
if (hr == WAIT_TIMEOUT) {
hr = mDevice->GetDeviceRemovedReason();
if (hr == S_OK) {
// There is no driver-removed event. Crash with this timeout.
MOZ_CRASH("GFX: D3D11 normal status timeout");
}
// Since the timeout is related to the driver-removed. Return false for
// error handling.
gfxCriticalNote << "GFX: D3D11 timeout with device-removed:" << gfx::hexa(hr);
return false;
}
if (hr == WAIT_ABANDONED) {
gfxCriticalNote << "GFX: AL_D3D11 abandoned sync";
}
return true;
}
SyncObjectD3D11Client::SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice)
: mSyncHandle(aSyncHandle)
{
if (!aDevice) {
mDevice = DeviceManagerDx::Get()->GetContentDevice();
return;
}
mDevice = aDevice;
}
bool
SyncObjectD3D11Client::Init()
{
if (mKeyedMutex) {
return true;
}
HRESULT hr = mD3D11Device->OpenSharedResource(
HRESULT hr = mDevice->OpenSharedResource(
mSyncHandle,
__uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)getter_AddRefs(mD3D11Texture));
if (FAILED(hr) || !mD3D11Texture) {
(void**)(ID3D11Texture2D**)getter_AddRefs(mSyncTexture));
if (FAILED(hr) || !mSyncTexture) {
gfxCriticalNote << "Failed to OpenSharedResource for SyncObjectD3D11: " << hexa(hr);
if (ShouldDevCrashOnSyncInitFailure()) {
gfxDevCrash(LogReason::D3D11FinalizeFrame) << "Without device reset: " << hexa(hr);
@ -1570,10 +1648,10 @@ SyncObjectD3D11::Init()
return false;
}
hr = mD3D11Texture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
hr = mSyncTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(mKeyedMutex));
if (FAILED(hr) || !mKeyedMutex) {
// Leave both the critical error and MOZ_CRASH for now; the critical error lets
// us "save" the hr value. We will probably eventuall replace this with gfxDevCrash.
// us "save" the hr value. We will probably eventually replace this with gfxDevCrash.
gfxCriticalError() << "Failed to get KeyedMutex (2): " << hexa(hr);
MOZ_CRASH("GFX: Cannot get D3D11 KeyedMutex");
}
@ -1582,25 +1660,25 @@ SyncObjectD3D11::Init()
}
void
SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
SyncObjectD3D11Client::RegisterTexture(ID3D11Texture2D* aTexture)
{
mD3D11SyncedTextures.push_back(aTexture);
mSyncedTextures.push_back(aTexture);
}
bool
SyncObjectD3D11::IsSyncObjectValid()
SyncObjectD3D11Client::IsSyncObjectValid()
{
RefPtr<ID3D11Device> dev = DeviceManagerDx::Get()->GetContentDevice();
if (!dev || (NS_IsMainThread() && dev != mD3D11Device)) {
if (!dev || (NS_IsMainThread() && dev != mDevice)) {
return false;
}
return true;
}
void
SyncObjectD3D11::FinalizeFrame()
SyncObjectD3D11Client::Synchronize()
{
if (!mD3D11SyncedTextures.size()) {
if (!mSyncedTextures.size()) {
return;
}
if (!Init()) {
@ -1623,7 +1701,7 @@ SyncObjectD3D11::FinalizeFrame()
box.back = box.bottom = box.right = 1;
RefPtr<ID3D11Device> dev;
mD3D11Texture->GetDevice(getter_AddRefs(dev));
mSyncTexture->GetDevice(getter_AddRefs(dev));
if (dev == DeviceManagerDx::Get()->GetContentDevice()) {
if (DeviceManagerDx::Get()->HasDeviceReset()) {
@ -1631,7 +1709,7 @@ SyncObjectD3D11::FinalizeFrame()
}
}
if (dev != mD3D11Device) {
if (dev != mDevice) {
gfxWarning() << "Attempt to sync texture from invalid device.";
return;
}
@ -1639,11 +1717,11 @@ SyncObjectD3D11::FinalizeFrame()
RefPtr<ID3D11DeviceContext> ctx;
dev->GetImmediateContext(getter_AddRefs(ctx));
for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) {
ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box);
for (auto iter = mSyncedTextures.begin(); iter != mSyncedTextures.end(); iter++) {
ctx->CopySubresourceRegion(mSyncTexture, 0, 0, 0, 0, *iter, 0, &box);
}
mD3D11SyncedTextures.clear();
mSyncedTextures.clear();
}
uint32_t

View File

@ -440,26 +440,47 @@ private:
RefPtr<ID3D11RenderTargetView> mRTView;
};
class SyncObjectD3D11 : public SyncObject
class SyncObjectD3D11Host : public SyncObjectHost
{
public:
explicit SyncObjectD3D11(SyncHandle aSyncHandle, ID3D11Device* aDevice);
virtual void FinalizeFrame();
virtual bool IsSyncObjectValid();
explicit SyncObjectD3D11Host(ID3D11Device* aDevice);
virtual SyncType GetSyncType() { return SyncType::D3D11; }
virtual bool Init() override;
virtual SyncHandle GetSyncHandle() override;
virtual bool Synchronize() override;
private:
virtual ~SyncObjectD3D11Host() { }
SyncHandle mSyncHandle;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDXGIResource> mSyncTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
};
class SyncObjectD3D11Client : public SyncObjectClient
{
public:
explicit SyncObjectD3D11Client(SyncHandle aSyncHandle, ID3D11Device* aDevice);
virtual void Synchronize() override;
virtual bool IsSyncObjectValid() override;
virtual SyncType GetSyncType() override { return SyncType::D3D11; }
void RegisterTexture(ID3D11Texture2D* aTexture);
private:
bool Init();
private:
SyncHandle mSyncHandle;
RefPtr<ID3D11Device> mD3D11Device;
RefPtr<ID3D11Texture2D> mD3D11Texture;
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11Texture2D> mSyncTexture;
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
std::vector<ID3D11Texture2D*> mD3D11SyncedTextures;
std::vector<ID3D11Texture2D*> mSyncedTextures;
};
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)

View File

@ -224,6 +224,7 @@ EXPORTS.mozilla.layers += [
'ShareableCanvasRenderer.h',
'SourceSurfaceSharedData.h',
'SourceSurfaceVolatileData.h',
'SyncObject.h',
'TextureSourceProvider.h',
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
@ -456,6 +457,7 @@ UNIFIED_SOURCES += [
'ShareableCanvasRenderer.cpp',
'SourceSurfaceSharedData.cpp',
'SourceSurfaceVolatileData.cpp',
'SyncObject.cpp',
'TextureSourceProvider.cpp',
'TextureWrapperImage.cpp',
'wr/AsyncImagePipelineManager.cpp',