mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1143575. Make ImageClientSingle handle multiple textures. r=nical
--HG-- extra : commitid : IMpF8V8HNbk extra : rebase_source : e7748b4daa61d031a092970c793edef38787f974
This commit is contained in:
parent
7f3db8a464
commit
6111862fcc
@ -376,6 +376,7 @@ public:
|
||||
|
||||
struct OwningImage {
|
||||
nsRefPtr<Image> mImage;
|
||||
TimeStamp mTimeStamp;
|
||||
};
|
||||
/**
|
||||
* Copy the current Image list to aImages.
|
||||
|
@ -103,7 +103,11 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
GetForwarder()->UseTexture(this, mBuffer);
|
||||
nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mBuffer;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
}
|
||||
@ -380,7 +384,11 @@ CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
// Add the new TexClient.
|
||||
MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );
|
||||
|
||||
forwarder->UseTexture(this, mFront);
|
||||
nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mFront;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
|
||||
forwarder->UseTextures(this, textures);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -384,7 +384,12 @@ ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
|
||||
mForwarder->UseComponentAlphaTextures(this, mTextureClient,
|
||||
mTextureClientOnWhite);
|
||||
} else {
|
||||
mForwarder->UseTexture(this, mTextureClient);
|
||||
nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mTextureClient;
|
||||
IntSize size = mTextureClient->GetSize();
|
||||
t->mPictureRect = nsIntRect(0, 0, size.width, size.height);
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
}
|
||||
mForwarder->UpdateTextureRegion(this,
|
||||
ThebesBufferData(BufferRect(),
|
||||
|
@ -113,9 +113,11 @@ void
|
||||
ImageClientSingle::FlushAllImages(bool aExceptFront,
|
||||
AsyncTransactionWaiter* aAsyncTransactionWaiter)
|
||||
{
|
||||
if (!aExceptFront && mFrontBuffer) {
|
||||
RemoveTextureWithWaiter(mFrontBuffer, aAsyncTransactionWaiter);
|
||||
mFrontBuffer = nullptr;
|
||||
if (!aExceptFront) {
|
||||
for (auto& b : mBuffers) {
|
||||
RemoveTextureWithWaiter(b.mTextureClient, aAsyncTransactionWaiter);
|
||||
}
|
||||
mBuffers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,107 +133,137 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
||||
}
|
||||
mLastUpdateGenerationCounter = generationCounter;
|
||||
|
||||
Image* image = images[0].mImage;
|
||||
// Don't try to update to an invalid image. We return true because the caller
|
||||
// would attempt to recreate the ImageClient otherwise, and that isn't going
|
||||
// to help.
|
||||
if (!image->IsValid()) {
|
||||
for (int32_t i = images.Length() - 1; i >= 0; --i) {
|
||||
if (!images[i].mImage->IsValid()) {
|
||||
// Don't try to update to an invalid image.
|
||||
images.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
if (images.IsEmpty()) {
|
||||
// We return true because the caller would attempt to recreate the
|
||||
// ImageClient otherwise, and that isn't going to help.
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<TextureClient> texture = image->GetTextureClient(this);
|
||||
nsTArray<Buffer> newBuffers;
|
||||
nsAutoTArray<CompositableForwarder::TimedTextureClient,4> textures;
|
||||
|
||||
AutoRemoveTexture autoRemoveTexture(this);
|
||||
if (texture != mFrontBuffer) {
|
||||
autoRemoveTexture.mTexture = mFrontBuffer;
|
||||
mFrontBuffer = nullptr;
|
||||
}
|
||||
for (auto& img : images) {
|
||||
Image* image = img.mImage;
|
||||
RefPtr<TextureClient> texture = image->GetTextureClient(this);
|
||||
|
||||
if (!texture) {
|
||||
// Slow path, we should not be hitting it very often and if we do it means
|
||||
// we are using an Image class that is not backed by textureClient and we
|
||||
// should fix it.
|
||||
if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
|
||||
const PlanarYCbCrData* data = ycbcr->GetData();
|
||||
if (!data) {
|
||||
return false;
|
||||
for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
|
||||
if (mBuffers[i].mImageSerial == image->GetSerial()) {
|
||||
if (texture) {
|
||||
MOZ_ASSERT(texture == mBuffers[i].mTextureClient);
|
||||
} else {
|
||||
texture = mBuffers[i].mTextureClient;
|
||||
}
|
||||
// Remove this element from mBuffers so mBuffers only contains
|
||||
// images that aren't present in 'images'
|
||||
mBuffers.RemoveElementAt(i);
|
||||
}
|
||||
texture = TextureClient::CreateForYCbCr(GetForwarder(),
|
||||
data->mYSize, data->mCbCrSize, data->mStereoMode,
|
||||
TextureFlags::DEFAULT | mTextureFlags
|
||||
);
|
||||
if (!texture || !texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
return false;
|
||||
}
|
||||
bool status = texture->AsTextureClientYCbCr()->UpdateYCbCr(*data);
|
||||
MOZ_ASSERT(status);
|
||||
}
|
||||
|
||||
texture->Unlock();
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
|
||||
image->GetFormat() == ImageFormat::EGLIMAGE) {
|
||||
gfx::IntSize size = image->GetSize();
|
||||
|
||||
if (image->GetFormat() == ImageFormat::EGLIMAGE) {
|
||||
EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
|
||||
texture = new EGLImageTextureClient(GetForwarder(),
|
||||
mTextureFlags,
|
||||
typedImage,
|
||||
size);
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
||||
SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
|
||||
const SurfaceTextureImage::Data* data = typedImage->GetData();
|
||||
texture = new SurfaceTextureClient(GetForwarder(), mTextureFlags,
|
||||
data->mSurfTex, size,
|
||||
data->mOriginPos);
|
||||
#endif
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Bad ImageFormat.");
|
||||
}
|
||||
} else {
|
||||
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
|
||||
MOZ_ASSERT(surface);
|
||||
texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
|
||||
gfx::BackendType::NONE, mTextureFlags);
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(texture->CanExposeDrawTarget());
|
||||
|
||||
if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// We must not keep a reference to the DrawTarget after it has been unlocked.
|
||||
DrawTarget* dt = texture->BorrowDrawTarget();
|
||||
if (!dt) {
|
||||
gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
|
||||
if (!texture) {
|
||||
// Slow path, we should not be hitting it very often and if we do it means
|
||||
// we are using an Image class that is not backed by textureClient and we
|
||||
// should fix it.
|
||||
if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
|
||||
const PlanarYCbCrData* data = ycbcr->GetData();
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(surface.get());
|
||||
dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
|
||||
texture = TextureClient::CreateForYCbCr(GetForwarder(),
|
||||
data->mYSize, data->mCbCrSize, data->mStereoMode,
|
||||
TextureFlags::DEFAULT | mTextureFlags
|
||||
);
|
||||
if (!texture || !texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
return false;
|
||||
}
|
||||
bool status = texture->AsTextureClientYCbCr()->UpdateYCbCr(*data);
|
||||
MOZ_ASSERT(status);
|
||||
|
||||
texture->Unlock();
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
|
||||
image->GetFormat() == ImageFormat::EGLIMAGE) {
|
||||
gfx::IntSize size = image->GetSize();
|
||||
|
||||
if (image->GetFormat() == ImageFormat::EGLIMAGE) {
|
||||
EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
|
||||
texture = new EGLImageTextureClient(GetForwarder(),
|
||||
mTextureFlags,
|
||||
typedImage,
|
||||
size);
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
|
||||
SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
|
||||
const SurfaceTextureImage::Data* data = typedImage->GetData();
|
||||
texture = new SurfaceTextureClient(GetForwarder(), mTextureFlags,
|
||||
data->mSurfTex, size,
|
||||
data->mOriginPos);
|
||||
#endif
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Bad ImageFormat.");
|
||||
}
|
||||
} else {
|
||||
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
|
||||
MOZ_ASSERT(surface);
|
||||
texture = CreateTextureClientForDrawing(surface->GetFormat(), image->GetSize(),
|
||||
gfx::BackendType::NONE, mTextureFlags);
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(texture->CanExposeDrawTarget());
|
||||
|
||||
if (!texture->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// We must not keep a reference to the DrawTarget after it has been unlocked.
|
||||
DrawTarget* dt = texture->BorrowDrawTarget();
|
||||
if (!dt) {
|
||||
gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget";
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(surface.get());
|
||||
dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
|
||||
}
|
||||
|
||||
texture->Unlock();
|
||||
}
|
||||
|
||||
texture->Unlock();
|
||||
}
|
||||
}
|
||||
if (!texture || !AddTextureClient(texture)) {
|
||||
return false;
|
||||
if (!texture || !AddTextureClient(texture)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = texture;
|
||||
t->mTimeStamp = img.mTimeStamp;
|
||||
t->mPictureRect = image->GetPictureRect();
|
||||
|
||||
Buffer* newBuf = newBuffers.AppendElement();
|
||||
newBuf->mImageSerial = image->GetSerial();
|
||||
newBuf->mTextureClient = texture;
|
||||
|
||||
aContainer->NotifyPaintedImage(image);
|
||||
texture->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
|
||||
mFrontBuffer = texture;
|
||||
IntRect pictureRect = image->GetPictureRect();
|
||||
GetForwarder()->UseTexture(this, texture, &pictureRect);
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
|
||||
aContainer->NotifyPaintedImage(image);
|
||||
texture->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
for (auto& b : mBuffers) {
|
||||
RemoveTexture(b.mTextureClient);
|
||||
}
|
||||
mBuffers.SwapElements(newBuffers);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -246,7 +278,7 @@ ImageClientSingle::AddTextureClient(TextureClient* aTexture)
|
||||
void
|
||||
ImageClientSingle::OnDetach()
|
||||
{
|
||||
mFrontBuffer = nullptr;
|
||||
mBuffers.Clear();
|
||||
}
|
||||
|
||||
ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
|
||||
|
@ -106,7 +106,11 @@ public:
|
||||
AsyncTransactionWaiter* aAsyncTransactionWaiter) override;
|
||||
|
||||
protected:
|
||||
RefPtr<TextureClient> mFrontBuffer;
|
||||
struct Buffer {
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
int32_t mImageSerial;
|
||||
};
|
||||
nsTArray<Buffer> mBuffers;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -128,16 +128,17 @@ public:
|
||||
mTexturesToRemove.Clear();
|
||||
}
|
||||
|
||||
struct TimedTextureClient {
|
||||
TextureClient* mTextureClient;
|
||||
TimeStamp mTimeStamp;
|
||||
nsIntRect mPictureRect;
|
||||
};
|
||||
/**
|
||||
* Tell the CompositableHost on the compositor side what texture to use for
|
||||
* Tell the CompositableHost on the compositor side what textures to use for
|
||||
* the next composition.
|
||||
* If non-null, aPictureRect is the area of the texture which makes up the
|
||||
* image. That is, the area that should be composited. In texture space.
|
||||
* When aPictureRect is null, the entire area of the texture is used.
|
||||
*/
|
||||
virtual void UseTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aClient,
|
||||
const nsIntRect* aPictureRect = nullptr) = 0;
|
||||
virtual void UseTextures(CompositableClient* aCompositable,
|
||||
const nsTArray<TimedTextureClient>& aTextures) = 0;
|
||||
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
|
||||
TextureClient* aClientOnBlack,
|
||||
TextureClient* aClientOnWhite) = 0;
|
||||
|
@ -107,22 +107,22 @@ struct AutoEndTransaction {
|
||||
};
|
||||
|
||||
void
|
||||
ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aTexture,
|
||||
const gfx::IntRect* aPictureRect)
|
||||
ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
|
||||
const nsTArray<TimedTextureClient>& aTextures)
|
||||
{
|
||||
MOZ_ASSERT(aCompositable);
|
||||
MOZ_ASSERT(aTexture);
|
||||
MOZ_ASSERT(aCompositable->GetIPDLActor());
|
||||
MOZ_ASSERT(aTexture->GetIPDLActor());
|
||||
|
||||
FenceHandle fence = aTexture->GetAcquireFenceHandle();
|
||||
IntRect pictureRect = aPictureRect ? *aPictureRect :
|
||||
IntRect(IntPoint(0, 0), IntSize(aTexture->GetSize()));
|
||||
nsAutoTArray<TimedTexture,1> textures;
|
||||
textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
|
||||
fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
|
||||
TimeStamp(), pictureRect));
|
||||
nsAutoTArray<TimedTexture,4> textures;
|
||||
|
||||
for (auto& t : aTextures) {
|
||||
MOZ_ASSERT(t.mTextureClient);
|
||||
MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
|
||||
FenceHandle fence = t.mTextureClient->GetAcquireFenceHandle();
|
||||
textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
|
||||
fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
|
||||
t.mTimeStamp, t.mPictureRect));
|
||||
}
|
||||
mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
|
||||
textures));
|
||||
}
|
||||
|
@ -217,11 +217,10 @@ public:
|
||||
virtual bool IsImageBridgeChild() const override { return true; }
|
||||
|
||||
/**
|
||||
* See CompositableForwarder::UseTexture
|
||||
* See CompositableForwarder::UseTextures
|
||||
*/
|
||||
virtual void UseTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aClient,
|
||||
const nsIntRect* aPictureRect = nullptr) override;
|
||||
virtual void UseTextures(CompositableClient* aCompositable,
|
||||
const nsTArray<TimedTextureClient>& aTextures) override;
|
||||
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
|
||||
TextureClient* aClientOnBlack,
|
||||
TextureClient* aClientOnWhite) override;
|
||||
|
@ -350,31 +350,32 @@ ShadowLayerForwarder::UpdateTextureRegion(CompositableClient* aCompositable,
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aTexture,
|
||||
const nsIntRect* aPictureRect)
|
||||
ShadowLayerForwarder::UseTextures(CompositableClient* aCompositable,
|
||||
const nsTArray<TimedTextureClient>& aTextures)
|
||||
{
|
||||
MOZ_ASSERT(aCompositable);
|
||||
MOZ_ASSERT(aTexture);
|
||||
MOZ_ASSERT(aCompositable->GetIPDLActor());
|
||||
MOZ_ASSERT(aTexture->GetIPDLActor());
|
||||
|
||||
FenceHandle fence = aTexture->GetAcquireFenceHandle();
|
||||
IntRect pictureRect = aPictureRect ? *aPictureRect :
|
||||
IntRect(nsIntPoint(0, 0), IntSize(aTexture->GetSize()));
|
||||
nsAutoTArray<TimedTexture,1> textures;
|
||||
textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
|
||||
fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
|
||||
TimeStamp(), pictureRect));
|
||||
nsAutoTArray<TimedTexture,4> textures;
|
||||
|
||||
for (auto& t : aTextures) {
|
||||
MOZ_ASSERT(t.mTextureClient);
|
||||
MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
|
||||
FenceHandle fence = t.mTextureClient->GetAcquireFenceHandle();
|
||||
textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
|
||||
fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
|
||||
t.mTimeStamp, t.mPictureRect));
|
||||
if ((t.mTextureClient->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD)
|
||||
&& t.mTextureClient->HasInternalBuffer()) {
|
||||
|
||||
// We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot
|
||||
// race with updates on the main thread. In this case we want the transaction
|
||||
// to be synchronous.
|
||||
mTxn->MarkSyncTransaction();
|
||||
}
|
||||
}
|
||||
mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
|
||||
textures));
|
||||
if (aTexture->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD
|
||||
&& aTexture->HasInternalBuffer()) {
|
||||
// We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot
|
||||
// race with updates on the main thread. In this case we want the transaction
|
||||
// to be synchronous.
|
||||
mTxn->MarkSyncTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -229,11 +229,10 @@ public:
|
||||
const nsIntRegion& aUpdatedRegion) override;
|
||||
|
||||
/**
|
||||
* See CompositableForwarder::UseTexture
|
||||
* See CompositableForwarder::UseTextures
|
||||
*/
|
||||
virtual void UseTexture(CompositableClient* aCompositable,
|
||||
TextureClient* aClient,
|
||||
const nsIntRect* aPictureRect = nullptr) override;
|
||||
virtual void UseTextures(CompositableClient* aCompositable,
|
||||
const nsTArray<TimedTextureClient>& aTextures) override;
|
||||
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
|
||||
TextureClient* aClientOnBlack,
|
||||
TextureClient* aClientOnWhite) override;
|
||||
|
Loading…
Reference in New Issue
Block a user