From f1166bf04f48602d4f94af346ee9b212f0443f06 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Thu, 16 Oct 2014 19:08:32 +0200 Subject: [PATCH] Bug 1077301 - Simplify the gralloc texture code. r=sotaro --- gfx/layers/Compositor.h | 15 - gfx/layers/composite/CompositableHost.cpp | 36 +- gfx/layers/composite/CompositableHost.h | 50 --- gfx/layers/composite/ContentHost.cpp | 278 ++++++++++++--- gfx/layers/composite/ContentHost.h | 46 ++- gfx/layers/composite/ImageHost.cpp | 61 ++-- gfx/layers/composite/ImageHost.h | 5 +- gfx/layers/composite/TextureHost.cpp | 31 +- gfx/layers/composite/TextureHost.h | 84 ++++- gfx/layers/opengl/GrallocTextureHost.cpp | 398 +++++++++++----------- gfx/layers/opengl/GrallocTextureHost.h | 43 ++- gfx/layers/opengl/TextureHostOGL.cpp | 231 +++---------- gfx/layers/opengl/TextureHostOGL.h | 128 ++----- 13 files changed, 688 insertions(+), 718 deletions(-) diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 592bdd733e76..0168a767ff78 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -135,17 +135,6 @@ enum SurfaceInitMode INIT_MODE_CLEAR }; -/** - * A base class for a platform-dependent helper for use by TextureHost. - */ -class CompositorBackendSpecificData -{ - NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData) - -protected: - virtual ~CompositorBackendSpecificData() {} -}; - /** * Common interface for compositor backends. * @@ -481,10 +470,6 @@ public: return fillRatio; } - virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() { - return nullptr; - } - ScreenRotation GetScreenRotation() const { return mScreenRotation; } diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index 2bbbd78d82ad..645e0f813cb6 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -24,14 +24,6 @@ namespace layers { class Compositor; -CompositableBackendSpecificData::CompositableBackendSpecificData() - : mAllowSharingTextureHost(false) -{ - static uint64_t sNextID = 1; - ++sNextID; - mId = sNextID; -} - /** * IPDL actor used by CompositableHost to match with its corresponding * CompositableClient on the content side. @@ -87,9 +79,6 @@ CompositableHost::CompositableHost(const TextureInfo& aTextureInfo) CompositableHost::~CompositableHost() { MOZ_COUNT_DTOR(CompositableHost); - if (mBackendData) { - mBackendData->ClearData(); - } } PCompositableParent* @@ -121,7 +110,6 @@ CompositableHost::UseTextureHost(TextureHost* aTexture) return; } aTexture->SetCompositor(GetCompositor()); - aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); } void @@ -130,17 +118,12 @@ CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, { MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite); aTextureOnBlack->SetCompositor(GetCompositor()); - aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); aTextureOnWhite->SetCompositor(GetCompositor()); - aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); } void CompositableHost::RemoveTextureHost(TextureHost* aTexture) -{ - // Clear strong refrence to CompositableBackendSpecificData - aTexture->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); -} +{} void CompositableHost::SetCompositor(Compositor* aCompositor) @@ -153,7 +136,7 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects, const gfx::Matrix4x4& aTransform, bool aIs3D) { - RefPtr source; + CompositableTextureSourceRef source; RefPtr host = GetAsTextureHost(); if (!host) { @@ -166,14 +149,12 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects, return false; } - source = host->GetTextureSources(); - MOZ_ASSERT(source); - - if (!source) { + if (!host->BindTextureSource(source)) { NS_WARNING("The TextureHost was successfully locked but can't provide a TextureSource"); host->Unlock(); return false; } + MOZ_ASSERT(source); RefPtr effect = new EffectMask(source, source->GetSize(), @@ -192,9 +173,6 @@ CompositableHost::RemoveMaskEffect() } } -// implemented in TextureHostOGL.cpp -TemporaryRef CreateCompositableBackendSpecificDataOGL(); - /* static */ TemporaryRef CompositableHost::Create(const TextureInfo& aTextureInfo) { @@ -227,12 +205,6 @@ CompositableHost::Create(const TextureInfo& aTextureInfo) default: NS_ERROR("Unknown CompositableType"); } - // We know that Tiled buffers don't use the compositable backend-specific - // data, so don't bother creating it. - if (result && aTextureInfo.mCompositableType != CompositableType::BUFFER_TILED) { - RefPtr data = CreateCompositableBackendSpecificDataOGL(); - result->SetCompositableBackendSpecificData(data); - } return result; } diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index 4a2862813ef2..0c6543ad51b1 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -49,42 +49,6 @@ class CompositableParentManager; class PCompositableParent; struct EffectChain; -/** - * A base class for doing CompositableHost and platform dependent task on TextureHost. - */ -class CompositableBackendSpecificData -{ -protected: - virtual ~CompositableBackendSpecificData() {} - -public: - NS_INLINE_DECL_REFCOUNTING(CompositableBackendSpecificData) - - CompositableBackendSpecificData(); - - virtual void ClearData() {} - virtual void SetCompositor(Compositor* aCompositor) {} - - bool IsAllowingSharingTextureHost() - { - return mAllowSharingTextureHost; - } - - void SetAllowSharingTextureHost(bool aAllow) - { - mAllowSharingTextureHost = aAllow; - } - - uint64_t GetId() - { - return mId; - } - -public: - bool mAllowSharingTextureHost; - uint64_t mId; -}; - /** * The compositor-side counterpart to CompositableClient. Responsible for * updating textures and data about textures from IPC and how textures are @@ -112,16 +76,6 @@ public: virtual CompositableType GetType() = 0; - virtual CompositableBackendSpecificData* GetCompositableBackendSpecificData() - { - return mBackendData; - } - - virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) - { - mBackendData = aBackendData; - } - // If base class overrides, it should still call the parent implementation virtual void SetCompositor(Compositor* aCompositor); @@ -252,9 +206,6 @@ public: SetLayer(nullptr); mAttached = false; mKeepAttached = false; - if (mBackendData) { - mBackendData->ClearData(); - } } } bool IsAttached() { return mAttached; } @@ -314,7 +265,6 @@ protected: uint64_t mCompositorID; RefPtr mCompositor; Layer* mLayer; - RefPtr mBackendData; uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true. bool mAttached; bool mKeepAttached; diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index 09b0a0550b8a..e8ea6dde223f 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -35,12 +35,12 @@ ContentHostBase::~ContentHostBase() } void -ContentHostBase::Composite(EffectChain& aEffectChain, - float aOpacity, - const gfx::Matrix4x4& aTransform, - const Filter& aFilter, - const Rect& aClipRect, - const nsIntRegion* aVisibleRegion) +ContentHostTexture::Composite(EffectChain& aEffectChain, + float aOpacity, + const gfx::Matrix4x4& aTransform, + const Filter& aFilter, + const Rect& aClipRect, + const nsIntRegion* aVisibleRegion) { NS_ASSERTION(aVisibleRegion, "Requires a visible region"); @@ -49,14 +49,21 @@ ContentHostBase::Composite(EffectChain& aEffectChain, return; } - RefPtr source = GetTextureSource(); - RefPtr sourceOnWhite = GetTextureSourceOnWhite(); + if (!mTextureHost->BindTextureSource(mTextureSource)) { + return; + } + MOZ_ASSERT(mTextureSource.get()); - if (!source) { + if (!mTextureHostOnWhite) { + mTextureSourceOnWhite = nullptr; + } + if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) { return; } - RefPtr effect = GenEffect(aFilter); + RefPtr effect = CreateTexturedEffect(mTextureSource.get(), + mTextureSourceOnWhite.get(), + aFilter, true); if (!effect) { return; } @@ -81,7 +88,7 @@ ContentHostBase::Composite(EffectChain& aEffectChain, region.MoveBy(-origin); // Figure out the intersecting draw region - gfx::IntSize texSize = source->GetSize(); + gfx::IntSize texSize = mTextureSource->GetSize(); nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height); textureRect.MoveBy(region.GetBounds().TopLeft()); nsIntRegion subregion; @@ -105,14 +112,14 @@ ContentHostBase::Composite(EffectChain& aEffectChain, regionRects.Or(regionRects, regionRect); } - BigImageIterator* bigImgIter = source->AsBigImageIterator(); + BigImageIterator* bigImgIter = mTextureSource->AsBigImageIterator(); BigImageIterator* iterOnWhite = nullptr; if (bigImgIter) { bigImgIter->BeginBigImageIteration(); } - if (sourceOnWhite) { - iterOnWhite = sourceOnWhite->AsBigImageIterator(); + if (mTextureSourceOnWhite) { + iterOnWhite = mTextureSourceOnWhite->AsBigImageIterator(); MOZ_ASSERT(!bigImgIter || bigImgIter->GetTileCount() == iterOnWhite->GetTileCount(), "Tile count mismatch on component alpha texture"); if (iterOnWhite) { @@ -205,32 +212,40 @@ ContentHostBase::Composite(EffectChain& aEffectChain, aTransform, mFlashCounter); } -TemporaryRef -ContentHostBase::GenEffect(const gfx::Filter& aFilter) -{ - RefPtr source = GetTextureSource(); - RefPtr sourceOnWhite = GetTextureSourceOnWhite(); - if (!source) { - return nullptr; - } - return CreateTexturedEffect(source, sourceOnWhite, aFilter, true); -} - void ContentHostTexture::UseTextureHost(TextureHost* aTexture) { + if (mTextureHost && mTextureHost != aTexture) { + mTextureHost->UnbindTextureSource(); + } ContentHostBase::UseTextureHost(aTexture); mTextureHost = aTexture; mTextureHostOnWhite = nullptr; + mTextureSourceOnWhite = nullptr; + if (mTextureHost) { + mTextureHost->PrepareTextureSource(mTextureSource); + } } void ContentHostTexture::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, TextureHost* aTextureOnWhite) { + if (mTextureHost && mTextureHost != aTextureOnBlack) { + mTextureHost->UnbindTextureSource(); + } + if (mTextureHostOnWhite && mTextureHostOnWhite != aTextureOnWhite) { + mTextureHostOnWhite->UnbindTextureSource(); + } ContentHostBase::UseComponentAlphaTextures(aTextureOnBlack, aTextureOnWhite); mTextureHost = aTextureOnBlack; mTextureHostOnWhite = aTextureOnWhite; + if (mTextureHost) { + mTextureHost->PrepareTextureSource(mTextureSource); + } + if (mTextureHostOnWhite) { + mTextureHostOnWhite->PrepareTextureSource(mTextureSourceOnWhite); + } } void @@ -417,6 +432,176 @@ ContentHostIncremental::UpdateIncremental(TextureIdentifier aTextureId, FlushUpdateQueue(); } +void +ContentHostIncremental::Composite(EffectChain& aEffectChain, + float aOpacity, + const gfx::Matrix4x4& aTransform, + const Filter& aFilter, + const Rect& aClipRect, + const nsIntRegion* aVisibleRegion) +{ + NS_ASSERTION(aVisibleRegion, "Requires a visible region"); + + AutoLockCompositableHost lock(this); + if (lock.Failed()) { + return; + } + + if (!mSource) { + return; + } + + RefPtr effect = CreateTexturedEffect(mSource.get(), + mSourceOnWhite.get(), + aFilter, true); + if (!effect) { + return; + } + + aEffectChain.mPrimaryEffect = effect; + + nsIntRegion tmpRegion; + const nsIntRegion* renderRegion; + if (PaintWillResample()) { + // If we're resampling, then the texture image will contain exactly the + // entire visible region's bounds, and we should draw it all in one quad + // to avoid unexpected aliasing. + tmpRegion = aVisibleRegion->GetBounds(); + renderRegion = &tmpRegion; + } else { + renderRegion = aVisibleRegion; + } + + nsIntRegion region(*renderRegion); + nsIntPoint origin = GetOriginOffset(); + // translate into TexImage space, buffer origin might not be at texture (0,0) + region.MoveBy(-origin); + + // Figure out the intersecting draw region + gfx::IntSize texSize = mSource->GetSize(); + nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height); + textureRect.MoveBy(region.GetBounds().TopLeft()); + nsIntRegion subregion; + subregion.And(region, textureRect); + if (subregion.IsEmpty()) { + // Region is empty, nothing to draw + return; + } + + nsIntRegion screenRects; + nsIntRegion regionRects; + + // Collect texture/screen coordinates for drawing + nsIntRegionRectIterator iter(subregion); + while (const nsIntRect* iterRect = iter.Next()) { + nsIntRect regionRect = *iterRect; + nsIntRect screenRect = regionRect; + screenRect.MoveBy(origin); + + screenRects.Or(screenRects, screenRect); + regionRects.Or(regionRects, regionRect); + } + + BigImageIterator* bigImgIter = mSource->AsBigImageIterator(); + BigImageIterator* iterOnWhite = nullptr; + if (bigImgIter) { + bigImgIter->BeginBigImageIteration(); + } + + if (mSourceOnWhite) { + iterOnWhite = mSourceOnWhite->AsBigImageIterator(); + MOZ_ASSERT(!bigImgIter || bigImgIter->GetTileCount() == iterOnWhite->GetTileCount(), + "Tile count mismatch on component alpha texture"); + if (iterOnWhite) { + iterOnWhite->BeginBigImageIteration(); + } + } + + bool usingTiles = (bigImgIter && bigImgIter->GetTileCount() > 1); + do { + if (iterOnWhite) { + MOZ_ASSERT(iterOnWhite->GetTileRect() == bigImgIter->GetTileRect(), + "component alpha textures should be the same size."); + } + + nsIntRect texRect = bigImgIter ? bigImgIter->GetTileRect() + : nsIntRect(0, 0, + texSize.width, + texSize.height); + + // Draw texture. If we're using tiles, we do repeating manually, as texture + // repeat would cause each individual tile to repeat instead of the + // compound texture as a whole. This involves drawing at most 4 sections, + // 2 for each axis that has texture repeat. + for (int y = 0; y < (usingTiles ? 2 : 1); y++) { + for (int x = 0; x < (usingTiles ? 2 : 1); x++) { + nsIntRect currentTileRect(texRect); + currentTileRect.MoveBy(x * texSize.width, y * texSize.height); + + nsIntRegionRectIterator screenIter(screenRects); + nsIntRegionRectIterator regionIter(regionRects); + + const nsIntRect* screenRect; + const nsIntRect* regionRect; + while ((screenRect = screenIter.Next()) && + (regionRect = regionIter.Next())) { + nsIntRect tileScreenRect(*screenRect); + nsIntRect tileRegionRect(*regionRect); + + // When we're using tiles, find the intersection between the tile + // rect and this region rect. Tiling is then handled by the + // outer for-loops and modifying the tile rect. + if (usingTiles) { + tileScreenRect.MoveBy(-origin); + tileScreenRect = tileScreenRect.Intersect(currentTileRect); + tileScreenRect.MoveBy(origin); + + if (tileScreenRect.IsEmpty()) + continue; + + tileRegionRect = regionRect->Intersect(currentTileRect); + tileRegionRect.MoveBy(-currentTileRect.TopLeft()); + } + gfx::Rect rect(tileScreenRect.x, tileScreenRect.y, + tileScreenRect.width, tileScreenRect.height); + + effect->mTextureCoords = Rect(Float(tileRegionRect.x) / texRect.width, + Float(tileRegionRect.y) / texRect.height, + Float(tileRegionRect.width) / texRect.width, + Float(tileRegionRect.height) / texRect.height); + GetCompositor()->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform); + if (usingTiles) { + DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT | DiagnosticFlags::BIGIMAGE; + if (iterOnWhite) { + diagnostics |= DiagnosticFlags::COMPONENT_ALPHA; + } + GetCompositor()->DrawDiagnostics(diagnostics, rect, aClipRect, + aTransform, mFlashCounter); + } + } + } + } + + if (iterOnWhite) { + iterOnWhite->NextTile(); + } + } while (usingTiles && bigImgIter->NextTile()); + + if (bigImgIter) { + bigImgIter->EndBigImageIteration(); + } + if (iterOnWhite) { + iterOnWhite->EndBigImageIteration(); + } + + DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT; + if (iterOnWhite) { + diagnostics |= DiagnosticFlags::COMPONENT_ALPHA; + } + GetCompositor()->DrawDiagnostics(diagnostics, nsIntRegion(mBufferRect), aClipRect, + aTransform, mFlashCounter); +} + void ContentHostIncremental::FlushUpdateQueue() { @@ -439,20 +624,6 @@ ContentHostIncremental::ProcessTextureUpdates() mUpdateList.Clear(); } -TextureSource* -ContentHostIncremental::GetTextureSource() -{ - MOZ_ASSERT(mLocked); - return mSource; -} - -TextureSource* -ContentHostIncremental::GetTextureSourceOnWhite() -{ - MOZ_ASSERT(mLocked); - return mSourceOnWhite; -} - void ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental* aHost) { @@ -683,6 +854,35 @@ ContentHostTexture::GetRenderState() return result; } +TemporaryRef +ContentHostTexture::GenEffect(const gfx::Filter& aFilter) +{ + if (!mTextureHost) { + return nullptr; + } + if (!mTextureHost->BindTextureSource(mTextureSource)) { + return nullptr; + } + if (!mTextureHostOnWhite) { + mTextureSourceOnWhite = nullptr; + } + if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) { + return nullptr; + } + return CreateTexturedEffect(mTextureSource.get(), + mTextureSourceOnWhite.get(), + aFilter, true); +} + +TemporaryRef +ContentHostIncremental::GenEffect(const gfx::Filter& aFilter) +{ + if (!mSource) { + return nullptr; + } + return CreateTexturedEffect(mSource, mSourceOnWhite, aFilter, true); +} + #ifdef MOZ_DUMP_PAINTING TemporaryRef ContentHostTexture::GetAsSurface() diff --git a/gfx/layers/composite/ContentHost.h b/gfx/layers/composite/ContentHost.h index b445287ef20c..e7676d798c39 100644 --- a/gfx/layers/composite/ContentHost.h +++ b/gfx/layers/composite/ContentHost.h @@ -96,18 +96,6 @@ public: explicit ContentHostBase(const TextureInfo& aTextureInfo); virtual ~ContentHostBase(); - virtual void Composite(EffectChain& aEffectChain, - float aOpacity, - const gfx::Matrix4x4& aTransform, - const gfx::Filter& aFilter, - const gfx::Rect& aClipRect, - const nsIntRegion* aVisibleRegion = nullptr); - - virtual TextureSource* GetTextureSource() = 0; - virtual TextureSource* GetTextureSourceOnWhite() = 0; - - virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; - protected: virtual nsIntPoint GetOriginOffset() { @@ -132,6 +120,13 @@ public: , mLocked(false) { } + virtual void Composite(EffectChain& aEffectChain, + float aOpacity, + const gfx::Matrix4x4& aTransform, + const gfx::Filter& aFilter, + const gfx::Rect& aClipRect, + const nsIntRegion* aVisibleRegion = nullptr); + virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; #ifdef MOZ_DUMP_PAINTING @@ -173,23 +168,15 @@ public: mLocked = false; } - virtual TextureSource* GetTextureSource() MOZ_OVERRIDE { - MOZ_ASSERT(mLocked); - return mTextureHost->GetTextureSources(); - } - virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE { - MOZ_ASSERT(mLocked); - if (mTextureHostOnWhite) { - return mTextureHostOnWhite->GetTextureSources(); - } - return nullptr; - } - LayerRenderState GetRenderState(); + virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; + protected: RefPtr mTextureHost; RefPtr mTextureHostOnWhite; + CompositableTextureSourceRef mTextureSource; + CompositableTextureSourceRef mTextureSourceOnWhite; bool mLocked; }; @@ -277,6 +264,13 @@ public: return false; } + virtual void Composite(EffectChain& aEffectChain, + float aOpacity, + const gfx::Matrix4x4& aTransform, + const gfx::Filter& aFilter, + const gfx::Rect& aClipRect, + const nsIntRegion* aVisibleRegion = nullptr); + virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE; virtual bool Lock() MOZ_OVERRIDE { @@ -291,8 +285,8 @@ public: mLocked = false; } - virtual TextureSource* GetTextureSource() MOZ_OVERRIDE; - virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE; + virtual TemporaryRef + GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; private: diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index 6fd06a4d8a0b..3a07fcf677db 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -37,28 +37,21 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo) ImageHost::~ImageHost() { if (mFrontBuffer) { - mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); - } -} - -void -ImageHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) -{ - CompositableHost::SetCompositableBackendSpecificData(aBackendData); - // ImageHost allows TextureHost sharing among ImageHosts. - if (aBackendData) { - aBackendData->SetAllowSharingTextureHost(true); + mFrontBuffer->UnbindTextureSource(); } } void ImageHost::UseTextureHost(TextureHost* aTexture) { - CompositableHost::UseTextureHost(aTexture); - if (mFrontBuffer) { - mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); + if (mFrontBuffer && mFrontBuffer != aTexture) { + mFrontBuffer->UnbindTextureSource(); } + CompositableHost::UseTextureHost(aTexture); mFrontBuffer = aTexture; + if (mFrontBuffer) { + mFrontBuffer->PrepareTextureSource(mTextureSource); + } } void @@ -66,7 +59,8 @@ ImageHost::RemoveTextureHost(TextureHost* aTexture) { CompositableHost::RemoveTextureHost(aTexture); if (aTexture && mFrontBuffer == aTexture) { - aTexture->SetCompositableBackendSpecificData(nullptr); + mFrontBuffer->UnbindTextureSource(); + mTextureSource = nullptr; mFrontBuffer = nullptr; } } @@ -97,25 +91,34 @@ ImageHost::Composite(EffectChain& aEffectChain, // Make sure the front buffer has a compositor mFrontBuffer->SetCompositor(GetCompositor()); - mFrontBuffer->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); AutoLockCompositableHost autoLock(this); if (autoLock.Failed()) { NS_WARNING("failed to lock front buffer"); return; } - RefPtr source = GetTextureSource(); - if (!source) { + + if (!mFrontBuffer->BindTextureSource(mTextureSource)) { return; } - RefPtr effect = GenEffect(aFilter); + if (!mTextureSource) { + // BindTextureSource above should have returned false! + MOZ_ASSERT(false); + return; + } + + bool isAlphaPremultiplied = !(mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED); + RefPtr effect = CreateTexturedEffect(mFrontBuffer->GetFormat(), + mTextureSource.get(), + aFilter, + isAlphaPremultiplied); if (!effect) { return; } aEffectChain.mPrimaryEffect = effect; - IntSize textureSize = source->GetSize(); + IntSize textureSize = mTextureSource->GetSize(); gfx::Rect gfxPictureRect = mHasPictureRect ? gfx::Rect(0, 0, mPictureRect.width, mPictureRect.height) : gfx::Rect(0, 0, textureSize.width, textureSize.height); @@ -123,7 +126,7 @@ ImageHost::Composite(EffectChain& aEffectChain, gfx::Rect pictureRect(0, 0, mPictureRect.width, mPictureRect.height); - BigImageIterator* it = source->AsBigImageIterator(); + BigImageIterator* it = mTextureSource->AsBigImageIterator(); if (it) { // This iteration does not work if we have multiple texture sources here @@ -139,7 +142,7 @@ ImageHost::Composite(EffectChain& aEffectChain, // the corresponding source tiles from all planes, with appropriate // per-plane per-tile texture coords. // DrawQuad currently assumes that all planes use the same texture coords. - MOZ_ASSERT(it->GetTileCount() == 1 || !source->GetNextSibling(), + MOZ_ASSERT(it->GetTileCount() == 1 || !mTextureSource->GetNextSibling(), "Can't handle multi-plane BigImages"); it->BeginBigImageIteration(); @@ -170,7 +173,7 @@ ImageHost::Composite(EffectChain& aEffectChain, gfxPictureRect, aClipRect, aTransform, mFlashCounter); } else { - IntSize textureSize = source->GetSize(); + IntSize textureSize = mTextureSource->GetSize(); gfx::Rect rect; if (mHasPictureRect) { effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width, @@ -273,18 +276,10 @@ ImageHost::Unlock() mLocked = false; } -TemporaryRef -ImageHost::GetTextureSource() -{ - MOZ_ASSERT(mLocked); - return mFrontBuffer->GetTextureSources(); -} - TemporaryRef ImageHost::GenEffect(const gfx::Filter& aFilter) { - RefPtr source = GetTextureSource(); - if (!source) { + if (!mFrontBuffer->BindTextureSource(mTextureSource)) { return nullptr; } bool isAlphaPremultiplied = true; @@ -292,7 +287,7 @@ ImageHost::GenEffect(const gfx::Filter& aFilter) isAlphaPremultiplied = false; return CreateTexturedEffect(mFrontBuffer->GetFormat(), - source, + mTextureSource, aFilter, isAlphaPremultiplied); } diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index ad12d229f049..e7524ebf7d20 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -45,8 +45,6 @@ public: virtual CompositableType GetType() { return mTextureInfo.mCompositableType; } - virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE; - virtual void Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, @@ -84,13 +82,12 @@ public: virtual void Unlock() MOZ_OVERRIDE; - virtual TemporaryRef GetTextureSource(); - virtual TemporaryRef GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE; protected: RefPtr mFrontBuffer; + CompositableTextureSourceRef mTextureSource; nsIntRect mPictureRect; bool mHasPictureRect; bool mLocked; diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 4af143eb1bba..cd6b4156ff52 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -144,6 +144,13 @@ TextureHost::GetIPDLActor() return mActor; } +bool +TextureHost::BindTextureSource(CompositableTextureSourceRef& texture) +{ + texture = GetTextureSources(); + return !!texture; +} + FenceHandle TextureHost::GetAndResetReleaseFenceHandle() { @@ -277,18 +284,6 @@ TextureHost::CompositorRecycle() static_cast(mActor)->CompositorRecycle(); } -void -TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) -{ - mCompositableBackendData = aBackendData; -} - -void -TextureHost::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) -{ - mCompositableBackendData = nullptr; -} - TextureHost::TextureHost(TextureFlags aFlags) : mActor(nullptr) , mFlags(aFlags) @@ -322,9 +317,11 @@ TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) } TextureSource::TextureSource() +: mCompositableCount(0) { MOZ_COUNT_CTOR(TextureSource); } + TextureSource::~TextureSource() { MOZ_COUNT_DTOR(TextureSource); @@ -844,8 +841,9 @@ SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor GLenum target = surf->ConsTextureTarget(); GLuint tex = surf->ConsTexture(gl); - texSource = new GLTextureSource(compositorOGL, tex, format, target, - surf->mSize); + texSource = new GLTextureSource(compositorOGL, tex, target, + surf->mSize, format, + true/*externally owned*/); break; } case gl::SharedSurfaceType::EGLImageShare: { @@ -860,8 +858,9 @@ SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor GLuint tex = 0; surf->AcquireConsumerTexture(gl, &tex, &target); - texSource = new GLTextureSource(compositorOGL, tex, format, target, - surf->mSize); + texSource = new GLTextureSource(compositorOGL, tex, target, + surf->mSize, format, + true/*externally owned*/); break; } #ifdef XP_MACOSX diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 0b8ba4c3d07f..f0c2ec38eb9b 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -46,7 +46,6 @@ namespace layers { class Compositor; class CompositableHost; -class CompositableBackendSpecificData; class CompositableParentManager; class SurfaceDescriptor; class SharedSurfaceDescriptor; @@ -150,10 +149,69 @@ public: return nullptr; } + void AddCompositableRef() { ++mCompositableCount; } + + void ReleaseCompositableRef() { + --mCompositableCount; + MOZ_ASSERT(mCompositableCount >= 0); + } + + int NumCompositableRefs() const { return mCompositableCount; } + protected: virtual ~TextureSource(); RefPtr mNextSibling; + int mCompositableCount; +}; + +/** + * equivalent of a RefPtr, that calls AddCompositableRef and + * ReleaseCompositableRef in addition to the usual AddRef and Release. + */ +class CompositableTextureSourceRef { +public: + CompositableTextureSourceRef() {} + + ~CompositableTextureSourceRef() + { + if (mRef) { + mRef->ReleaseCompositableRef(); + } + } + + CompositableTextureSourceRef& operator=(const TemporaryRef& aOther) + { + RefPtr temp = aOther; + if (temp) { + temp->AddCompositableRef(); + } + if (mRef) { + mRef->ReleaseCompositableRef(); + } + mRef = temp; + return *this; + } + + CompositableTextureSourceRef& operator=(TextureSource* aOther) + { + if (aOther) { + aOther->AddCompositableRef(); + } + if (mRef) { + mRef->ReleaseCompositableRef(); + } + mRef = aOther; + return *this; + } + + TextureSource* get() const { return mRef; } + operator TextureSource*() const { return mRef; } + TextureSource* operator->() const { return mRef; } + TextureSource& operator*() const { return *mRef; } + +private: + RefPtr mRef; }; /** @@ -302,6 +360,25 @@ public: */ virtual TextureSource* GetTextureSources() = 0; + /** + * Called during the transaction. The TextureSource may or may not be composited. + * + * Note that this is called outside of lock/unlock. + */ + virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) {} + + /** + * Called at composition time, just before compositing the TextureSource composited. + * + * Note that this is called only withing lock/unlock. + */ + virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture); + + /** + * Called when another TextureHost will take over. + */ + virtual void UnbindTextureSource() {} + /** * Is called before compositing if the shared data has changed since last * composition. @@ -406,10 +483,6 @@ public: return LayerRenderState(); } - virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData); - - virtual void UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData); - // If a texture host holds a reference to shmem, it should override this method // to forget about the shmem _without_ releasing it. virtual void OnShutdown() {} @@ -435,7 +508,6 @@ public: protected: PTextureParent* mActor; TextureFlags mFlags; - RefPtr mCompositableBackendData; friend class TextureParent; }; diff --git a/gfx/layers/opengl/GrallocTextureHost.cpp b/gfx/layers/opengl/GrallocTextureHost.cpp index c34d00074fb4..6ec86604ae26 100644 --- a/gfx/layers/opengl/GrallocTextureHost.cpp +++ b/gfx/layers/opengl/GrallocTextureHost.cpp @@ -136,17 +136,6 @@ GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) gl()->fActiveTexture(aTextureUnit); gl()->fBindTexture(textureTarget, tex); - if (mTextureBackendSpecificData) { - // There are two paths for locking/unlocking - if mTextureBackendSpecificData is - // set, we use the texture on there, otherwise we use - // CompositorBackendSpecificData from the compositor and bind the EGLImage - // only in Lock(). - if (!mEGLImage) { - mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer()); - } - BindEGLImage(); - } - ApplyFilterToBoundTexture(gl(), aFilter, textureTarget); #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 @@ -159,10 +148,6 @@ GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) bool GrallocTextureSourceOGL::Lock() { - if (mTextureBackendSpecificData) { - return true; - } - MOZ_ASSERT(IsValid()); if (!IsValid()) { return false; @@ -188,7 +173,7 @@ bool GrallocTextureSourceOGL::Lock() bool GrallocTextureSourceOGL::IsValid() const { - return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mTextureBackendSpecificData); + return !!gl() && !!mGraphicBuffer.get() && !!mCompositor; } gl::GLContext* @@ -230,62 +215,6 @@ GrallocTextureSourceOGL::GetTextureTarget() const return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat()); } -void -GrallocTextureSourceOGL::SetTextureBackendSpecificData(TextureSharedDataGonkOGL* aBackendData) -{ - if (!aBackendData) { - DeallocateDeviceData(); - // Update mTextureBackendSpecificData after calling DeallocateDeviceData(). - mTextureBackendSpecificData = nullptr; - return; - } - - if (mTextureBackendSpecificData != aBackendData) { - mNeedsReset = true; - } - - if (!gl() || !gl()->MakeCurrent()) { - NS_WARNING("Failed to make the context current"); - return; - } - - if (!mNeedsReset) { - // Update binding to the EGLImage - GLuint tex = GetGLTexture(); - GLuint textureTarget = GetTextureTarget(); - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(textureTarget, tex); - BindEGLImage(); - return; - } - - if (!mCompositor) { - mTextureBackendSpecificData = aBackendData; - return; - } - - // delete old EGLImage - DeallocateDeviceData(); - - // Update mTextureBackendSpecificData after calling DeallocateDeviceData(). - mTextureBackendSpecificData = aBackendData; - - GLuint tex = GetGLTexture(); - GLuint textureTarget = GetTextureTarget(); - - gl()->fActiveTexture(LOCAL_GL_TEXTURE0); - gl()->fBindTexture(textureTarget, tex); - - // Setup texure parameters at the first binding. - gl()->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_T, GetWrapMode()); - gl()->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_S, GetWrapMode()); - - // create new EGLImage - mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer()); - BindEGLImage(); - mNeedsReset = false; -} - gfx::IntSize GrallocTextureSourceOGL::GetSize() const { @@ -304,9 +233,6 @@ GrallocTextureSourceOGL::DeallocateDeviceData() if (!gl() || !gl()->MakeCurrent()) { return; } - if (mTextureBackendSpecificData) { - mTextureBackendSpecificData->ClearBoundEGLImage(mEGLImage); - } EGLImageDestroy(gl(), mEGLImage); mEGLImage = EGL_NO_IMAGE; } @@ -315,49 +241,48 @@ GrallocTextureSourceOGL::DeallocateDeviceData() GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags, const NewSurfaceDescriptorGralloc& aDescriptor) : TextureHost(aFlags) + , mGrallocHandle(aDescriptor) + , mSize(0, 0) + , mDescriptorSize(aDescriptor.size()) + , mFormat(gfx::SurfaceFormat::UNKNOWN) + , mEGLImage(EGL_NO_IMAGE) { - gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN; - mGrallocHandle = aDescriptor; - android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); MOZ_ASSERT(graphicBuffer); - mSize = aDescriptor.size(); if (graphicBuffer) { - format = + mFormat = SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(), aFlags & TextureFlags::RB_SWAPPED); - mTextureSource = new GrallocTextureSourceOGL(nullptr, - this, - graphicBuffer, - format); + mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight()); } else { printf_stderr("gralloc buffer is nullptr"); } } GrallocTextureHostOGL::~GrallocTextureHostOGL() -{ - MOZ_ASSERT(!mTextureSource || (mFlags & TextureFlags::DEALLOCATE_CLIENT), - "Leaking our buffer"); -} +{} void GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor) { - if (mTextureSource) { - mTextureSource->SetCompositor(static_cast(aCompositor)); + mCompositor = static_cast(aCompositor); + if (mTilingTextureSource) { + mTilingTextureSource->SetCompositor(mCompositor); + } + if (mGLTextureSource) { + mGLTextureSource->SetCompositor(mCompositor); + } + + if (mCompositor && aCompositor != mCompositor) { + DestroyEGLImage(); } } bool GrallocTextureHostOGL::Lock() { - if (IsValid()) { - mTextureSource->Lock(); - return true; - } - return false; + return IsValid(); } void @@ -369,28 +294,29 @@ GrallocTextureHostOGL::Unlock() bool GrallocTextureHostOGL::IsValid() const { - if (!mTextureSource) { - return false; - } - return mTextureSource->IsValid(); + android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); + return graphicBuffer != nullptr; } gfx::SurfaceFormat GrallocTextureHostOGL::GetFormat() const { - if (!mTextureSource) { - return gfx::SurfaceFormat::UNKNOWN; - } - return mTextureSource->GetFormat(); + return mFormat; } void GrallocTextureHostOGL::DeallocateSharedData() { - if (mTextureSource) { - mTextureSource->ForgetBuffer(); - mTextureSource = nullptr; + if (mTilingTextureSource) { + mTilingTextureSource->ForgetBuffer(); + mTilingTextureSource = nullptr; } + if (mGLTextureSource) { + mGLTextureSource = nullptr; + } + + DestroyEGLImage(); + if (mGrallocHandle.buffer().type() != SurfaceDescriptor::Tnull_t) { MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer(); base::ProcessId owner; @@ -408,24 +334,33 @@ GrallocTextureHostOGL::DeallocateSharedData() void GrallocTextureHostOGL::ForgetSharedData() { - if (mTextureSource) { - mTextureSource->ForgetBuffer(); - mTextureSource = nullptr; + if (mTilingTextureSource) { + mTilingTextureSource->ForgetBuffer(); + mTilingTextureSource = nullptr; + } + if (mGLTextureSource) { + mGLTextureSource = nullptr; } } void GrallocTextureHostOGL::DeallocateDeviceData() { - if (mTextureSource) { - mTextureSource->DeallocateDeviceData(); + if (mTilingTextureSource) { + mTilingTextureSource->DeallocateDeviceData(); } + if (mGLTextureSource) { + mGLTextureSource = nullptr; + } + DestroyEGLImage(); } LayerRenderState GrallocTextureHostOGL::GetRenderState() { - if (IsValid()) { + android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); + + if (graphicBuffer) { LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT; if (mFlags & TextureFlags::NEEDS_Y_FLIP) { flags |= LayerRenderStateFlags::Y_FLIPPED; @@ -433,8 +368,8 @@ GrallocTextureHostOGL::GetRenderState() if (mFlags & TextureFlags::RB_SWAPPED) { flags |= LayerRenderStateFlags::FORMAT_RB_SWAP; } - return LayerRenderState(mTextureSource->mGraphicBuffer.get(), - gfx::ThebesIntSize(mSize), + return LayerRenderState(graphicBuffer, + gfx::ThebesIntSize(mDescriptorSize), flags, this); } @@ -444,8 +379,8 @@ GrallocTextureHostOGL::GetRenderState() TemporaryRef GrallocTextureHostOGL::GetAsSurface() { - return mTextureSource ? mTextureSource->GetAsSurface() - : nullptr; + return mTilingTextureSource ? mTilingTextureSource->GetAsSurface() + : nullptr; } TemporaryRef @@ -473,103 +408,186 @@ GrallocTextureSourceOGL::GetAsSurface() { GLuint GrallocTextureSourceOGL::GetGLTexture() { - if (mTextureBackendSpecificData) { - mTextureBackendSpecificData->SetCompositor(mCompositor); - return mTextureBackendSpecificData->GetTexture(); - } - return mTexture; } void GrallocTextureSourceOGL::BindEGLImage() { - if (mTextureBackendSpecificData) { - mTextureBackendSpecificData->BindEGLImage(GetTextureTarget(), mEGLImage); + gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage); +} + +TextureSource* +GrallocTextureHostOGL::GetTextureSources() +{ + // This is now only used with tiled layers, and will eventually be removed. + // Other layer types use BindTextureSource instead. + MOZ_ASSERT(!mGLTextureSource); + if (!mTilingTextureSource) { + android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); + MOZ_ASSERT(graphicBuffer); + if (!graphicBuffer) { + return nullptr; + } + mTilingTextureSource = new GrallocTextureSourceOGL(mCompositor, this, + graphicBuffer, mFormat); + } + mTilingTextureSource->Lock(); + return mTilingTextureSource; +} + +void +GrallocTextureHostOGL::UnbindTextureSource() +{ + // Clear the reference to the TextureSource (if any), because we know that + // another TextureHost is being bound to the TextureSource. This means that + // we will have to re-do gl->fEGLImageTargetTexture2D next time we go through + // BindTextureSource (otherwise we would have skipped it). + // Note that this doesn't "unlock" the gralloc buffer or force it to be + // detached, Although decreasing the refcount of the TextureSource may lead + // to the gl handle being destroyed, which would unlock the gralloc buffer. + // That said, this method is called before another TextureHost attaches to the + // TextureSource, which has the effect of unlocking the gralloc buffer. So when + // this is called we know we are going to be unlocked soon. + mGLTextureSource = nullptr; +} + +GLenum GetTextureTarget(gl::GLContext* aGL, android::PixelFormat aFormat) { + MOZ_ASSERT(aGL); + if (aGL->Renderer() == gl::GLRenderer::SGX530 || + aGL->Renderer() == gl::GLRenderer::SGX540) { + // SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will + // result in black pixels when trying to draw from bound textures. + // Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on + // performance. + // See Bug 950050. + return LOCAL_GL_TEXTURE_EXTERNAL; } else { - gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage); + return TextureTargetForAndroidPixelFormat(aFormat); } } void -GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) +GrallocTextureHostOGL::DestroyEGLImage() { - if(!aBackendData) { - return; + // Only called when we want to get rid of the gralloc buffer, usually + // around the end of life of the TextureHost. + if (mEGLImage != EGL_NO_IMAGE && GetGLContext()) { + EGLImageDestroy(GetGLContext(), mEGLImage); + mEGLImage = EGL_NO_IMAGE; } - - // Update mTextureBackendSpecificData if it is not set yet. - if (!mTextureBackendSpecificData) { - MOZ_ASSERT(!mCompositableBackendData); - mCompositableBackendData = aBackendData; - CompositableDataGonkOGL* backend = static_cast(mCompositableBackendData.get()); - mTextureBackendSpecificData = backend->GetTextureBackendSpecificData(); - } - - // If TextureHost sharing by multiple CompositableHosts are detected, - // enable mBackendDatas usage. - if (!mBackendDatas && - mCompositableBackendData && - mCompositableBackendData != aBackendData && - mTextureBackendSpecificData->IsAllowingSharingTextureHost()) - { - mBackendDatas = MakeUnique > >(); - (*mBackendDatas)[mCompositableBackendData->GetId()] = mCompositableBackendData; - mCompositableBackendData = nullptr; - - // Get new mTextureBackendSpecificData - mTextureBackendSpecificData = - mTextureBackendSpecificData->GetNewTextureBackendSpecificData(mTextureSource->GetEGLImage()); - mTextureBackendSpecificData->SetOwnedByTextureHost(); - } - - // Update mCompositableBackendData. - if (mBackendDatas) - { - // Handle a case that TextureHost has ownership of TextureSharedDataGonkOGL. - MOZ_ASSERT(aBackendData->IsAllowingSharingTextureHost()); - (*mBackendDatas)[aBackendData->GetId()] = aBackendData; - if (mBackendDatas->size() > 200) { - NS_WARNING("Too many CompositableBackends"); - } - } else { - // Handle a case that CompositableHost has ownership of TextureSharedDataGonkOGL. - mCompositableBackendData = aBackendData; - CompositableDataGonkOGL* backend = static_cast(mCompositableBackendData.get()); - mTextureBackendSpecificData = backend->GetTextureBackendSpecificData(); - } - - if (mTextureSource) { - mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData); - } - } void -GrallocTextureHostOGL::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) +GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) { - if(!aBackendData || - !mTextureBackendSpecificData) { + // This happens during the layers transaction. + // All of the gralloc magic goes here. The only thing that happens externally + // and that is good to keep in mind is that when the TextureSource is deleted, + // it destroys its gl texture handle which is important for genlock. + + // If this TextureHost's mGLTextureSource member is non-null, it means we are + // still bound to the TextureSource, in which case we can skip the driver + // overhead of binding the texture again (fEGLImageTargetTexture2D) + // As a result, if the TextureHost is used with several CompositableHosts, + // it will be bound to only one TextureSource, and we'll do the driver work + // only once, which is great. This means that all of the compositables that + // use this TextureHost will keep a reference to this TextureSource at least + // for the duration of this frame. + + // If the compositable already has a TextureSource (the aTextureSource parameter), + // that is compatible and is not in use by several compositable, we try to + // attach to it. This has the effect of unlocking the previous TextureHost that + // we attached to the TextureSource (the previous frame) + + // If the TextureSource used by the compositable is also used by other + // compositables (see NumCompositableRefs), we have to create a new TextureSource, + // because otherwise we would be modifying the content of every layer that uses + // the TextureSource in question, even thoug they don't use this TextureHost. + + MOZ_ASSERT(!mTilingTextureSource); + + android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get(); + + MOZ_ASSERT(graphicBuffer); + if (!graphicBuffer) { + mGLTextureSource = nullptr; return; } - if (mBackendDatas) - { - // Handle a case that TextureHost has ownership of TextureSharedDataGonkOGL. - mBackendDatas->erase(aBackendData->GetId()); - if (mBackendDatas->size() == 0) { - mCompositableBackendData = nullptr; - mTextureBackendSpecificData = nullptr; - } - } else { - // Handle a case that CompositableHost has ownership of TextureSharedDataGonkOGL. - mCompositableBackendData = nullptr; - mTextureBackendSpecificData = nullptr; + if (mGLTextureSource && !mGLTextureSource->IsValid()) { + mGLTextureSource = nullptr; } - if (mTextureSource) { - mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData); + if (mGLTextureSource) { + // We are already attached to a TextureSource, nothing to do except tell + // the compositable to use it. + aTextureSource = mGLTextureSource.get(); + return; } + + gl::GLContext* gl = GetGLContext(); + if (!gl || !gl->MakeCurrent()) { + mGLTextureSource = nullptr; + return; + } + + if (mEGLImage == EGL_NO_IMAGE) { + // Should only happen the first time. + mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer()); + } + + GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat()); + + GLTextureSource* glSource = aTextureSource.get() ? + aTextureSource->AsSourceOGL()->AsGLTextureSource() : nullptr; + + bool shouldCreateTextureSource = !glSource || !glSource->IsValid() + || glSource->NumCompositableRefs() > 1 + || glSource->GetTextureTarget() != textureTarget; + + if (shouldCreateTextureSource) { + GLuint textureHandle; + gl->fGenTextures(1, &textureHandle); + gl->fBindTexture(textureTarget, textureHandle); + gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage); + + mGLTextureSource = new GLTextureSource(mCompositor, textureHandle, textureTarget, + mSize, mFormat); + aTextureSource = mGLTextureSource.get(); + } else { + gl->fBindTexture(textureTarget, glSource->GetTextureHandle()); + + gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage); + glSource->SetSize(mSize); + glSource->SetFormat(mFormat); + mGLTextureSource = glSource; + } +} + +bool +GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource) +{ + // This happens at composition time. + + // If mGLTextureSource is null it means PrepareTextureSource failed. + if (!mGLTextureSource) { + return false; + } + + // If Prepare didn't fail, we expect our TextureSource to be the same as aTextureSource, + // otherwise it means something has fiddled with the TextureSource between Prepare and + // now. + MOZ_ASSERT(mGLTextureSource == aTextureSource); + aTextureSource = mGLTextureSource.get(); + +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 + // Wait until it's ready. + WaitAcquireFenceSyncComplete(); +#endif + return true; } } // namepsace layers diff --git a/gfx/layers/opengl/GrallocTextureHost.h b/gfx/layers/opengl/GrallocTextureHost.h index 55500c6ec06a..aad2799b74e0 100644 --- a/gfx/layers/opengl/GrallocTextureHost.h +++ b/gfx/layers/opengl/GrallocTextureHost.h @@ -17,6 +17,7 @@ namespace layers { class GrallocTextureHostOGL; +// Progressively getting replaced by GLTextureSource class GrallocTextureSourceOGL : public TextureSource , public TextureSourceOGL { @@ -47,8 +48,6 @@ public: return LOCAL_GL_CLAMP_TO_EDGE; } - virtual void SetTextureBackendSpecificData(TextureSharedDataGonkOGL* aBackendData); - void DeallocateDeviceData(); gl::GLContext* gl() const; @@ -75,7 +74,6 @@ public: bool Lock(); protected: - RefPtr mTextureBackendSpecificData; RefPtr mCompositor; GrallocTextureHostOGL* mTextureHost; android::sp mGraphicBuffer; @@ -113,14 +111,17 @@ public: virtual gfx::SurfaceFormat GetFormat() const; - virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; } + virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mDescriptorSize; } virtual LayerRenderState GetRenderState() MOZ_OVERRIDE; - virtual TextureSource* GetTextureSources() MOZ_OVERRIDE - { - return mTextureSource; - } + virtual void PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE; + + virtual bool BindTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE; + + virtual void UnbindTextureSource() MOZ_OVERRIDE; + + virtual TextureSource* GetTextureSources() MOZ_OVERRIDE; #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE @@ -131,21 +132,27 @@ public: virtual TemporaryRef GetAsSurface() MOZ_OVERRIDE; - virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE; - - virtual void UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE; - bool IsValid() const; virtual const char* Name() MOZ_OVERRIDE { return "GrallocTextureHostOGL"; } -private: - NewSurfaceDescriptorGralloc mGrallocHandle; - RefPtr mTextureSource; - gfx::IntSize mSize; // See comment in textureClientOGL.h + gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; } - RefPtr mTextureBackendSpecificData; - UniquePtr > > mBackendDatas; +private: + void DestroyEGLImage(); + + NewSurfaceDescriptorGralloc mGrallocHandle; + RefPtr mGLTextureSource; + RefPtr mCompositor; + // only used for tiling, will be removed. + RefPtr mTilingTextureSource; + // Size reported by the GraphicBuffer + gfx::IntSize mSize; + // Size reported by TextureClient, can be different in some cases (video?), + // used by LayerRenderState. + gfx::IntSize mDescriptorSize; + gfx::SurfaceFormat mFormat; + EGLImage mEGLImage; }; } // namespace layers diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index 2394c822bc3b..0dd4cb935d47 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -40,16 +40,6 @@ namespace layers { class Compositor; -TemporaryRef -CreateCompositableBackendSpecificDataOGL() -{ -#ifdef MOZ_WIDGET_GONK - return new CompositableDataGonkOGL(); -#else - return nullptr; -#endif -} - TemporaryRef CreateTextureHostOGL(const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, @@ -119,174 +109,6 @@ FlagsToGLFlags(TextureFlags aFlags) return static_cast(result); } -CompositableDataGonkOGL::CompositableDataGonkOGL() -{ -} - -CompositableDataGonkOGL::~CompositableDataGonkOGL() -{ - ClearData(); -} - -void -CompositableDataGonkOGL::ClearData() -{ - CompositableBackendSpecificData::ClearData(); - mTextureBackendSpecificData = nullptr; - mCompositor = nullptr; -} - -void -CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor) -{ - mCompositor = static_cast(aCompositor); - if (mTextureBackendSpecificData) { - mTextureBackendSpecificData->SetCompositor(aCompositor); - } -} - -TextureSharedDataGonkOGL* -CompositableDataGonkOGL::GetTextureBackendSpecificData() -{ - if (!mTextureBackendSpecificData) { - mTextureBackendSpecificData = new TextureSharedDataGonkOGL(); - mTextureBackendSpecificData->SetCompositor(mCompositor); - mTextureBackendSpecificData->SetAllowSharingTextureHost(IsAllowingSharingTextureHost()); - } - return mTextureBackendSpecificData; -} - -TextureSharedDataGonkOGL::TextureSharedDataGonkOGL() - : mOwnedByCompositableHost(true) - , mAllowSharingTextureHost(false) - , mTexture(0) - , mBoundEGLImage(EGL_NO_IMAGE) -{ -} - -TextureSharedDataGonkOGL::TextureSharedDataGonkOGL(GLuint aTexture, EGLImage aImage, CompositorOGL* aCompositor) - : mOwnedByCompositableHost(true) - , mAllowSharingTextureHost(false) - , mCompositor(aCompositor) - , mTexture(aTexture) - , mBoundEGLImage(aImage) -{ -} - -TextureSharedDataGonkOGL::~TextureSharedDataGonkOGL() -{ - DeleteTextureIfPresent(); -} - -gl::GLContext* -TextureSharedDataGonkOGL::gl() const -{ - return mCompositor ? mCompositor->gl() : nullptr; -} - -void -TextureSharedDataGonkOGL::SetCompositor(Compositor* aCompositor) -{ - if (gl() && mCompositor != aCompositor) { - DeleteTextureIfPresent(); - } - mCompositor = static_cast(aCompositor); -} - -void -TextureSharedDataGonkOGL::ClearData() -{ - DeleteTextureIfPresent(); -} - -TemporaryRef -TextureSharedDataGonkOGL::GetNewTextureBackendSpecificData(EGLImage aImage) -{ - MOZ_ASSERT(IsAllowingSharingTextureHost()); - - if (IsEGLImageBound(aImage)) - { - // If EGLImage is already bound to OpenGL Texture, - // handover the OpenGL Texture to caller - GLuint textureId = GetAndResetGLTextureOwnership(); - RefPtr data = new TextureSharedDataGonkOGL(textureId, aImage, mCompositor); - data->SetCompositor(mCompositor); - data->SetAllowSharingTextureHost(true); - return data; - } - - // Create brand new TextureSharedDataGonkOGL - RefPtr data = new TextureSharedDataGonkOGL(); - data->SetCompositor(mCompositor); - data->SetAllowSharingTextureHost(true); - return data; -} - -GLuint -TextureSharedDataGonkOGL::GetTexture() -{ - if (!mTexture) { - if (gl() && gl()->MakeCurrent()) { - gl()->fGenTextures(1, &mTexture); - } - } - return mTexture; -} - -GLuint -TextureSharedDataGonkOGL::GetAndResetGLTextureOwnership() -{ - GLuint texture = mTexture; - mTexture = 0; - mBoundEGLImage = EGL_NO_IMAGE; - return texture; -} - -void -TextureSharedDataGonkOGL::DeleteTextureIfPresent() -{ - if (mTexture) { - MOZ_ASSERT(mCompositor); - if (gl() && gl()->MakeCurrent()) { - gl()->fDeleteTextures(1, &mTexture); - } - mTexture = 0; - mBoundEGLImage = EGL_NO_IMAGE; - } -} - -void -TextureSharedDataGonkOGL::BindEGLImage(GLuint aTarget, EGLImage aImage) -{ - if (mBoundEGLImage != aImage) { - MOZ_ASSERT(gl()); - if (gl()) { - gl()->fEGLImageTargetTexture2D(aTarget, aImage); - } - mBoundEGLImage = aImage; - } -} - -void -TextureSharedDataGonkOGL::ClearBoundEGLImage(EGLImage aImage) -{ - if (mBoundEGLImage == aImage) { - DeleteTextureIfPresent(); - mBoundEGLImage = EGL_NO_IMAGE; - } -} - -bool -TextureSharedDataGonkOGL::IsEGLImageBound(EGLImage aImage) -{ - if (mTexture != 0 && - aImage != EGL_NO_IMAGE && - aImage == mBoundEGLImage) { - return true; - } - return false; -} - #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 bool TextureHostOGL::SetReleaseFence(const android::sp& aReleaseFence) @@ -529,27 +351,56 @@ TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilt // GLTextureSource GLTextureSource::GLTextureSource(CompositorOGL* aCompositor, - GLuint aTex, - gfx::SurfaceFormat aFormat, + GLuint aTextureHandle, GLenum aTarget, - gfx::IntSize aSize) - : mSize(aSize) - , mCompositor(aCompositor) - , mTex(aTex) - , mFormat(aFormat) + gfx::IntSize aSize, + gfx::SurfaceFormat aFormat, + bool aExternallyOwned) + : mCompositor(aCompositor) + , mTextureHandle(aTextureHandle) , mTextureTarget(aTarget) + , mSize(aSize) + , mFormat(aFormat) + , mExternallyOwned(aExternallyOwned) { + MOZ_COUNT_CTOR(GLTextureSource); +} + +GLTextureSource::~GLTextureSource() +{ + MOZ_COUNT_DTOR(GLTextureSource); + if (!mExternallyOwned) { + DeleteTextureHandle(); + } +} + +void +GLTextureSource::DeallocateDeviceData() +{ + if (!mExternallyOwned) { + DeleteTextureHandle(); + } +} + +void +GLTextureSource::DeleteTextureHandle() +{ + if (mTextureHandle != 0 && gl() && gl()->MakeCurrent()) { + gl()->fDeleteTextures(1, &mTextureHandle); + } + mTextureHandle = 0; } void GLTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) { + MOZ_ASSERT(gl()); + MOZ_ASSERT(mTextureHandle != 0); if (!gl()) { - NS_WARNING("Trying to bind a texture without a GLContext"); return; } gl()->fActiveTexture(aTextureUnit); - gl()->fBindTexture(mTextureTarget, mTex); + gl()->fBindTexture(mTextureTarget, mTextureHandle); ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget); } @@ -562,7 +413,7 @@ GLTextureSource::SetCompositor(Compositor* aCompositor) bool GLTextureSource::IsValid() const { - return !!gl(); + return !!gl() && mTextureHandle != 0; } gl::GLContext* @@ -614,6 +465,10 @@ SurfaceTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter) void SurfaceTextureSource::SetCompositor(Compositor* aCompositor) { + if (mCompositor != aCompositor) { + DeallocateDeviceData(); + } + mCompositor = static_cast(aCompositor); } diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 7407002eff43..ca2b19a15855 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -58,99 +58,7 @@ class Compositor; class CompositorOGL; class TextureImageTextureSourceOGL; class TextureSharedDataGonkOGL; - -/** - * CompositableBackendSpecificData implementation for the Gonk OpenGL backend. - * Share a same texture between TextureHosts in the same CompositableHost. - * By shareing the texture among the TextureHosts, number of texture allocations - * can be reduced than texture allocation in every TextureHosts. - * From Bug 912134, use only one texture among all TextureHosts degrade - * the rendering performance. - * CompositableDataGonkOGL chooses in a middile of them. - */ -class CompositableDataGonkOGL : public CompositableBackendSpecificData -{ -protected: - virtual ~CompositableDataGonkOGL(); - -public: - CompositableDataGonkOGL(); - virtual void ClearData() MOZ_OVERRIDE; - virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; - - TextureSharedDataGonkOGL* GetTextureBackendSpecificData(); -protected: - nsRefPtr mTextureBackendSpecificData; - RefPtr mCompositor; -}; - -/** - * Manage actual shared resources of CompositableDataGonkOGL. - * The resources are split from CompositableDataGonkOGL to handle two use cases. - * Normally TextureHost is used from one CompositableHost at the same time. - * In this case, performance is good if the resources are owned by CompositableDataGonkOGL. - * But TextureHost could be shared among multiple ImageHosts. - * If it happens, performance is good if the resource is owned by TextureHost. - * The resources ownership is carryed over from CompositableDataGonkOGL to TextureHost. - * See Bug 1017351. - */ -class TextureSharedDataGonkOGL -{ -protected: - virtual ~TextureSharedDataGonkOGL(); - -public: - NS_INLINE_DECL_REFCOUNTING(TextureSharedDataGonkOGL) - - TextureSharedDataGonkOGL(); - TextureSharedDataGonkOGL(GLuint aTexture, EGLImage aImage, CompositorOGL* aCompositor); - - void SetCompositor(Compositor* aCompositor); - void ClearData(); - - // Mark TextureSharedDataGonkOGL as owned by TextureHost. - void SetOwnedByTextureHost() - { - mOwnedByCompositableHost = false; - } - - // Check if this is owned by CompositableHost or TextureHost. - bool IsOwnedByCompositableHost() - { - return mOwnedByCompositableHost; - } - - bool IsAllowingSharingTextureHost() - { - return mAllowSharingTextureHost; - } - - void SetAllowSharingTextureHost(bool aAllow) - { - mAllowSharingTextureHost = aAllow; - } - - // Create new TextureSharedDataGonkOGL. - // If aImage is already bound to OpenGL texture, the OpenGL textre is carried over - // to a new object. It could reduce calling fEGLImageTargetTexture2D() - // during resources ownership carry over from CompositableHost to TextureHost. - TemporaryRef GetNewTextureBackendSpecificData(EGLImage aImage); - - GLuint GetTexture(); - void DeleteTextureIfPresent(); - gl::GLContext* gl() const; - void BindEGLImage(GLuint aTarget, EGLImage aImage); - void ClearBoundEGLImage(EGLImage aImage); - bool IsEGLImageBound(EGLImage aImage); -protected: - GLuint GetAndResetGLTextureOwnership(); - - bool mOwnedByCompositableHost; - bool mAllowSharingTextureHost; - RefPtr mCompositor; - GLuint mTexture; - EGLImage mBoundEGLImage; -}; +class GLTextureSource; inline void ApplyFilterToBoundTexture(gl::GLContext* aGL, gfx::Filter aFilter, @@ -205,6 +113,8 @@ public: virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return nullptr; } + virtual GLTextureSource* AsGLTextureSource() { return nullptr; } + void SetFilter(gl::GLContext* aGL, gfx::Filter aFilter) { if (mHasCachedFilter && @@ -373,10 +283,15 @@ class GLTextureSource : public TextureSource { public: GLTextureSource(CompositorOGL* aCompositor, - GLuint aTex, - gfx::SurfaceFormat aFormat, + GLuint aTextureHandle, GLenum aTarget, - gfx::IntSize aSize); + gfx::IntSize aSize, + gfx::SurfaceFormat aFormat, + bool aExternallyOwned = false); + + ~GLTextureSource(); + + virtual GLTextureSource* AsGLTextureSource() MOZ_OVERRIDE { return this; } virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; } @@ -392,18 +307,29 @@ public: virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; } - virtual void DeallocateDeviceData() MOZ_OVERRIDE {} + virtual void DeallocateDeviceData() MOZ_OVERRIDE; virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE; + void SetSize(gfx::IntSize aSize) { mSize = aSize; } + + void SetFormat(gfx::SurfaceFormat aFormat) { mFormat = aFormat; } + + GLuint GetTextureHandle() const { return mTextureHandle; } + gl::GLContext* gl() const; protected: - const gfx::IntSize mSize; + void DeleteTextureHandle(); + RefPtr mCompositor; - const GLuint mTex; - const gfx::SurfaceFormat mFormat; - const GLenum mTextureTarget; + GLuint mTextureHandle; + GLenum mTextureTarget; + gfx::IntSize mSize; + gfx::SurfaceFormat mFormat; + // If the texture is externally owned, the gl handle will not be deleted + // in the destructor. + bool mExternallyOwned; }; ////////////////////////////////////////////////////////////////////////