mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 02:05:42 +00:00
Bug 1291296 - Make it possible to change a PersistentBufferProvider's Forwarder without crashing. r=ethlin
This commit is contained in:
parent
8289246c56
commit
36eabd3917
@ -135,6 +135,84 @@ PersistentBufferProviderShared::~PersistentBufferProviderShared()
|
||||
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*
|
||||
PersistentBufferProviderShared::GetTexture(Maybe<uint32_t> aIndex)
|
||||
{
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
virtual TextureClient* GetTextureClient() { return nullptr; }
|
||||
|
||||
virtual void OnShutdown() {}
|
||||
|
||||
virtual bool SetForwarder(CompositableForwarder* aFwd) { return true; }
|
||||
};
|
||||
|
||||
|
||||
@ -124,6 +126,8 @@ public:
|
||||
|
||||
virtual void OnShutdown() override { Destroy(); }
|
||||
|
||||
virtual bool SetForwarder(CompositableForwarder* aFwd) override;
|
||||
|
||||
protected:
|
||||
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
CompositableForwarder* aFwd,
|
||||
|
@ -126,6 +126,10 @@ ClientCanvasLayer::RenderLayer()
|
||||
|
||||
FirePreTransactionCallback();
|
||||
if (mBufferProvider && mBufferProvider->GetTextureClient()) {
|
||||
if (!mBufferProvider->SetForwarder(mCanvasClient->GetForwarder())) {
|
||||
gfxCriticalNote << "BufferProvider::SetForwarder failed";
|
||||
return;
|
||||
}
|
||||
mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
|
||||
} else {
|
||||
mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
|
||||
|
Loading…
Reference in New Issue
Block a user