mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1088414: Use a single synchronization texture for D3D11. r=jrmuizel
This patch adds a cross platform 'sync object' that is used to synchronize the drawing of individual textures. For the D3D11 implementation all textures that are written to will have one pixel copied into the D3D11 sync texture while holding its lock. The compositor will then, before composition acquire and release sync once, this should ensure all drawing on the content side has completed.
This commit is contained in:
parent
cee30634bf
commit
b24ee3fde9
@ -815,6 +815,7 @@ struct ParamTraits<mozilla::layers::TextureFactoryIdentifier>
|
||||
WriteParam(aMsg, aParam.mMaxTextureSize);
|
||||
WriteParam(aMsg, aParam.mSupportsTextureBlitting);
|
||||
WriteParam(aMsg, aParam.mSupportsPartialUploads);
|
||||
WriteParam(aMsg, aParam.mSyncHandle);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
@ -824,7 +825,8 @@ struct ParamTraits<mozilla::layers::TextureFactoryIdentifier>
|
||||
ReadParam(aMsg, aIter, &supportedBlendModes) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mMaxTextureSize) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mSupportsTextureBlitting) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mSupportsPartialUploads);
|
||||
ReadParam(aMsg, aIter, &aResult->mSupportsPartialUploads) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mSyncHandle);
|
||||
aResult->mSupportedBlendModes.deserialize(supportedBlendModes);
|
||||
return result;
|
||||
}
|
||||
|
@ -158,6 +158,12 @@ MOZ_BEGIN_ENUM_CLASS(DeprecatedTextureHostFlags, uint8_t)
|
||||
MOZ_END_ENUM_CLASS(DeprecatedTextureHostFlags)
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DeprecatedTextureHostFlags)
|
||||
|
||||
#ifdef XP_WIN
|
||||
typedef void* SyncHandle;
|
||||
#else
|
||||
typedef uintptr_t SyncHandle;
|
||||
#endif // XP_WIN
|
||||
|
||||
/**
|
||||
* Sent from the compositor to the content-side LayerManager, includes properties
|
||||
* of the compositor and should (in the future) include information about what
|
||||
@ -171,18 +177,21 @@ struct TextureFactoryIdentifier
|
||||
int32_t mMaxTextureSize;
|
||||
bool mSupportsTextureBlitting;
|
||||
bool mSupportsPartialUploads;
|
||||
SyncHandle mSyncHandle;
|
||||
|
||||
explicit TextureFactoryIdentifier(LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
|
||||
GeckoProcessType aParentProcessId = GeckoProcessType_Default,
|
||||
int32_t aMaxTextureSize = 4096,
|
||||
bool aSupportsTextureBlitting = false,
|
||||
bool aSupportsPartialUploads = false)
|
||||
bool aSupportsPartialUploads = false,
|
||||
SyncHandle aSyncHandle = 0)
|
||||
: mParentBackend(aLayersBackend)
|
||||
, mParentProcessId(aParentProcessId)
|
||||
, mSupportedBlendModes(gfx::CompositionOp::OP_OVER)
|
||||
, mMaxTextureSize(aMaxTextureSize)
|
||||
, mSupportsTextureBlitting(aSupportsTextureBlitting)
|
||||
, mSupportsPartialUploads(aSupportsPartialUploads)
|
||||
, mSyncHandle(aSyncHandle)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -112,6 +112,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
if (updated) {
|
||||
GetForwarder()->UpdatedTexture(this, mBuffer, nullptr);
|
||||
GetForwarder()->UseTexture(this, mBuffer);
|
||||
mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -529,6 +529,10 @@ ClientLayerManager::StopFrameTimeRecording(uint32_t aStartIndex,
|
||||
void
|
||||
ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
|
||||
{
|
||||
if (mForwarder->GetSyncObject()) {
|
||||
mForwarder->GetSyncObject()->FinalizeFrame();
|
||||
}
|
||||
|
||||
mPhase = PHASE_FORWARD;
|
||||
|
||||
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
|
||||
|
@ -255,10 +255,13 @@ ContentClientRemoteBuffer::EndPaint(nsTArray<ReadbackProcessor::Update>* aReadba
|
||||
}
|
||||
|
||||
mTextureClient->Unlock();
|
||||
mTextureClient->SyncWithObject(mForwarder->GetSyncObject());
|
||||
}
|
||||
if (mTextureClientOnWhite && mTextureClientOnWhite->IsLocked()) {
|
||||
mTextureClientOnWhite->Unlock();
|
||||
mTextureClientOnWhite->SyncWithObject(mForwarder->GetSyncObject());
|
||||
}
|
||||
|
||||
ContentClientRemote::EndPaint(aReadbackUpdates);
|
||||
}
|
||||
|
||||
|
@ -242,6 +242,9 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
||||
|
||||
mLastPaintedImageSerial = image->GetSerial();
|
||||
aContainer->NotifyPaintedImage(image);
|
||||
|
||||
texture->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -886,5 +886,21 @@ SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescripto
|
||||
return true;
|
||||
}
|
||||
|
||||
TemporaryRef<SyncObject>
|
||||
SyncObject::CreateSyncObject(SyncHandle aHandle)
|
||||
{
|
||||
if (!aHandle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
RefPtr<SyncObject> syncObject = new SyncObjectD3D11(aHandle);
|
||||
return syncObject;
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE();
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "mozilla/ipc/Shmem.h" // for Shmem
|
||||
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
@ -73,6 +74,31 @@ enum TextureAllocationFlags {
|
||||
ALLOC_CLEAR_BUFFER_WHITE = 2
|
||||
};
|
||||
|
||||
#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 TemporaryRef<SyncObject> CreateSyncObject(SyncHandle aHandle);
|
||||
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS(SyncType)
|
||||
D3D11,
|
||||
MOZ_END_NESTED_ENUM_CLASS(SyncType)
|
||||
|
||||
virtual SyncType GetSyncType() = 0;
|
||||
virtual void FinalizeFrame() = 0;
|
||||
|
||||
protected:
|
||||
SyncObject() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for TextureClients that can be updated using YCbCr data.
|
||||
*/
|
||||
@ -433,6 +459,8 @@ public:
|
||||
virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) {
|
||||
mReadbackSink = aReadbackSink;
|
||||
}
|
||||
|
||||
virtual void SyncWithObject(SyncObject* aSyncObject) { }
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -66,6 +66,7 @@ struct DeviceAttachmentsD3D11
|
||||
RefPtr<ID3D11BlendState> mNonPremulBlendState;
|
||||
RefPtr<ID3D11BlendState> mComponentBlendState;
|
||||
RefPtr<ID3D11BlendState> mDisabledBlendState;
|
||||
RefPtr<IDXGIResource> mSyncTexture;
|
||||
};
|
||||
|
||||
CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
|
||||
@ -273,6 +274,24 @@ CompositorD3D11::Initialize()
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = texture->QueryInterface((IDXGIResource**)byRef(mAttachments->mSyncTexture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIDevice> dxgiDevice;
|
||||
@ -377,6 +396,13 @@ CompositorD3D11::GetTextureFactoryIdentifier()
|
||||
ident.mMaxTextureSize = GetMaxTextureSize();
|
||||
ident.mParentProcessId = XRE_GetProcessType();
|
||||
ident.mParentBackend = LayersBackend::LAYERS_D3D11;
|
||||
if (mAttachments->mSyncTexture) {
|
||||
HRESULT hr = mAttachments->mSyncTexture->GetSharedHandle(&ident.mSyncHandle);
|
||||
if (FAILED(hr) || !ident.mSyncHandle) {
|
||||
gfxCriticalError() << "Failed to get SharedHandle for sync texture. Result: " << hr;
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
return ident;
|
||||
}
|
||||
|
||||
@ -882,6 +908,13 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
|
||||
// ClearRect will set the correct blend state for us.
|
||||
ClearRect(Rect(invalidRect.x, invalidRect.y, invalidRect.width, invalidRect.height));
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
mAttachments->mSyncTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
|
||||
|
||||
MOZ_ASSERT(mutex);
|
||||
mutex->AcquireSync(0, INFINITE);
|
||||
mutex->ReleaseSync(0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -214,6 +214,24 @@ TextureClientD3D11::CreateSimilar(TextureFlags aFlags,
|
||||
return tex;
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientD3D11::SyncWithObject(SyncObject* aSyncObject)
|
||||
{
|
||||
if (!aSyncObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aSyncObject->GetSyncType() == SyncObject::SyncType::D3D11);
|
||||
|
||||
SyncObjectD3D11* sync = static_cast<SyncObjectD3D11*>(aSyncObject);
|
||||
|
||||
if (mTexture) {
|
||||
sync->RegisterTexture(mTexture);
|
||||
} else {
|
||||
sync->RegisterTexture(mTexture10);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClientD3D11::Lock(OpenMode aMode)
|
||||
{
|
||||
@ -358,7 +376,7 @@ TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlag
|
||||
aSize.width, aSize.height, 1, 1,
|
||||
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE);
|
||||
|
||||
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
newDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
hr = d3d11device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture));
|
||||
} else
|
||||
@ -370,7 +388,7 @@ TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlag
|
||||
aSize.width, aSize.height, 1, 1,
|
||||
D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE);
|
||||
|
||||
newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
newDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
|
||||
|
||||
hr = device->CreateTexture2D(&newDesc, nullptr, byRef(mTexture10));
|
||||
}
|
||||
@ -674,5 +692,112 @@ CompositingRenderTargetD3D11::GetSize() const
|
||||
return TextureSourceD3D11::GetSize();
|
||||
}
|
||||
|
||||
SyncObjectD3D11::SyncObjectD3D11(SyncHandle aHandle)
|
||||
{
|
||||
MOZ_ASSERT(aHandle);
|
||||
|
||||
mHandle = aHandle;
|
||||
}
|
||||
|
||||
void
|
||||
SyncObjectD3D11::RegisterTexture(ID3D11Texture2D* aTexture)
|
||||
{
|
||||
mD3D11SyncedTextures.push_back(aTexture);
|
||||
}
|
||||
|
||||
void
|
||||
SyncObjectD3D11::RegisterTexture(ID3D10Texture2D* aTexture)
|
||||
{
|
||||
mD3D10SyncedTextures.push_back(aTexture);
|
||||
}
|
||||
|
||||
void
|
||||
SyncObjectD3D11::FinalizeFrame()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!mD3D10Texture && mD3D10SyncedTextures.size()) {
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
|
||||
hr = device->OpenSharedResource(mHandle, __uuidof(ID3D10Texture2D), (void**)(ID3D10Texture2D**)byRef(mD3D10Texture));
|
||||
|
||||
if (FAILED(hr) || !mD3D10Texture) {
|
||||
gfxCriticalError() << "Failed to OpenSharedResource: " << hexa(hr);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// test QI
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
hr = mD3D10Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
|
||||
|
||||
if (FAILED(hr) || !mutex) {
|
||||
gfxCriticalError() << "Failed to get KeyedMutex: " << hexa(hr);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mD3D11Texture && mD3D11SyncedTextures.size()) {
|
||||
ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
|
||||
|
||||
hr = device->OpenSharedResource(mHandle, __uuidof(ID3D11Texture2D), (void**)(ID3D11Texture2D**)byRef(mD3D11Texture));
|
||||
|
||||
if (FAILED(hr) || !mD3D11Texture) {
|
||||
gfxCriticalError() << "Failed to OpenSharedResource: " << hexa(hr);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// test QI
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
|
||||
|
||||
if (FAILED(hr) || !mutex) {
|
||||
gfxCriticalError() << "Failed to get KeyedMutex: " << hexa(hr);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
if (mD3D10SyncedTextures.size()) {
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
hr = mD3D10Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
|
||||
mutex->AcquireSync(0, INFINITE);
|
||||
|
||||
D3D10_BOX box;
|
||||
box.front = box.top = box.left = 0;
|
||||
box.back = box.bottom = box.right = 1;
|
||||
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
|
||||
for (auto iter = mD3D10SyncedTextures.begin(); iter != mD3D10SyncedTextures.end(); iter++) {
|
||||
device->CopySubresourceRegion(mD3D10Texture, 0, 0, 0, 0, *iter, 0, &box);
|
||||
}
|
||||
|
||||
mutex->ReleaseSync(0);
|
||||
|
||||
mD3D10SyncedTextures.clear();
|
||||
}
|
||||
|
||||
if (mD3D11SyncedTextures.size()) {
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
hr = mD3D11Texture->QueryInterface((IDXGIKeyedMutex**)byRef(mutex));
|
||||
mutex->AcquireSync(0, INFINITE);
|
||||
|
||||
D3D11_BOX box;
|
||||
box.front = box.top = box.left = 0;
|
||||
box.back = box.bottom = box.right = 1;
|
||||
|
||||
ID3D11Device* dev = gfxWindowsPlatform::GetPlatform()->GetD3D11ContentDevice();
|
||||
RefPtr<ID3D11DeviceContext> ctx;
|
||||
dev->GetImmediateContext(byRef(ctx));
|
||||
|
||||
for (auto iter = mD3D11SyncedTextures.begin(); iter != mD3D11SyncedTextures.end(); iter++) {
|
||||
ctx->CopySubresourceRegion(mD3D11Texture, 0, 0, 0, 0, *iter, 0, &box);
|
||||
}
|
||||
|
||||
mutex->ReleaseSync(0);
|
||||
|
||||
mD3D11SyncedTextures.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
|
||||
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
|
||||
|
||||
virtual void SyncWithObject(SyncObject* aSyncObject) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
gfx::IntSize mSize;
|
||||
RefPtr<ID3D10Texture2D> mTexture10;
|
||||
@ -230,6 +232,25 @@ private:
|
||||
RefPtr<ID3D11RenderTargetView> mRTView;
|
||||
};
|
||||
|
||||
class SyncObjectD3D11 : public SyncObject
|
||||
{
|
||||
public:
|
||||
SyncObjectD3D11(SyncHandle aSyncHandle);
|
||||
|
||||
virtual SyncType GetSyncType() { return SyncType::D3D11; }
|
||||
virtual void FinalizeFrame();
|
||||
|
||||
void RegisterTexture(ID3D11Texture2D* aTexture);
|
||||
void RegisterTexture(ID3D10Texture2D* aTexture);
|
||||
|
||||
private:
|
||||
RefPtr<ID3D11Texture2D> mD3D11Texture;
|
||||
RefPtr<ID3D10Texture2D> mD3D10Texture;
|
||||
std::vector<ID3D10Texture2D*> mD3D10SyncedTextures;
|
||||
std::vector<ID3D11Texture2D*> mD3D11SyncedTextures;
|
||||
SyncHandle mHandle;
|
||||
};
|
||||
|
||||
inline uint32_t GetMaxTextureSizeForFeatureLevel(D3D_FEATURE_LEVEL aFeatureLevel)
|
||||
{
|
||||
int32_t maxTextureSize;
|
||||
|
@ -232,10 +232,13 @@ public:
|
||||
|
||||
int32_t GetSerial() { return mSerial; }
|
||||
|
||||
SyncObject* GetSyncObject() { return mSyncObject; }
|
||||
|
||||
protected:
|
||||
TextureFactoryIdentifier mTextureFactoryIdentifier;
|
||||
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
|
||||
std::vector<uint64_t> mTransactionsToRespond;
|
||||
RefPtr<SyncObject> mSyncObject;
|
||||
const int32_t mSerial;
|
||||
static mozilla::Atomic<int32_t> sSerialCounter;
|
||||
};
|
||||
|
@ -163,6 +163,8 @@ void
|
||||
CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
||||
{
|
||||
mTextureFactoryIdentifier = aIdentifier;
|
||||
|
||||
mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
|
||||
}
|
||||
|
||||
ShadowLayerForwarder::ShadowLayerForwarder()
|
||||
|
Loading…
Reference in New Issue
Block a user