Bug 1101552 - Remove the double-buffered ImageClient. r=sotaro

This commit is contained in:
Nicolas Silva 2014-11-20 19:49:51 +01:00
parent a8942550e7
commit bf0ea674ba
8 changed files with 99 additions and 267 deletions

View File

@ -159,17 +159,15 @@ MOZ_END_ENUM_CLASS(EffectTypes)
MOZ_BEGIN_ENUM_CLASS(CompositableType, uint8_t)
BUFFER_UNKNOWN,
// the deprecated compositable types
BUFFER_IMAGE_SINGLE, // image/canvas with a single texture, single buffered
BUFFER_IMAGE_BUFFERED, // canvas, double buffered
BUFFER_BRIDGE, // image bridge protocol
BUFFER_CONTENT_INC, // painted layer interface, only sends incremental
// updates to a texture on the compositor side.
// somewhere in the middle
BUFFER_TILED, // tiled painted layer
BUFFER_SIMPLE_TILED,
// the new compositable types
IMAGE, // image with single buffering
IMAGE_OVERLAY, // image without buffer
IMAGE, // image with single buffering
IMAGE_OVERLAY, // image without buffer
IMAGE_BRIDGE, // ImageBridge protocol
CONTENT_SINGLE, // painted layer interface, single buffering
CONTENT_DOUBLE, // painted layer interface, double buffering
BUFFER_COUNT

View File

@ -137,7 +137,7 @@ ImageContainer::ImageContainer(int flag)
if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
// the refcount of this ImageClient is 1. we don't use a RefPtr here because the refcount
// of this class must be done on the ImageBridge thread.
mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::BUFFER_IMAGE_SINGLE).drop();
mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::IMAGE).drop();
MOZ_ASSERT(mImageClient);
}
}

View File

@ -101,33 +101,22 @@ protected:
}
if (mContainer->IsAsync()) {
mImageClientTypeContainer = CompositableType::BUFFER_BRIDGE;
return mImageClientTypeContainer;
}
// Since D3D11 TextureClient doesn't have an internal buffer, modifying the
// front buffer directly may break the transactional property of layer updates.
if (ClientManager()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11) {
mImageClientTypeContainer = CompositableType::BUFFER_IMAGE_BUFFERED;
mImageClientTypeContainer = CompositableType::IMAGE_BRIDGE;
return mImageClientTypeContainer;
}
AutoLockImage autoLock(mContainer);
#ifdef MOZ_WIDGET_GONK
// gralloc buffer needs CompositableType::BUFFER_IMAGE_BUFFERED to prevent
// the buffer's usage conflict.
if (autoLock.GetImage()->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
mImageClientTypeContainer = CompositableType::IMAGE_OVERLAY;
return mImageClientTypeContainer;
}
mImageClientTypeContainer = autoLock.GetImage() ?
CompositableType::BUFFER_IMAGE_BUFFERED : CompositableType::BUFFER_UNKNOWN;
#else
mImageClientTypeContainer = autoLock.GetImage() ?
CompositableType::BUFFER_IMAGE_SINGLE : CompositableType::BUFFER_UNKNOWN;
#endif
mImageClientTypeContainer = autoLock.GetImage()
? CompositableType::IMAGE
: CompositableType::BUFFER_UNKNOWN;
return mImageClientTypeContainer;
}
@ -163,7 +152,7 @@ ClientImageLayer::RenderLayer()
mImageClient = ImageClient::CreateImageClient(type,
ClientManager()->AsShadowForwarder(),
flags);
if (type == CompositableType::BUFFER_BRIDGE) {
if (type == CompositableType::IMAGE_BRIDGE) {
static_cast<ImageClientBridge*>(mImageClient.get())->SetLayer(this);
}

View File

@ -49,13 +49,9 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
RefPtr<ImageClient> result = nullptr;
switch (aCompositableHostType) {
case CompositableType::IMAGE:
case CompositableType::BUFFER_IMAGE_SINGLE:
result = new ImageClientSingle(aForwarder, aFlags, CompositableType::IMAGE);
break;
case CompositableType::BUFFER_IMAGE_BUFFERED:
result = new ImageClientBuffered(aForwarder, aFlags, CompositableType::IMAGE);
break;
case CompositableType::BUFFER_BRIDGE:
case CompositableType::IMAGE_BRIDGE:
result = new ImageClientBridge(aForwarder, aFlags);
break;
case CompositableType::BUFFER_UNKNOWN:
@ -116,13 +112,6 @@ ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
{
}
ImageClientBuffered::ImageClientBuffered(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType)
: ImageClientSingle(aFwd, aFlags, aType)
{
}
TextureInfo ImageClientSingle::GetTextureInfo() const
{
return TextureInfo(CompositableType::IMAGE);
@ -148,34 +137,10 @@ ImageClientSingle::FlushAllImages(bool aExceptFront,
}
}
void
ImageClientBuffered::FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker)
{
if (!aExceptFront && mFrontBuffer) {
RemoveTexture(mFrontBuffer);
mFrontBuffer = nullptr;
}
if (mBackBuffer) {
RemoveTextureWithTracker(mBackBuffer, aAsyncTransactionTracker);
mBackBuffer = nullptr;
}
}
bool
ImageClientSingle::UpdateImage(ImageContainer* aContainer,
uint32_t aContentFlags)
{
bool isSwapped = false;
return UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
}
bool
ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
uint32_t aContentFlags, bool* aIsSwapped)
ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
{
AutoLockImage autoLock(aContainer);
*aIsSwapped = false;
Image *image = autoLock.GetImage();
if (!image) {
@ -186,186 +151,101 @@ ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
return true;
}
RefPtr<TextureClient> texture = image->AsSharedImage()
? image->AsSharedImage()->GetTextureClient(this)
: nullptr;
AutoRemoveTexture autoRemoveTexture(this);
if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient(this)) {
// fast path: no need to allocate and/or copy image data
RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient(this);
if (texture != mFrontBuffer) {
autoRemoveTexture.mTexture = mFrontBuffer;
}
mFrontBuffer = texture;
if (!AddTextureClient(texture)) {
mFrontBuffer = nullptr;
return false;
}
GetForwarder()->UpdatedTexture(this, texture, nullptr);
GetForwarder()->UseTexture(this, texture);
} else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
const PlanarYCbCrData* data = ycbcr->GetData();
if (!data) {
return false;
}
if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
autoRemoveTexture.mTexture = mFrontBuffer;
mFrontBuffer = nullptr;
}
bool bufferCreated = false;
if (!mFrontBuffer) {
gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
mFrontBuffer = TextureClient::CreateForYCbCr(GetForwarder(),
ySize, cbCrSize, data->mStereoMode,
TextureFlags::DEFAULT|mTextureFlags);
if (!mFrontBuffer) {
return false;
}
bufferCreated = true;
}
if (!mFrontBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) {
mFrontBuffer = nullptr;
return false;
}
bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data);
mFrontBuffer->Unlock();
if (bufferCreated) {
if (!AddTextureClient(mFrontBuffer)) {
mFrontBuffer = nullptr;
return false;
}
}
if (status) {
GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
GetForwarder()->UseTexture(this, mFrontBuffer);
} else {
MOZ_ASSERT(false);
return false;
}
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
image->GetFormat() == ImageFormat::EGLIMAGE)
{
gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
if (mFrontBuffer) {
autoRemoveTexture.mTexture = mFrontBuffer;
mFrontBuffer = nullptr;
}
RefPtr<TextureClient> buffer;
if (image->GetFormat() == ImageFormat::EGLIMAGE) {
EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
const EGLImageImage::Data* data = typedImage->GetData();
buffer = new EGLImageTextureClient(mTextureFlags,
data->mImage,
size,
data->mInverted);
#ifdef MOZ_WIDGET_ANDROID
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
const SurfaceTextureImage::Data* data = typedImage->GetData();
buffer = new SurfaceTextureClient(mTextureFlags,
data->mSurfTex,
size,
data->mInverted);
#endif
} else {
MOZ_ASSERT(false, "Bad ImageFormat.");
}
mFrontBuffer = buffer;
if (!AddTextureClient(mFrontBuffer)) {
mFrontBuffer = nullptr;
return false;
}
GetForwarder()->UseTexture(this, mFrontBuffer);
} else {
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
MOZ_ASSERT(surface);
gfx::IntSize size = image->GetSize();
if (mFrontBuffer &&
(mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
autoRemoveTexture.mTexture = mFrontBuffer;
mFrontBuffer = nullptr;
}
bool bufferCreated = false;
if (!mFrontBuffer) {
mFrontBuffer = CreateTextureClientForDrawing(surface->GetFormat(), size,
gfx::BackendType::NONE, mTextureFlags);
if (!mFrontBuffer) {
return false;
}
MOZ_ASSERT(mFrontBuffer->CanExposeDrawTarget());
bufferCreated = true;
}
if (!mFrontBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) {
mFrontBuffer = nullptr;
return false;
}
{
// We must not keep a reference to the DrawTarget after it has been unlocked.
DrawTarget* dt = mFrontBuffer->BorrowDrawTarget();
MOZ_ASSERT(surface.get());
dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
}
mFrontBuffer->Unlock();
if (bufferCreated) {
if (!AddTextureClient(mFrontBuffer)) {
mFrontBuffer = nullptr;
return false;
}
}
GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr);
GetForwarder()->UseTexture(this, mFrontBuffer);
if (texture != mFrontBuffer) {
autoRemoveTexture.mTexture = mFrontBuffer;
mFrontBuffer = nullptr;
}
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;
}
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);
const EGLImageImage::Data* data = typedImage->GetData();
texture = new EGLImageTextureClient(mTextureFlags, data->mImage,
size, data->mInverted);
#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(mTextureFlags, data->mSurfTex,
size, data->mInverted);
#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();
MOZ_ASSERT(surface.get());
dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint());
}
texture->Unlock();
}
}
if (!texture || !AddTextureClient(texture)) {
return false;
}
mFrontBuffer = texture;
GetForwarder()->UpdatedTexture(this, texture, nullptr);
GetForwarder()->UseTexture(this, texture);
UpdatePictureRect(image->GetPictureRect());
mLastPaintedImageSerial = image->GetSerial();
aContainer->NotifyPaintedImage(image);
*aIsSwapped = true;
return true;
}
bool
ImageClientBuffered::UpdateImage(ImageContainer* aContainer,
uint32_t aContentFlags)
{
RefPtr<TextureClient> temp = mFrontBuffer;
mFrontBuffer = mBackBuffer;
mBackBuffer = temp;
bool isSwapped = false;
bool ret = ImageClientSingle::UpdateImageInternal(aContainer, aContentFlags, &isSwapped);
if (!isSwapped) {
// If buffer swap did not happen at Host side, swap back the buffers.
RefPtr<TextureClient> temp = mFrontBuffer;
mFrontBuffer = mBackBuffer;
mBackBuffer = temp;
}
return ret;
}
bool
ImageClientSingle::AddTextureClient(TextureClient* aTexture)
{
@ -379,13 +259,6 @@ ImageClientSingle::OnDetach()
mFrontBuffer = nullptr;
}
void
ImageClientBuffered::OnDetach()
{
mFrontBuffer = nullptr;
mBackBuffer = nullptr;
}
ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
CompositableType aType)
: CompositableClient(aFwd, aFlags)
@ -406,7 +279,7 @@ ImageClient::UpdatePictureRect(nsIntRect aRect)
ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
TextureFlags aFlags)
: ImageClient(aFwd, aFlags, CompositableType::BUFFER_BRIDGE)
: ImageClient(aFwd, aFlags, CompositableType::IMAGE_BRIDGE)
, mAsyncContainerID(0)
, mLayer(nullptr)
{

View File

@ -114,34 +114,10 @@ public:
virtual void FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker) MOZ_OVERRIDE;
protected:
virtual bool UpdateImageInternal(ImageContainer* aContainer, uint32_t aContentFlags, bool* aIsSwapped);
protected:
RefPtr<TextureClient> mFrontBuffer;
};
/**
* An image client which uses two texture clients.
*/
class ImageClientBuffered : public ImageClientSingle
{
public:
ImageClientBuffered(CompositableForwarder* aFwd,
TextureFlags aFlags,
CompositableType aType);
virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
virtual void OnDetach() MOZ_OVERRIDE;
virtual void FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker) MOZ_OVERRIDE;
protected:
RefPtr<TextureClient> mBackBuffer;
};
/**
* Image class to be used for async image uploads using the image bridge
* protocol.

View File

@ -45,8 +45,6 @@ bool
CanvasLayerComposite::SetCompositableHost(CompositableHost* aHost)
{
switch (aHost->GetType()) {
case CompositableType::BUFFER_IMAGE_SINGLE:
case CompositableType::BUFFER_IMAGE_BUFFERED:
case CompositableType::IMAGE:
mImageHost = aHost;
return true;

View File

@ -178,7 +178,7 @@ CompositableHost::Create(const TextureInfo& aTextureInfo)
{
RefPtr<CompositableHost> result;
switch (aTextureInfo.mCompositableType) {
case CompositableType::BUFFER_BRIDGE:
case CompositableType::IMAGE_BRIDGE:
NS_ERROR("Cannot create an image bridge compositable this way");
break;
case CompositableType::BUFFER_CONTENT_INC:

View File

@ -51,8 +51,6 @@ bool
ImageLayerComposite::SetCompositableHost(CompositableHost* aHost)
{
switch (aHost->GetType()) {
case CompositableType::BUFFER_IMAGE_SINGLE:
case CompositableType::BUFFER_IMAGE_BUFFERED:
case CompositableType::IMAGE:
case CompositableType::IMAGE_OVERLAY:
mImageHost = aHost;