--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -131,27 +131,16 @@ 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
@@ -476,20 +465,16 @@ 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,24 +19,16 @@
#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.
*/
@@ -82,19 +74,16 @@ 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);
@@ -116,69 +105,61 @@ 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)
{
- RefPtr<TextureSource> source;
+ CompositableTextureSourceRef 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;
}
- 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<EffectMask> effect = new EffectMask(source,
source->GetSize(),
aTransform);
effect->mIs3D = aIs3D;
aEffects.mSecondaryEffects[EffectTypes::MASK] = effect;
return true;
}
@@ -187,19 +168,16 @@ 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;
@@ -222,22 +200,16 @@ 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,52 +45,16 @@ 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.
@@ -107,26 +71,16 @@ 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,
@@ -247,19 +201,16 @@ 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) { }
@@ -309,17 +260,16 @@ 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,38 +30,42 @@ ContentHostBase::ContentHostBase(const T
, mInitialised(false)
{}
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");
AutoLockCompositableHost lock(this);
if (lock.Failed()) {
return;
}
- RefPtr<TextureSource> source = GetTextureSource();
- RefPtr<TextureSource> sourceOnWhite = GetTextureSourceOnWhite();
+ if (!mTextureHost->BindTextureSource(mTextureSource)) {
+ return;
+ }
+ MOZ_ASSERT(mTextureSource.get());
- if (!source) {
+ if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
return;
}
- RefPtr<TexturedEffect> effect = GenEffect(aFilter);
+ RefPtr<TexturedEffect> effect = CreateTexturedEffect(mTextureSource.get(),
+ mTextureSourceOnWhite.get(),
+ aFilter, true);
if (!effect) {
return;
}
aEffectChain.mPrimaryEffect = effect;
nsIntRegion tmpRegion;
const nsIntRegion* renderRegion;
@@ -76,17 +80,17 @@ ContentHostBase::Composite(EffectChain&
}
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 = source->GetSize();
+ gfx::IntSize texSize = mTextureSource->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;
}
@@ -100,24 +104,24 @@ ContentHostBase::Composite(EffectChain&
nsIntRect regionRect = *iterRect;
nsIntRect screenRect = regionRect;
screenRect.MoveBy(origin);
screenRects.Or(screenRects, screenRect);
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) {
iterOnWhite->BeginBigImageIteration();
}
}
bool usingTiles = (bigImgIter && bigImgIter->GetTileCount() > 1);
@@ -200,42 +204,49 @@ ContentHostBase::Composite(EffectChain&
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);
@@ -413,16 +424,186 @@ 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) {
@@ -434,30 +615,16 @@ 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);
@@ -678,16 +845,42 @@ 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,28 +91,16 @@ 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;
@@ -127,16 +115,23 @@ 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;
@@ -168,33 +163,25 @@ public:
MOZ_ASSERT(mLocked);
mTextureHost->Unlock();
if (mTextureHostOnWhite) {
mTextureHostOnWhite->Unlock();
}
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();
- LayerRenderState GetRenderState();
+ virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
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.
*/
@@ -272,32 +259,39 @@ 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 TextureSource* GetTextureSource() MOZ_OVERRIDE;
- virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE;
+ virtual TemporaryRef<TexturedEffect>
+ GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
private:
void FlushUpdateQueue();
void ProcessTextureUpdates();
class Request
{
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -32,46 +32,40 @@ ImageHost::ImageHost(const TextureInfo&
, mFrontBuffer(nullptr)
, mHasPictureRect(false)
, mLocked(false)
{}
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)
{
+ if (mFrontBuffer && mFrontBuffer != aTexture) {
+ mFrontBuffer->UnbindTextureSource();
+ }
CompositableHost::UseTextureHost(aTexture);
+ mFrontBuffer = aTexture;
if (mFrontBuffer) {
- mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
+ mFrontBuffer->PrepareTextureSource(mTextureSource);
}
- mFrontBuffer = aTexture;
}
void
ImageHost::RemoveTextureHost(TextureHost* aTexture)
{
CompositableHost::RemoveTextureHost(aTexture);
if (aTexture && mFrontBuffer == aTexture) {
- aTexture->SetCompositableBackendSpecificData(nullptr);
+ mFrontBuffer->UnbindTextureSource();
+ mTextureSource = nullptr;
mFrontBuffer = nullptr;
}
}
TextureHost*
ImageHost::GetAsTextureHost()
{
return mFrontBuffer;
@@ -92,59 +86,68 @@ 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;
}
- RefPtr<TextureSource> source = GetTextureSource();
- if (!source) {
+
+ if (!mFrontBuffer->BindTextureSource(mTextureSource)) {
return;
}
- RefPtr<TexturedEffect> effect = GenEffect(aFilter);
+ 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);
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);
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
// (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 || !source->GetNextSibling(),
+ MOZ_ASSERT(it->GetTileCount() == 1 || !mTextureSource->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);
@@ -165,17 +168,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 = source->GetSize();
+ IntSize textureSize = mTextureSource->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 {
@@ -268,36 +271,28 @@ 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)
{
- RefPtr<TextureSource> source = GetTextureSource();
- if (!source) {
+ if (!mFrontBuffer->BindTextureSource(mTextureSource)) {
return nullptr;
}
bool isAlphaPremultiplied = true;
if (mFrontBuffer->GetFlags() & TextureFlags::NON_PREMULTIPLIED)
isAlphaPremultiplied = false;
return CreateTexturedEffect(mFrontBuffer->GetFormat(),
- source,
+ mTextureSource,
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,18 +40,16 @@ 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;
@@ -79,23 +77,22 @@ 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,16 +139,23 @@ 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();
}
@@ -272,28 +279,16 @@ 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()
{
}
@@ -317,19 +312,21 @@ 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)
@@ -838,34 +835,36 @@ 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, format, target,
- surf->mSize);
+ texSource = new GLTextureSource(compositorOGL, tex, target,
+ surf->mSize, format,
+ true/*externally owned*/);
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, format, target,
- surf->mSize);
+ texSource = new GLTextureSource(compositorOGL, tex, target,
+ surf->mSize, format,
+ true/*externally owned*/);
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,17 +41,16 @@ 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;
@@ -145,20 +144,79 @@ 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
@@ -298,16 +356,35 @@ 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.
*/
@@ -401,20 +478,16 @@ 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"; }
@@ -430,17 +503,16 @@ 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,43 +125,28 @@ 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;
}
@@ -177,17 +162,17 @@ bool GrallocTextureSourceOGL::Lock()
}
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
return true;
}
bool
GrallocTextureSourceOGL::IsValid() const
{
- return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mTextureBackendSpecificData);
+ return !!gl() && !!mGraphicBuffer.get() && !!mCompositor;
}
gl::GLContext*
GrallocTextureSourceOGL::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
@@ -219,72 +204,16 @@ 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());
@@ -293,103 +222,100 @@ 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) {
- 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<CompositorOGL*>(aCompositor));
+ mCompositor = static_cast<CompositorOGL*>(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
GrallocTextureHostOGL::Unlock()
{
// Unlock is done internally by binding the texture to another gralloc buffer
}
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;
if (handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
owner = handle.get_GrallocBufferRef().mOwner;
}
else {
owner = handle.get_MagicGrallocBufferHandle().mRef.mOwner;
@@ -397,54 +323,63 @@ GrallocTextureHostOGL::DeallocateSharedD
SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
}
}
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;
}
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);
}
return LayerRenderState();
}
TemporaryRef<gfx::DataSourceSurface>
GrallocTextureHostOGL::GetAsSurface() {
- return mTextureSource ? mTextureSource->GetAsSurface()
- : nullptr;
+ return mTilingTextureSource ? mTilingTextureSource->GetAsSurface()
+ : nullptr;
}
TemporaryRef<gfx::DataSourceSurface>
GrallocTextureSourceOGL::GetAsSurface() {
if (!IsValid() || !gl()->MakeCurrent()) {
return nullptr;
}
@@ -462,109 +397,192 @@ 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()
{
- 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::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;
}
}
void
-GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextureSource)
{
- if(!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;
return;
}
- // 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();
+ if (mEGLImage == EGL_NO_IMAGE) {
+ // Should only happen the first time.
+ mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer());
}
- // 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");
- }
+ 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 {
- // Handle a case that CompositableHost has ownership of TextureSharedDataGonkOGL.
- mCompositableBackendData = aBackendData;
- CompositableDataGonkOGL* backend = static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get());
- mTextureBackendSpecificData = backend->GetTextureBackendSpecificData();
+ gl->fBindTexture(textureTarget, glSource->GetTextureHandle());
+
+ gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
+ glSource->SetSize(mSize);
+ glSource->SetFormat(mFormat);
+ mGLTextureSource = glSource;
}
-
- if (mTextureSource) {
- mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
- }
-
}
-void
-GrallocTextureHostOGL::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
+bool
+GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource)
{
- if(!aBackendData ||
- !mTextureBackendSpecificData) {
- return;
+ // This happens at composition time.
+
+ // If mGLTextureSource is null it means PrepareTextureSource failed.
+ if (!mGLTextureSource) {
+ return false;
}
- 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 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 (mTextureSource) {
- mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
- }
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+ // Wait until it's ready.
+ WaitAcquireFenceSyncComplete();
+#endif
+ return true;
}
} // namepsace layers
} // namepsace mozilla
--- a/gfx/layers/opengl/GrallocTextureHost.h
+++ b/gfx/layers/opengl/GrallocTextureHost.h
@@ -12,16 +12,17 @@
#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,
@@ -42,18 +43,16 @@ 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()
{
@@ -70,17 +69,16 @@ 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;
};
@@ -108,48 +106,57 @@ 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 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
{
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<GrallocTextureSourceOGL> mTextureSource;
- gfx::IntSize mSize; // See comment in textureClientOGL.h
-
- RefPtr<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
- UniquePtr<std::map<uint64_t, RefPtr<CompositableBackendSpecificData> > > mBackendDatas;
+ 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;
};
} // namespace layers
} // namespace mozilla
#endif
#endif
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -35,26 +35,16 @@
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:
@@ -114,184 +104,16 @@ 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;
@@ -524,50 +346,79 @@ TextureImageTextureSourceOGL::BindTextur
mTexImage->BindTexture(aTextureUnit);
SetFilter(mGL, aFilter);
}
////////////////////////////////////////////////////////////////////////
// GLTextureSource
GLTextureSource::GLTextureSource(CompositorOGL* aCompositor,
- GLuint aTex,
- gfx::SurfaceFormat aFormat,
+ GLuint aTextureHandle,
GLenum aTarget,
- gfx::IntSize aSize)
- : mSize(aSize)
- , mCompositor(aCompositor)
- , mTex(aTex)
+ gfx::IntSize aSize,
+ gfx::SurfaceFormat aFormat,
+ bool aExternallyOwned)
+ : mCompositor(aCompositor)
+ , mTextureHandle(aTextureHandle)
+ , mTextureTarget(aTarget)
+ , mSize(aSize)
, mFormat(aFormat)
- , mTextureTarget(aTarget)
+ , 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);
}
void
GLTextureSource::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
GLTextureSource::IsValid() const
{
- return !!gl();
+ return !!gl() && mTextureHandle != 0;
}
gl::GLContext*
GLTextureSource::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
@@ -611,16 +462,20 @@ 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,109 +50,17 @@ class DataSourceSurface;
}
namespace layers {
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<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;
-};
+class GLTextureSource;
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);
@@ -197,16 +105,18 @@ 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;
@@ -365,47 +275,63 @@ protected:
*
* The shared texture handle is owned by the TextureHost.
*/
class GLTextureSource : public TextureSource
, public TextureSourceOGL
{
public:
GLTextureSource(CompositorOGL* aCompositor,
- GLuint aTex,
+ GLuint aTextureHandle,
+ GLenum aTarget,
+ gfx::IntSize aSize,
gfx::SurfaceFormat aFormat,
- GLenum aTarget,
- gfx::IntSize aSize);
+ bool aExternallyOwned = false);
+
+ ~GLTextureSource();
+
+ virtual GLTextureSource* AsGLTextureSource() MOZ_OVERRIDE { return this; }
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:
- const gfx::IntSize mSize;
+ void DeleteTextureHandle();
+
RefPtr<CompositorOGL> 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;
};
////////////////////////////////////////////////////////////////////////
// SurfaceTexture
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureSource : public TextureSource