зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1291296 - Make it possible to change a PersistentBufferProvider's Forwarder without crashing. r=ethlin
This commit is contained in:
Родитель
8289246c56
Коммит
36eabd3917
|
@ -135,6 +135,84 @@ PersistentBufferProviderShared::~PersistentBufferProviderShared()
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PersistentBufferProviderShared::SetForwarder(CompositableForwarder* aFwd)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aFwd);
|
||||||
|
if (!aFwd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFwd == aFwd) {
|
||||||
|
// The forwarder should not change most of the time.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsActivityTracked()) {
|
||||||
|
mFwd->GetActiveResourceTracker().RemoveObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFwd->AsTextureForwarder() != aFwd->AsTextureForwarder() ||
|
||||||
|
mFwd->GetCompositorBackendType() != aFwd->GetCompositorBackendType()) {
|
||||||
|
// We are going to be used with an different and/or incompatible forwarder.
|
||||||
|
// This should be extremely rare. We have to copy the front buffer into a
|
||||||
|
// texture that is compatible with the new forwarder.
|
||||||
|
|
||||||
|
// Grab the current front buffer.
|
||||||
|
RefPtr<TextureClient> prevTexture = GetTexture(mFront);
|
||||||
|
|
||||||
|
// Get rid of everything else
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
if (prevTexture) {
|
||||||
|
RefPtr<TextureClient> newTexture = TextureClient::CreateForDrawing(
|
||||||
|
aFwd, mFormat, mSize,
|
||||||
|
BackendSelector::Canvas,
|
||||||
|
TextureFlags::DEFAULT,
|
||||||
|
TextureAllocationFlags::ALLOC_DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
|
MOZ_ASSERT(newTexture);
|
||||||
|
if (!newTexture) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we early-return in one of the following branches, we will
|
||||||
|
// leave the buffer provider in an empty state, since we called
|
||||||
|
// Destroy. Not ideal but at least we won't try to use it with a
|
||||||
|
// an incompatible ipc channel.
|
||||||
|
|
||||||
|
if (!newTexture->Lock(OpenMode::OPEN_WRITE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prevTexture->Lock(OpenMode::OPEN_READ)) {
|
||||||
|
newTexture->Unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = prevTexture->CopyToTextureClient(newTexture, nullptr, nullptr);
|
||||||
|
|
||||||
|
prevTexture->Unlock();
|
||||||
|
newTexture->Unlock();
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mTextures.append(newTexture)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mFront = Some<uint32_t>(mTextures.length() - 1);
|
||||||
|
mBack = mFront;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFwd = aFwd;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
TextureClient*
|
TextureClient*
|
||||||
PersistentBufferProviderShared::GetTexture(Maybe<uint32_t> aIndex)
|
PersistentBufferProviderShared::GetTexture(Maybe<uint32_t> aIndex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,8 @@ public:
|
||||||
virtual TextureClient* GetTextureClient() { return nullptr; }
|
virtual TextureClient* GetTextureClient() { return nullptr; }
|
||||||
|
|
||||||
virtual void OnShutdown() {}
|
virtual void OnShutdown() {}
|
||||||
|
|
||||||
|
virtual bool SetForwarder(CompositableForwarder* aFwd) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,6 +126,8 @@ public:
|
||||||
|
|
||||||
virtual void OnShutdown() override { Destroy(); }
|
virtual void OnShutdown() override { Destroy(); }
|
||||||
|
|
||||||
|
virtual bool SetForwarder(CompositableForwarder* aFwd) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||||
CompositableForwarder* aFwd,
|
CompositableForwarder* aFwd,
|
||||||
|
|
|
@ -126,6 +126,10 @@ ClientCanvasLayer::RenderLayer()
|
||||||
|
|
||||||
FirePreTransactionCallback();
|
FirePreTransactionCallback();
|
||||||
if (mBufferProvider && mBufferProvider->GetTextureClient()) {
|
if (mBufferProvider && mBufferProvider->GetTextureClient()) {
|
||||||
|
if (!mBufferProvider->SetForwarder(mCanvasClient->GetForwarder())) {
|
||||||
|
gfxCriticalNote << "BufferProvider::SetForwarder failed";
|
||||||
|
return;
|
||||||
|
}
|
||||||
mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
|
mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
|
||||||
} else {
|
} else {
|
||||||
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
|
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче