--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -131,16 +131,27 @@ class LayerManagerComposite;
enum SurfaceInitMode
{
INIT_MODE_NONE,
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.
*
* Compositor provides a cross-platform interface to a set of operations for
* compositing quads. Compositor knows nothing about the layer tree. It must be
* told everything about each composited quad - contents, location, transform,
* opacity, etc.
*
* In theory it should be possible for different widgets to use the same
@@ -465,16 +476,20 @@ public:
fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
if (fillRatio > 999.0f) {
fillRatio = 999.0f;
}
}
return fillRatio;
}
+ virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() {
+ return nullptr;
+ }
+
ScreenRotation GetScreenRotation() const {
return mScreenRotation;
}
void SetScreenRotation(ScreenRotation aRotation) {
mScreenRotation = aRotation;
}
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -19,16 +19,24 @@
#include "gfxPlatform.h" // for gfxPlatform
#include "mozilla/layers/PCompositableParent.h"
namespace mozilla {
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.
*
* CompositableParent is owned by the IPDL system. It's deletion is triggered
* by either the CompositableChild's deletion, or by the IPDL communication
* goind down.
*/
@@ -74,16 +82,19 @@ CompositableHost::CompositableHost(const
, mKeepAttached(false)
{
MOZ_COUNT_CTOR(CompositableHost);
}
CompositableHost::~CompositableHost()
{
MOZ_COUNT_DTOR(CompositableHost);
+ if (mBackendData) {
+ mBackendData->ClearData();
+ }
}
PCompositableParent*
CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr,
const TextureInfo& aTextureInfo,
uint64_t aID)
{
return new CompositableParent(aMgr, aTextureInfo, aID);
@@ -105,61 +116,69 @@ CompositableHost::FromIPDLActor(PComposi
void
CompositableHost::UseTextureHost(TextureHost* aTexture)
{
if (!aTexture) {
return;
}
aTexture->SetCompositor(GetCompositor());
+ aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite)
{
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)
{
mCompositor = aCompositor;
}
bool
CompositableHost::AddMaskEffect(EffectChain& aEffects,
const gfx::Matrix4x4& aTransform,
bool aIs3D)
{
- CompositableTextureSourceRef source;
+ RefPtr<TextureSource> source;
RefPtr<TextureHost> host = GetAsTextureHost();
if (!host) {
NS_WARNING("Using compositable with no valid TextureHost as mask");
return false;
}
if (!host->Lock()) {
NS_WARNING("Failed to lock the mask texture");
return false;
}
- if (!host->BindTextureSource(source)) {
+ source = host->GetTextureSources();
+ MOZ_ASSERT(source);
+
+ if (!source) {
NS_WARNING("The TextureHost was successfully locked but can't provide a TextureSource");
host->Unlock();
return false;
}
- MOZ_ASSERT(source);
RefPtr<EffectMask> effect = new EffectMask(source,
source->GetSize(),
aTransform);
effect->mIs3D = aIs3D;
aEffects.mSecondaryEffects[EffectTypes::MASK] = effect;
return true;
}
@@ -168,16 +187,19 @@ void
CompositableHost::RemoveMaskEffect()
{
RefPtr<TextureHost> host = GetAsTextureHost();
if (host) {
host->Unlock();
}
}
+// implemented in TextureHostOGL.cpp
+TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL();
+
/* static */ TemporaryRef<CompositableHost>
CompositableHost::Create(const TextureInfo& aTextureInfo)
{
RefPtr<CompositableHost> result;
switch (aTextureInfo.mCompositableType) {
case CompositableType::BUFFER_BRIDGE:
NS_ERROR("Cannot create an image bridge compositable this way");
break;
@@ -200,16 +222,22 @@ CompositableHost::Create(const TextureIn
result = new ContentHostSingleBuffered(aTextureInfo);
break;
case CompositableType::CONTENT_DOUBLE:
result = new ContentHostDoubleBuffered(aTextureInfo);
break;
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<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
+ result->SetCompositableBackendSpecificData(data);
+ }
return result;
}
#ifdef MOZ_DUMP_PAINTING
void
CompositableHost::DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture)
{
if (!aTexture) {
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -45,16 +45,52 @@ class Compositor;
class ISurfaceAllocator;
class ThebesBufferData;
class TiledLayerComposer;
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
* composited (tiling, double buffering, etc.).
*
* Update (for images/canvases) and UpdateThebes (for Thebes) are called during
* the layers transaction to update the Compositbale's textures from the
* content side. The actual update (and any syncronous upload) is done by the
* TextureHost, but it is coordinated by the CompositableHost.
@@ -71,16 +107,26 @@ protected:
public:
NS_INLINE_DECL_REFCOUNTING(CompositableHost)
explicit CompositableHost(const TextureInfo& aTextureInfo);
static TemporaryRef<CompositableHost> Create(const TextureInfo& aTextureInfo);
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);
// composite the contents of this buffer host to the compositor's surface
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
@@ -201,16 +247,19 @@ public:
virtual void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS)
{
if (!mKeepAttached ||
aLayer == mLayer ||
aFlags & FORCE_DETACH) {
SetLayer(nullptr);
mAttached = false;
mKeepAttached = false;
+ if (mBackendData) {
+ mBackendData->ClearData();
+ }
}
}
bool IsAttached() { return mAttached; }
#ifdef MOZ_DUMP_PAINTING
virtual void Dump(std::stringstream& aStream,
const char* aPrefix="",
bool aDumpHtml=false) { }
@@ -260,16 +309,17 @@ public:
}
protected:
TextureInfo mTextureInfo;
uint64_t mAsyncID;
uint64_t mCompositorID;
RefPtr<Compositor> mCompositor;
Layer* mLayer;
+ RefPtr<CompositableBackendSpecificData> mBackendData;
uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true.
bool mAttached;
bool mKeepAttached;
};
class AutoLockCompositableHost MOZ_FINAL
{
public:
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -30,42 +30,38 @@ ContentHostBase::ContentHostBase(const T
, mInitialised(false)
{}
ContentHostBase::~ContentHostBase()
{
}
void
-ContentHostTexture::Composite(EffectChain& aEffectChain,
- float aOpacity,
- const gfx::Matrix4x4& aTransform,
- const Filter& aFilter,
- const Rect& aClipRect,
- const nsIntRegion* aVisibleRegion)
+ContentHostBase::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 (!mTextureHost->BindTextureSource(mTextureSource)) {
- return;
- }
- MOZ_ASSERT(mTextureSource.get());
+ RefPtr<TextureSource> source = GetTextureSource();
+ RefPtr<TextureSource> sourceOnWhite = GetTextureSourceOnWhite();
- if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
+ if (!source) {
return;
}
- RefPtr<TexturedEffect> effect = CreateTexturedEffect(mTextureSource.get(),
- mTextureSourceOnWhite.get(),
- aFilter, true);
+ RefPtr<TexturedEffect> effect = GenEffect(aFilter);
if (!effect) {
return;
}
aEffectChain.mPrimaryEffect = effect;
nsIntRegion tmpRegion;
const nsIntRegion* renderRegion;
@@ -80,17 +76,17 @@ ContentHostTexture::Composite(EffectChai
}
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 = mTextureSource->GetSize();
+ gfx::IntSize texSize = source->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;
}
@@ -104,24 +100,24 @@ ContentHostTexture::Composite(EffectChai
nsIntRect regionRect = *iterRect;
nsIntRect screenRect = regionRect;
screenRect.MoveBy(origin);
screenRects.Or(screenRects, screenRect);
regionRects.Or(regionRects, regionRect);
}
- BigImageIterator* bigImgIter = mTextureSource->AsBigImageIterator();
+ BigImageIterator* bigImgIter = source->AsBigImageIterator();
BigImageIterator* iterOnWhite = nullptr;
if (bigImgIter) {
bigImgIter->BeginBigImageIteration();
}
- if (mTextureSourceOnWhite) {
- iterOnWhite = mTextureSourceOnWhite->AsBigImageIterator();
+ if (sourceOnWhite) {
+ iterOnWhite = sourceOnWhite->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);
@@ -204,49 +200,42 @@ ContentHostTexture::Composite(EffectChai
DiagnosticFlags diagnostics = DiagnosticFlags::CONTENT;
if (iterOnWhite) {
diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
}
GetCompositor()->DrawDiagnostics(diagnostics, nsIntRegion(mBufferRect), aClipRect,
aTransform, mFlashCounter);
}
+TemporaryRef<TexturedEffect>
+ContentHostBase::GenEffect(const gfx::Filter& aFilter)
+{
+ RefPtr<TextureSource> source = GetTextureSource();
+ RefPtr<TextureSource> 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;
- 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) {
- mTextureHost->PrepareTextureSource(mTextureSourceOnWhite);
- }
}
void
ContentHostTexture::SetCompositor(Compositor* aCompositor)
{
ContentHostBase::SetCompositor(aCompositor);
if (mTextureHost) {
mTextureHost->SetCompositor(aCompositor);
@@ -424,186 +413,16 @@ ContentHostIncremental::UpdateIncrementa
aSurface,
aUpdated,
aBufferRect,
aBufferRotation));
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<TexturedEffect> 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()
{
// If we're not compositing for some reason (the window being minimized
// is one example), then we never process these updates and it can consume
// huge amounts of memory. Instead we forcibly process the updates (during the
// transaction) if the list gets too long.
static const uint32_t kMaxUpdateCount = 6;
if (mUpdateList.Length() >= kMaxUpdateCount) {
@@ -615,16 +434,30 @@ void
ContentHostIncremental::ProcessTextureUpdates()
{
for (uint32_t i = 0; i < mUpdateList.Length(); i++) {
mUpdateList[i]->Execute(this);
}
mUpdateList.Clear();
}
+TextureSource*
+ContentHostIncremental::GetTextureSource()
+{
+ MOZ_ASSERT(mLocked);
+ return mSource;
+}
+
+TextureSource*
+ContentHostIncremental::GetTextureSourceOnWhite()
+{
+ MOZ_ASSERT(mLocked);
+ return mSourceOnWhite;
+}
+
void
ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental* aHost)
{
Compositor* compositor = aHost->GetCompositor();
MOZ_ASSERT(compositor);
RefPtr<DataTextureSource> temp =
compositor->CreateDataTextureSource(mTextureInfo.mTextureFlags);
@@ -845,42 +678,16 @@ ContentHostTexture::GetRenderState()
if (mBufferRotation != nsIntPoint()) {
result.mFlags |= LayerRenderStateFlags::BUFFER_ROTATION;
}
result.SetOffset(GetOriginOffset());
return result;
}
-TemporaryRef<TexturedEffect>
-ContentHostTexture::GenEffect(const gfx::Filter& aFilter)
-{
- if (!mTextureHost) {
- return nullptr;
- }
- if (!mTextureHost->BindTextureSource(mTextureSource)) {
- return nullptr;
- }
- if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
- return nullptr;
- }
- return CreateTexturedEffect(mTextureSource.get(),
- mTextureSourceOnWhite.get(),
- aFilter, true);
-}
-
-TemporaryRef<TexturedEffect>
-ContentHostIncremental::GenEffect(const gfx::Filter& aFilter)
-{
- if (!mSource) {
- return nullptr;
- }
- return CreateTexturedEffect(mSource, mSourceOnWhite, aFilter, true);
-}
-
#ifdef MOZ_DUMP_PAINTING
TemporaryRef<gfx::DataSourceSurface>
ContentHostTexture::GetAsSurface()
{
if (!mTextureHost) {
return nullptr;
}
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -91,16 +91,28 @@ class ContentHostBase : public ContentHo
{
public:
typedef RotatedContentBuffer::ContentType ContentType;
typedef RotatedContentBuffer::PaintState PaintState;
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<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
+
protected:
virtual nsIntPoint GetOriginOffset()
{
return mBufferRect.TopLeft() - mBufferRotation;
}
nsIntRect mBufferRect;
@@ -115,23 +127,16 @@ protected:
class ContentHostTexture : public ContentHostBase
{
public:
explicit ContentHostTexture(const TextureInfo& aTextureInfo)
: ContentHostBase(aTextureInfo)
, 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
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
virtual void Dump(std::stringstream& aStream,
const char* aPrefix="",
bool aDumpHtml=false) MOZ_OVERRIDE;
@@ -163,25 +168,33 @@ public:
MOZ_ASSERT(mLocked);
mTextureHost->Unlock();
if (mTextureHostOnWhite) {
mTextureHostOnWhite->Unlock();
}
mLocked = false;
}
- LayerRenderState GetRenderState();
+ 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;
+ }
- virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
+ LayerRenderState GetRenderState();
protected:
RefPtr<TextureHost> mTextureHost;
RefPtr<TextureHost> mTextureHostOnWhite;
- CompositableTextureSourceRef mTextureSource;
- CompositableTextureSourceRef mTextureSourceOnWhite;
bool mLocked;
};
/**
* Double buffering is implemented by swapping the front and back TextureHosts.
* We assume that whenever we use double buffering, then we have
* render-to-texture and thus no texture upload to do.
*/
@@ -259,39 +272,32 @@ public:
const nsIntRegion& aUpdated,
const nsIntRegion& aOldValidRegionBack,
nsIntRegion* aUpdatedRegionBack)
{
NS_ERROR("Shouldn't call this");
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 {
MOZ_ASSERT(!mLocked);
ProcessTextureUpdates();
mLocked = true;
return true;
}
virtual void Unlock() MOZ_OVERRIDE {
MOZ_ASSERT(mLocked);
mLocked = false;
}
- virtual TemporaryRef<TexturedEffect>
- GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
+ virtual TextureSource* GetTextureSource() MOZ_OVERRIDE;
+ virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE;
private:
void FlushUpdateQueue();
void ProcessTextureUpdates();
class Request
{
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -32,40 +32,46 @@ ImageHost::ImageHost(const TextureInfo&
, mFrontBuffer(nullptr)
, mHasPictureRect(false)
, mLocked(false)
{}
ImageHost::~ImageHost()
{
if (mFrontBuffer) {
- mFrontBuffer->UnbindTextureSource();
+ mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
+ }
+}
+
+void
+ImageHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+{
+ CompositableHost::SetCompositableBackendSpecificData(aBackendData);
+ // ImageHost allows TextureHost sharing among ImageHosts.
+ if (aBackendData) {
+ aBackendData->SetAllowSharingTextureHost(true);
}
}
void
ImageHost::UseTextureHost(TextureHost* aTexture)
{
- if (mFrontBuffer && mFrontBuffer != aTexture) {
- mFrontBuffer->UnbindTextureSource();
+ CompositableHost::UseTextureHost(aTexture);
+ if (mFrontBuffer) {
+ mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
- CompositableHost::UseTextureHost(aTexture);
mFrontBuffer = aTexture;
- if (mFrontBuffer) {
- mFrontBuffer->PrepareTextureSource(mTextureSource);
- }
}
void
ImageHost::RemoveTextureHost(TextureHost* aTexture)
{
CompositableHost::RemoveTextureHost(aTexture);
if (aTexture && mFrontBuffer == aTexture) {
- mFrontBuffer->UnbindTextureSource();
- mTextureSource = nullptr;
+ aTexture->SetCompositableBackendSpecificData(nullptr);
mFrontBuffer = nullptr;
}
}
TextureHost*
ImageHost::GetAsTextureHost()
{
return mFrontBuffer;
@@ -86,68 +92,59 @@ ImageHost::Composite(EffectChain& aEffec
return;
}
if (!mFrontBuffer) {
return;
}
// 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;
}
-
- if (!mFrontBuffer->BindTextureSource(mTextureSource)) {
+ RefPtr<TextureSource> source = GetTextureSource();
+ if (!source) {
return;
}
- if (!mTextureSource) {
- // BindTextureSource above should have returned false!
- MOZ_ASSERT(false);
- return;
- }
-
- bool isAlphaPremultiplied = !(mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED);
- RefPtr<TexturedEffect> effect = CreateTexturedEffect(mFrontBuffer->GetFormat(),
- mTextureSource.get(),
- aFilter,
- isAlphaPremultiplied);
+ RefPtr<TexturedEffect> effect = GenEffect(aFilter);
if (!effect) {
return;
}
aEffectChain.mPrimaryEffect = effect;
- IntSize textureSize = mTextureSource->GetSize();
+ IntSize textureSize = source->GetSize();
gfx::Rect gfxPictureRect
= mHasPictureRect ? gfx::Rect(0, 0, mPictureRect.width, mPictureRect.height)
: gfx::Rect(0, 0, textureSize.width, textureSize.height);
gfx::Rect pictureRect(0, 0,
mPictureRect.width,
mPictureRect.height);
- BigImageIterator* it = mTextureSource->AsBigImageIterator();
+ BigImageIterator* it = source->AsBigImageIterator();
if (it) {
// This iteration does not work if we have multiple texture sources here
// (e.g. 3 YCbCr textures). There's nothing preventing the different
// planes from having different resolutions or tile sizes. For example, a
// YCbCr frame could have Cb and Cr planes that are half the resolution of
// the Y plane, in such a way that the Y plane overflows the maximum
// texture size and the Cb and Cr planes do not. Then the Y plane would be
// split into multiple tiles and the Cb and Cr planes would just be one
// tile each.
// To handle the general case correctly, we'd have to create a grid of
// intersected tiles over all planes, and then draw each grid tile using
// 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 || !mTextureSource->GetNextSibling(),
+ MOZ_ASSERT(it->GetTileCount() == 1 || !source->GetNextSibling(),
"Can't handle multi-plane BigImages");
it->BeginBigImageIteration();
do {
nsIntRect tileRect = it->GetTileRect();
gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
if (mHasPictureRect) {
rect = rect.Intersect(pictureRect);
@@ -168,17 +165,17 @@ ImageHost::Composite(EffectChain& aEffec
rect, aClipRect, aTransform, mFlashCounter);
} while (it->NextTile());
it->EndBigImageIteration();
// layer border
GetCompositor()->DrawDiagnostics(DiagnosticFlags::IMAGE,
gfxPictureRect, aClipRect,
aTransform, mFlashCounter);
} else {
- IntSize textureSize = mTextureSource->GetSize();
+ IntSize textureSize = source->GetSize();
gfx::Rect rect;
if (mHasPictureRect) {
effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
Float(mPictureRect.y) / textureSize.height,
Float(mPictureRect.width) / textureSize.width,
Float(mPictureRect.height) / textureSize.height);
rect = pictureRect;
} else {
@@ -271,28 +268,36 @@ ImageHost::Lock()
void
ImageHost::Unlock()
{
MOZ_ASSERT(mLocked);
mFrontBuffer->Unlock();
mLocked = false;
}
+TemporaryRef<TextureSource>
+ImageHost::GetTextureSource()
+{
+ MOZ_ASSERT(mLocked);
+ return mFrontBuffer->GetTextureSources();
+}
+
TemporaryRef<TexturedEffect>
ImageHost::GenEffect(const gfx::Filter& aFilter)
{
- if (!mFrontBuffer->BindTextureSource(mTextureSource)) {
+ RefPtr<TextureSource> source = GetTextureSource();
+ if (!source) {
return nullptr;
}
bool isAlphaPremultiplied = true;
if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED)
isAlphaPremultiplied = false;
return CreateTexturedEffect(mFrontBuffer->GetFormat(),
- mTextureSource,
+ source,
aFilter,
isAlphaPremultiplied);
}
#ifdef MOZ_WIDGET_GONK
ImageHostOverlay::ImageHostOverlay(const TextureInfo& aTextureInfo)
: CompositableHost(aTextureInfo)
, mHasPictureRect(false)
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -40,16 +40,18 @@ struct EffectChain;
class ImageHost : public CompositableHost
{
public:
explicit ImageHost(const TextureInfo& aTextureInfo);
~ImageHost();
virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
+ virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
+
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr) MOZ_OVERRIDE;
virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
@@ -77,22 +79,23 @@ public:
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
#endif
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
+ virtual TemporaryRef<TextureSource> GetTextureSource();
+
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
protected:
RefPtr<TextureHost> mFrontBuffer;
- CompositableTextureSourceRef mTextureSource;
nsIntRect mPictureRect;
bool mHasPictureRect;
bool mLocked;
};
#ifdef MOZ_WIDGET_GONK
/**
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -139,23 +139,16 @@ TextureHost::AsTextureHost(PTextureParen
}
PTextureParent*
TextureHost::GetIPDLActor()
{
return mActor;
}
-bool
-TextureHost::BindTextureSource(CompositableTextureSourceRef& texture)
-{
- texture = GetTextureSources();
- return !!texture;
-}
-
FenceHandle
TextureHost::GetAndResetReleaseFenceHandle()
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
TextureHostOGL* hostOGL = this->AsHostOGL();
if (!hostOGL) {
return FenceHandle();
}
@@ -279,16 +272,28 @@ void
TextureHost::CompositorRecycle()
{
if (!mActor) {
return;
}
static_cast<TextureParent*>(mActor)->CompositorRecycle();
}
+void
+TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+{
+ mCompositableBackendData = aBackendData;
+}
+
+void
+TextureHost::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+{
+ mCompositableBackendData = nullptr;
+}
+
TextureHost::TextureHost(TextureFlags aFlags)
: mActor(nullptr)
, mFlags(aFlags)
{}
TextureHost::~TextureHost()
{
}
@@ -312,21 +317,19 @@ TextureHost::PrintInfo(std::stringstream
AppendToString(aStream, GetSize(), " [size=", "]");
AppendToString(aStream, GetFormat(), " [format=", "]");
Unlock();
}
AppendToString(aStream, mFlags, " [flags=", "]");
}
TextureSource::TextureSource()
-: mCompositableCount(0)
{
MOZ_COUNT_CTOR(TextureSource);
}
-
TextureSource::~TextureSource()
{
MOZ_COUNT_DTOR(TextureSource);
}
BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
TextureFlags aFlags)
: TextureHost(aFlags)
@@ -835,36 +838,34 @@ SharedSurfaceToTexSource(gl::SharedSurfa
auto surf = gl::SharedSurface_GLTexture::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
GLenum target = surf->ConsTextureTarget();
GLuint tex = surf->ConsTexture(gl);
- texSource = new GLTextureSource(compositorOGL, tex, target,
- surf->mSize, format,
- true/*externally owned*/);
+ texSource = new GLTextureSource(compositorOGL, tex, format, target,
+ surf->mSize);
break;
}
case gl::SharedSurfaceType::EGLImageShare: {
auto surf = gl::SharedSurface_EGLImage::Cast(abstractSurf);
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
gl::GLContext* gl = compositorOGL->gl();
MOZ_ASSERT(gl->IsCurrent());
GLenum target = 0;
GLuint tex = 0;
surf->AcquireConsumerTexture(gl, &tex, &target);
- texSource = new GLTextureSource(compositorOGL, tex, target,
- surf->mSize, format,
- true/*externally owned*/);
+ texSource = new GLTextureSource(compositorOGL, tex, format, target,
+ surf->mSize);
break;
}
#ifdef XP_MACOSX
case gl::SharedSurfaceType::IOSurface: {
auto surf = gl::SharedSurface_IOSurface::Cast(abstractSurf);
MacIOSurface* ioSurf = surf->GetIOSurface();
MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -41,16 +41,17 @@ class SharedSurface;
namespace ipc {
class Shmem;
}
namespace layers {
class Compositor;
class CompositableHost;
+class CompositableBackendSpecificData;
class CompositableParentManager;
class SurfaceDescriptor;
class SharedSurfaceDescriptor;
class ISurfaceAllocator;
class TextureHostOGL;
class TextureSourceOGL;
class TextureSourceD3D9;
class TextureSourceD3D11;
@@ -144,79 +145,20 @@ public:
switch (index) {
case 0: return this;
case 1: return GetNextSibling();
case 2: return GetNextSibling() ? GetNextSibling()->GetNextSibling() : nullptr;
}
return nullptr;
}
- void AddCompositableRef() { ++mCompositableCount; }
-
- void ReleaseCompositableRef() {
- --mCompositableCount;
- MOZ_ASSERT(mCompositableCount >= 0);
- }
-
- int NumCompositableRefs() const { return mCompositableCount; }
-
protected:
virtual ~TextureSource();
RefPtr<TextureSource> mNextSibling;
- int mCompositableCount;
-};
-
-/**
- * equivalent of a RefPtr<TextureSource>, 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<TextureSource>& aOther)
- {
- RefPtr<TextureSource> 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<TextureSource> mRef;
};
/**
* Interface for TextureSources that can be updated from a DataSourceSurface.
*
* All backend should implement at least one DataTextureSource.
*/
class DataTextureSource : public TextureSource
@@ -356,35 +298,16 @@ public:
*
* This can trigger texture uploads, so do not call it inside transactions
* so as to not upload textures while the main thread is blocked.
* Must not be called while this TextureHost is not sucessfully Locked.
*/
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.
* This method should be overload in cases like when we need to do a texture
* upload for example.
*
* @param aRegion The region that has been changed, if nil, it means that the
* entire surface should be updated.
*/
@@ -478,16 +401,20 @@ public:
*/
virtual LayerRenderState GetRenderState()
{
// By default we return an empty render state, this should be overridden
// by the TextureHost implementations that are used on B2G with Composer2D
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() {}
// Forget buffer actor. Used only for hacky fix for bug 966446.
virtual void ForgetBufferActor() {}
virtual const char *Name() { return "TextureHost"; }
@@ -503,16 +430,17 @@ public:
/**
* Cast to a TextureHost for each backend.
*/
virtual TextureHostOGL* AsHostOGL() { return nullptr; }
protected:
PTextureParent* mActor;
TextureFlags mFlags;
+ RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
friend class TextureParent;
};
/**
* TextureHost that wraps a random access buffer such as a Shmem or some raw
* memory.
*
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -125,28 +125,43 @@ GrallocTextureSourceOGL::BindTexture(GLe
}
GLuint tex = GetGLTexture();
GLuint textureTarget = GetTextureTarget();
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
if (mTextureHost) {
// Wait until it's ready.
mTextureHost->WaitAcquireFenceSyncComplete();
}
#endif
}
bool GrallocTextureSourceOGL::Lock()
{
+ if (mTextureBackendSpecificData) {
+ return true;
+ }
+
MOZ_ASSERT(IsValid());
if (!IsValid()) {
return false;
}
if (!gl()->MakeCurrent()) {
NS_WARNING("Failed to make the gl context current");
return false;
}
@@ -162,17 +177,17 @@ bool GrallocTextureSourceOGL::Lock()
}
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
return true;
}
bool
GrallocTextureSourceOGL::IsValid() const
{
- return !!gl() && !!mGraphicBuffer.get() && !!mCompositor;
+ return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mTextureBackendSpecificData);
}
gl::GLContext*
GrallocTextureSourceOGL::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
@@ -204,16 +219,72 @@ GrallocTextureSourceOGL::GetTextureTarge
if (gl()->Renderer() == gl::GLRenderer::SGX530 ||
gl()->Renderer() == gl::GLRenderer::SGX540) {
return LOCAL_GL_TEXTURE_EXTERNAL;
}
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
{
if (!IsValid()) {
NS_WARNING("Trying to access the size of an invalid GrallocTextureSourceOGL");
return gfx::IntSize(0, 0);
}
return gfx::IntSize(mGraphicBuffer->getWidth(), mGraphicBuffer->getHeight());
@@ -222,100 +293,103 @@ GrallocTextureSourceOGL::GetSize() const
void
GrallocTextureSourceOGL::DeallocateDeviceData()
{
if (mEGLImage) {
MOZ_ASSERT(mCompositor);
if (!gl() || !gl()->MakeCurrent()) {
return;
}
+ if (mTextureBackendSpecificData) {
+ mTextureBackendSpecificData->ClearBoundEGLImage(mEGLImage);
+ }
EGLImageDestroy(gl(), mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}
}
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) {
- mFormat =
+ format =
SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
aFlags & TextureFlags::RB_SWAPPED);
- mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
+ mTextureSource = new GrallocTextureSourceOGL(nullptr,
+ this,
+ graphicBuffer,
+ format);
} else {
printf_stderr("gralloc buffer is nullptr");
}
}
GrallocTextureHostOGL::~GrallocTextureHostOGL()
-{}
+{
+ MOZ_ASSERT(!mTextureSource || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
+ "Leaking our buffer");
+}
void
GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
{
- mCompositor = static_cast<CompositorOGL*>(aCompositor);
- if (mTilingTextureSource) {
- mTilingTextureSource->SetCompositor(mCompositor);
- }
- if (mGLTextureSource) {
- mGLTextureSource->SetCompositor(mCompositor);
- }
-
- if (mCompositor && aCompositor != mCompositor) {
- DestroyEGLImage();
+ if (mTextureSource) {
+ mTextureSource->SetCompositor(static_cast<CompositorOGL*>(aCompositor));
}
}
bool
GrallocTextureHostOGL::Lock()
{
- return IsValid();
+ if (IsValid()) {
+ mTextureSource->Lock();
+ return true;
+ }
+ return false;
}
void
GrallocTextureHostOGL::Unlock()
{
// Unlock is done internally by binding the texture to another gralloc buffer
}
bool
GrallocTextureHostOGL::IsValid() const
{
- android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
- return graphicBuffer != nullptr;
+ if (!mTextureSource) {
+ return false;
+ }
+ return mTextureSource->IsValid();
}
gfx::SurfaceFormat
GrallocTextureHostOGL::GetFormat() const
{
- return mFormat;
+ if (!mTextureSource) {
+ return gfx::SurfaceFormat::UNKNOWN;
+ }
+ return mTextureSource->GetFormat();
}
void
GrallocTextureHostOGL::DeallocateSharedData()
{
- if (mTilingTextureSource) {
- mTilingTextureSource->ForgetBuffer();
- mTilingTextureSource = nullptr;
+ if (mTextureSource) {
+ mTextureSource->ForgetBuffer();
+ mTextureSource = nullptr;
}
- if (mGLTextureSource) {
- mGLTextureSource = nullptr;
- }
-
- DestroyEGLImage();
-
if (mGrallocHandle.buffer().type() != SurfaceDescriptor::Tnull_t) {
MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer();
base::ProcessId owner;
if (handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
owner = handle.get_GrallocBufferRef().mOwner;
}
else {
owner = handle.get_MagicGrallocBufferHandle().mRef.mOwner;
@@ -323,63 +397,54 @@ GrallocTextureHostOGL::DeallocateSharedD
SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
}
}
void
GrallocTextureHostOGL::ForgetSharedData()
{
- if (mTilingTextureSource) {
- mTilingTextureSource->ForgetBuffer();
- mTilingTextureSource = nullptr;
- }
- if (mGLTextureSource) {
- mGLTextureSource = nullptr;
+ if (mTextureSource) {
+ mTextureSource->ForgetBuffer();
+ mTextureSource = nullptr;
}
}
void
GrallocTextureHostOGL::DeallocateDeviceData()
{
- if (mTilingTextureSource) {
- mTilingTextureSource->DeallocateDeviceData();
+ if (mTextureSource) {
+ mTextureSource->DeallocateDeviceData();
}
- if (mGLTextureSource) {
- mGLTextureSource = nullptr;
- }
- DestroyEGLImage();
}
LayerRenderState
GrallocTextureHostOGL::GetRenderState()
{
- android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
-
- if (graphicBuffer) {
+ if (IsValid()) {
LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
if (mFlags & TextureFlags::NEEDS_Y_FLIP) {
flags |= LayerRenderStateFlags::Y_FLIPPED;
}
if (mFlags & TextureFlags::RB_SWAPPED) {
flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
}
- return LayerRenderState(graphicBuffer,
- gfx::ThebesIntSize(mDescriptorSize),
+ return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
+ gfx::ThebesIntSize(mSize),
flags,
this);
}
return LayerRenderState();
}
TemporaryRef<gfx::DataSourceSurface>
GrallocTextureHostOGL::GetAsSurface() {
- return mTilingTextureSource ? mTilingTextureSource->GetAsSurface()
- : nullptr;
+ return mTextureSource ? mTextureSource->GetAsSurface()
+ : nullptr;
}
TemporaryRef<gfx::DataSourceSurface>
GrallocTextureSourceOGL::GetAsSurface() {
if (!IsValid() || !gl()->MakeCurrent()) {
return nullptr;
}
@@ -397,192 +462,109 @@ GrallocTextureSourceOGL::GetAsSurface()
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
return surf.forget();
}
GLuint
GrallocTextureSourceOGL::GetGLTexture()
{
+ if (mTextureBackendSpecificData) {
+ mTextureBackendSpecificData->SetCompositor(mCompositor);
+ return mTextureBackendSpecificData->GetTexture();
+ }
+
return mTexture;
}
void
GrallocTextureSourceOGL::BindEGLImage()
{
- 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;
+ if (mTextureBackendSpecificData) {
+ mTextureBackendSpecificData->BindEGLImage(GetTextureTarget(), mEGLImage);
} else {
- return TextureTargetForAndroidPixelFormat(aFormat);
- }
-}
-
-void
-GrallocTextureHostOGL::DestroyEGLImage()
-{
- // 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;
+ gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
}
}
void
-GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextureSource)
+GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
{
- // 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 (mGLTextureSource && !mGLTextureSource->IsValid()) {
- mGLTextureSource = nullptr;
- }
-
- 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;
+ if(!aBackendData) {
return;
}
- if (mEGLImage == EGL_NO_IMAGE) {
- // Should only happen the first time.
- mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer());
+ // Update mTextureBackendSpecificData if it is not set yet.
+ if (!mTextureBackendSpecificData) {
+ MOZ_ASSERT(!mCompositableBackendData);
+ mCompositableBackendData = aBackendData;
+ CompositableDataGonkOGL* backend = static_cast<CompositableDataGonkOGL*>(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<std::map<uint64_t, RefPtr<CompositableBackendSpecificData> > >();
+ (*mBackendDatas)[mCompositableBackendData->GetId()] = mCompositableBackendData;
+ mCompositableBackendData = nullptr;
+
+ // Get new mTextureBackendSpecificData
+ mTextureBackendSpecificData =
+ mTextureBackendSpecificData->GetNewTextureBackendSpecificData(mTextureSource->GetEGLImage());
+ mTextureBackendSpecificData->SetOwnedByTextureHost();
}
- 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;
+ // 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<CompositableDataGonkOGL*>(mCompositableBackendData.get());
+ mTextureBackendSpecificData = backend->GetTextureBackendSpecificData();
+ }
- 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);
+ if (mTextureSource) {
+ mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
+ }
- 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)
+void
+GrallocTextureHostOGL::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
{
- // This happens at composition time.
-
- // If mGLTextureSource is null it means PrepareTextureSource failed.
- if (!mGLTextureSource) {
- return false;
+ if(!aBackendData ||
+ !mTextureBackendSpecificData) {
+ return;
}
- // 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 (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 defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
- // Wait until it's ready.
- WaitAcquireFenceSyncComplete();
-#endif
- return true;
+ if (mTextureSource) {
+ mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
+ }
}
} // namepsace layers
} // namepsace mozilla
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -12,17 +12,16 @@
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
#include <ui/GraphicBuffer.h>
namespace mozilla {
namespace layers {
class GrallocTextureHostOGL;
-// Progressively getting replaced by GLTextureSource
class GrallocTextureSourceOGL : public TextureSource
, public TextureSourceOGL
{
public:
friend class GrallocTextureHostOGL;
GrallocTextureSourceOGL(CompositorOGL* aCompositor,
GrallocTextureHostOGL* aTextureHost,
@@ -43,16 +42,18 @@ public:
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual GLenum GetWrapMode() const MOZ_OVERRIDE
{
return LOCAL_GL_CLAMP_TO_EDGE;
}
+ virtual void SetTextureBackendSpecificData(TextureSharedDataGonkOGL* aBackendData);
+
void DeallocateDeviceData();
gl::GLContext* gl() const;
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
void ForgetBuffer()
{
@@ -69,16 +70,17 @@ public:
EGLImage GetEGLImage()
{
return mEGLImage;
}
bool Lock();
protected:
+ RefPtr<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
RefPtr<CompositorOGL> mCompositor;
GrallocTextureHostOGL* mTextureHost;
android::sp<android::GraphicBuffer> mGraphicBuffer;
EGLImage mEGLImage;
GLuint mTexture;
gfx::SurfaceFormat mFormat;
bool mNeedsReset;
};
@@ -106,57 +108,48 @@ public:
virtual void DeallocateSharedData() MOZ_OVERRIDE;
virtual void ForgetSharedData() MOZ_OVERRIDE;
virtual void DeallocateDeviceData() MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const;
- virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mDescriptorSize; }
+ virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
- virtual void PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE;
-
- virtual bool BindTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE;
-
- virtual void UnbindTextureSource() MOZ_OVERRIDE;
-
- virtual TextureSource* GetTextureSources() MOZ_OVERRIDE;
+ virtual TextureSource* GetTextureSources() MOZ_OVERRIDE
+ {
+ return mTextureSource;
+ }
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
{
return this;
}
#endif
virtual TemporaryRef<gfx::DataSourceSurface> 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"; }
- gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; }
-
private:
- void DestroyEGLImage();
-
NewSurfaceDescriptorGralloc mGrallocHandle;
- RefPtr<GLTextureSource> mGLTextureSource;
- RefPtr<CompositorOGL> mCompositor;
- // only used for tiling, will be removed.
- RefPtr<GrallocTextureSourceOGL> 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;
+ RefPtr<GrallocTextureSourceOGL> mTextureSource;
+ gfx::IntSize mSize; // See comment in textureClientOGL.h
+
+ RefPtr<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
+ UniquePtr<std::map<uint64_t, RefPtr<CompositableBackendSpecificData> > > mBackendDatas;
};
} // namespace layers
} // namespace mozilla
#endif
#endif
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -35,16 +35,26 @@
using namespace mozilla::gl;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
class Compositor;
+TemporaryRef<CompositableBackendSpecificData>
+CreateCompositableBackendSpecificDataOGL()
+{
+#ifdef MOZ_WIDGET_GONK
+ return new CompositableDataGonkOGL();
+#else
+ return nullptr;
+#endif
+}
+
TemporaryRef<TextureHost>
CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
TextureFlags aFlags)
{
RefPtr<TextureHost> result;
switch (aDesc.type()) {
case SurfaceDescriptor::TSurfaceDescriptorShmem:
@@ -104,16 +114,184 @@ FlagsToGLFlags(TextureFlags aFlags)
if (aFlags & TextureFlags::NEEDS_Y_FLIP)
result |= TextureImage::NeedsYFlip;
if (aFlags & TextureFlags::DISALLOW_BIGIMAGE)
result |= TextureImage::DisallowBigImage;
return static_cast<gl::TextureImage::Flags>(result);
}
+CompositableDataGonkOGL::CompositableDataGonkOGL()
+{
+}
+
+CompositableDataGonkOGL::~CompositableDataGonkOGL()
+{
+ ClearData();
+}
+
+void
+CompositableDataGonkOGL::ClearData()
+{
+ CompositableBackendSpecificData::ClearData();
+ mTextureBackendSpecificData = nullptr;
+ mCompositor = nullptr;
+}
+
+void
+CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
+{
+ mCompositor = static_cast<CompositorOGL*>(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<CompositorOGL*>(aCompositor);
+}
+
+void
+TextureSharedDataGonkOGL::ClearData()
+{
+ DeleteTextureIfPresent();
+}
+
+TemporaryRef<TextureSharedDataGonkOGL>
+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<TextureSharedDataGonkOGL> data = new TextureSharedDataGonkOGL(textureId, aImage, mCompositor);
+ data->SetCompositor(mCompositor);
+ data->SetAllowSharingTextureHost(true);
+ return data;
+ }
+
+ // Create brand new TextureSharedDataGonkOGL
+ RefPtr<TextureSharedDataGonkOGL> 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<android::Fence>& aReleaseFence)
{
if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
// HWC might not provide Fence.
// In this case, HWC implicitly handles buffer's fence.
return false;
@@ -346,79 +524,50 @@ TextureImageTextureSourceOGL::BindTextur
mTexImage->BindTexture(aTextureUnit);
SetFilter(mGL, aFilter);
}
////////////////////////////////////////////////////////////////////////
// GLTextureSource
GLTextureSource::GLTextureSource(CompositorOGL* aCompositor,
- GLuint aTextureHandle,
- GLenum aTarget,
- gfx::IntSize aSize,
+ GLuint aTex,
gfx::SurfaceFormat aFormat,
- bool aExternallyOwned)
- : mCompositor(aCompositor)
- , mTextureHandle(aTextureHandle)
+ GLenum aTarget,
+ gfx::IntSize aSize)
+ : mSize(aSize)
+ , mCompositor(aCompositor)
+ , mTex(aTex)
+ , mFormat(aFormat)
, 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, mTextureHandle);
+ gl()->fBindTexture(mTextureTarget, mTex);
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
void
GLTextureSource::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
GLTextureSource::IsValid() const
{
- return !!gl() && mTextureHandle != 0;
+ return !!gl();
}
gl::GLContext*
GLTextureSource::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
@@ -462,20 +611,16 @@ SurfaceTextureSource::BindTexture(GLenum
mSurfTex->UpdateTexImage();
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
void
SurfaceTextureSource::SetCompositor(Compositor* aCompositor)
{
- if (mCompositor != aCompositor) {
- DeallocateDeviceData();
- }
-
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
SurfaceTextureSource::IsValid() const
{
return !!gl();
}
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -50,17 +50,109 @@ class DataSourceSurface;
}
namespace layers {
class Compositor;
class CompositorOGL;
class TextureImageTextureSourceOGL;
class TextureSharedDataGonkOGL;
-class GLTextureSource;
+
+/**
+ * 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<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
+ RefPtr<CompositorOGL> 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<TextureSharedDataGonkOGL> 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<CompositorOGL> mCompositor;
+ GLuint mTexture;
+ EGLImage mBoundEGLImage;
+};
inline void ApplyFilterToBoundTexture(gl::GLContext* aGL,
gfx::Filter aFilter,
GLuint aTarget = LOCAL_GL_TEXTURE_2D)
{
GLenum filter =
(aFilter == gfx::Filter::POINT ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR);
@@ -105,18 +197,16 @@ public:
virtual gfx::SurfaceFormat GetFormat() const = 0;
virtual GLenum GetWrapMode() const = 0;
virtual gfx::Matrix4x4 GetTextureTransform() { return gfx::Matrix4x4(); }
virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return nullptr; }
- virtual GLTextureSource* AsGLTextureSource() { return nullptr; }
-
void SetFilter(gl::GLContext* aGL, gfx::Filter aFilter)
{
if (mHasCachedFilter &&
mCachedFilter == aFilter) {
return;
}
mHasCachedFilter = true;
mCachedFilter = aFilter;
@@ -275,63 +365,47 @@ protected:
*
* The shared texture handle is owned by the TextureHost.
*/
class GLTextureSource : public TextureSource
, public TextureSourceOGL
{
public:
GLTextureSource(CompositorOGL* aCompositor,
- GLuint aTextureHandle,
- GLenum aTarget,
- gfx::IntSize aSize,
+ GLuint aTex,
gfx::SurfaceFormat aFormat,
- bool aExternallyOwned = false);
-
- ~GLTextureSource();
-
- virtual GLTextureSource* AsGLTextureSource() MOZ_OVERRIDE { return this; }
+ GLenum aTarget,
+ gfx::IntSize aSize);
virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE;
virtual bool IsValid() const MOZ_OVERRIDE;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual GLenum GetTextureTarget() const { return mTextureTarget; }
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:
- void DeleteTextureHandle();
-
+ const gfx::IntSize mSize;
RefPtr<CompositorOGL> mCompositor;
- 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;
+ const GLuint mTex;
+ const gfx::SurfaceFormat mFormat;
+ const GLenum mTextureTarget;
};
////////////////////////////////////////////////////////////////////////
// SurfaceTexture
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureSource : public TextureSource