Bug 1077301 - Simplify the gralloc texture code. r=sotaro

This commit is contained in:
Nicolas Silva 2014-10-16 19:08:32 +02:00
parent ea9226b0b4
commit b51bf9c156
13 changed files with 688 additions and 718 deletions

View File

@ -135,17 +135,6 @@ enum SurfaceInitMode
INIT_MODE_CLEAR
};
/**
* A base class for a platform-dependent helper for use by TextureHost.
*/
class CompositorBackendSpecificData
{
NS_INLINE_DECL_REFCOUNTING(CompositorBackendSpecificData)
protected:
virtual ~CompositorBackendSpecificData() {}
};
/**
* Common interface for compositor backends.
*
@ -481,10 +470,6 @@ public:
return fillRatio;
}
virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() {
return nullptr;
}
ScreenRotation GetScreenRotation() const {
return mScreenRotation;
}

View File

@ -24,14 +24,6 @@ namespace layers {
class Compositor;
CompositableBackendSpecificData::CompositableBackendSpecificData()
: mAllowSharingTextureHost(false)
{
static uint64_t sNextID = 1;
++sNextID;
mId = sNextID;
}
/**
* IPDL actor used by CompositableHost to match with its corresponding
* CompositableClient on the content side.
@ -87,9 +79,6 @@ CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
CompositableHost::~CompositableHost()
{
MOZ_COUNT_DTOR(CompositableHost);
if (mBackendData) {
mBackendData->ClearData();
}
}
PCompositableParent*
@ -121,7 +110,6 @@ CompositableHost::UseTextureHost(TextureHost* aTexture)
return;
}
aTexture->SetCompositor(GetCompositor());
aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
@ -130,17 +118,12 @@ CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
{
MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite);
aTextureOnBlack->SetCompositor(GetCompositor());
aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
aTextureOnWhite->SetCompositor(GetCompositor());
aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
CompositableHost::RemoveTextureHost(TextureHost* aTexture)
{
// Clear strong refrence to CompositableBackendSpecificData
aTexture->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
{}
void
CompositableHost::SetCompositor(Compositor* aCompositor)
@ -153,7 +136,7 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects,
const gfx::Matrix4x4& aTransform,
bool aIs3D)
{
RefPtr<TextureSource> source;
CompositableTextureSourceRef source;
RefPtr<TextureHost> host = GetAsTextureHost();
if (!host) {
@ -166,14 +149,12 @@ CompositableHost::AddMaskEffect(EffectChain& aEffects,
return false;
}
source = host->GetTextureSources();
MOZ_ASSERT(source);
if (!source) {
if (!host->BindTextureSource(source)) {
NS_WARNING("The TextureHost was successfully locked but can't provide a TextureSource");
host->Unlock();
return false;
}
MOZ_ASSERT(source);
RefPtr<EffectMask> effect = new EffectMask(source,
source->GetSize(),
@ -192,9 +173,6 @@ CompositableHost::RemoveMaskEffect()
}
}
// implemented in TextureHostOGL.cpp
TemporaryRef<CompositableBackendSpecificData> CreateCompositableBackendSpecificDataOGL();
/* static */ TemporaryRef<CompositableHost>
CompositableHost::Create(const TextureInfo& aTextureInfo)
{
@ -227,12 +205,6 @@ CompositableHost::Create(const TextureInfo& aTextureInfo)
default:
NS_ERROR("Unknown CompositableType");
}
// We know that Tiled buffers don't use the compositable backend-specific
// data, so don't bother creating it.
if (result && aTextureInfo.mCompositableType != CompositableType::BUFFER_TILED) {
RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
result->SetCompositableBackendSpecificData(data);
}
return result;
}

View File

@ -49,42 +49,6 @@ class CompositableParentManager;
class PCompositableParent;
struct EffectChain;
/**
* A base class for doing CompositableHost and platform dependent task on TextureHost.
*/
class CompositableBackendSpecificData
{
protected:
virtual ~CompositableBackendSpecificData() {}
public:
NS_INLINE_DECL_REFCOUNTING(CompositableBackendSpecificData)
CompositableBackendSpecificData();
virtual void ClearData() {}
virtual void SetCompositor(Compositor* aCompositor) {}
bool IsAllowingSharingTextureHost()
{
return mAllowSharingTextureHost;
}
void SetAllowSharingTextureHost(bool aAllow)
{
mAllowSharingTextureHost = aAllow;
}
uint64_t GetId()
{
return mId;
}
public:
bool mAllowSharingTextureHost;
uint64_t mId;
};
/**
* The compositor-side counterpart to CompositableClient. Responsible for
* updating textures and data about textures from IPC and how textures are
@ -112,16 +76,6 @@ public:
virtual CompositableType GetType() = 0;
virtual CompositableBackendSpecificData* GetCompositableBackendSpecificData()
{
return mBackendData;
}
virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
{
mBackendData = aBackendData;
}
// If base class overrides, it should still call the parent implementation
virtual void SetCompositor(Compositor* aCompositor);
@ -252,9 +206,6 @@ public:
SetLayer(nullptr);
mAttached = false;
mKeepAttached = false;
if (mBackendData) {
mBackendData->ClearData();
}
}
}
bool IsAttached() { return mAttached; }
@ -314,7 +265,6 @@ protected:
uint64_t mCompositorID;
RefPtr<Compositor> mCompositor;
Layer* mLayer;
RefPtr<CompositableBackendSpecificData> mBackendData;
uint32_t mFlashCounter; // used when the pref "layers.flash-borders" is true.
bool mAttached;
bool mKeepAttached;

View File

@ -35,12 +35,12 @@ ContentHostBase::~ContentHostBase()
}
void
ContentHostBase::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const Filter& aFilter,
const Rect& aClipRect,
const nsIntRegion* aVisibleRegion)
ContentHostTexture::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const Filter& aFilter,
const Rect& aClipRect,
const nsIntRegion* aVisibleRegion)
{
NS_ASSERTION(aVisibleRegion, "Requires a visible region");
@ -49,14 +49,21 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
return;
}
RefPtr<TextureSource> source = GetTextureSource();
RefPtr<TextureSource> sourceOnWhite = GetTextureSourceOnWhite();
if (!mTextureHost->BindTextureSource(mTextureSource)) {
return;
}
MOZ_ASSERT(mTextureSource.get());
if (!source) {
if (!mTextureHostOnWhite) {
mTextureSourceOnWhite = nullptr;
}
if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
return;
}
RefPtr<TexturedEffect> effect = GenEffect(aFilter);
RefPtr<TexturedEffect> effect = CreateTexturedEffect(mTextureSource.get(),
mTextureSourceOnWhite.get(),
aFilter, true);
if (!effect) {
return;
}
@ -81,7 +88,7 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
region.MoveBy(-origin);
// Figure out the intersecting draw region
gfx::IntSize texSize = source->GetSize();
gfx::IntSize texSize = mTextureSource->GetSize();
nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
textureRect.MoveBy(region.GetBounds().TopLeft());
nsIntRegion subregion;
@ -105,14 +112,14 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
regionRects.Or(regionRects, regionRect);
}
BigImageIterator* bigImgIter = source->AsBigImageIterator();
BigImageIterator* bigImgIter = mTextureSource->AsBigImageIterator();
BigImageIterator* iterOnWhite = nullptr;
if (bigImgIter) {
bigImgIter->BeginBigImageIteration();
}
if (sourceOnWhite) {
iterOnWhite = sourceOnWhite->AsBigImageIterator();
if (mTextureSourceOnWhite) {
iterOnWhite = mTextureSourceOnWhite->AsBigImageIterator();
MOZ_ASSERT(!bigImgIter || bigImgIter->GetTileCount() == iterOnWhite->GetTileCount(),
"Tile count mismatch on component alpha texture");
if (iterOnWhite) {
@ -205,32 +212,40 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
aTransform, mFlashCounter);
}
TemporaryRef<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;
mTextureSourceOnWhite = nullptr;
if (mTextureHost) {
mTextureHost->PrepareTextureSource(mTextureSource);
}
}
void
ContentHostTexture::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite)
{
if (mTextureHost && mTextureHost != aTextureOnBlack) {
mTextureHost->UnbindTextureSource();
}
if (mTextureHostOnWhite && mTextureHostOnWhite != aTextureOnWhite) {
mTextureHostOnWhite->UnbindTextureSource();
}
ContentHostBase::UseComponentAlphaTextures(aTextureOnBlack, aTextureOnWhite);
mTextureHost = aTextureOnBlack;
mTextureHostOnWhite = aTextureOnWhite;
if (mTextureHost) {
mTextureHost->PrepareTextureSource(mTextureSource);
}
if (mTextureHostOnWhite) {
mTextureHostOnWhite->PrepareTextureSource(mTextureSourceOnWhite);
}
}
void
@ -417,6 +432,176 @@ ContentHostIncremental::UpdateIncremental(TextureIdentifier aTextureId,
FlushUpdateQueue();
}
void
ContentHostIncremental::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const Filter& aFilter,
const Rect& aClipRect,
const nsIntRegion* aVisibleRegion)
{
NS_ASSERTION(aVisibleRegion, "Requires a visible region");
AutoLockCompositableHost lock(this);
if (lock.Failed()) {
return;
}
if (!mSource) {
return;
}
RefPtr<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()
{
@ -439,20 +624,6 @@ ContentHostIncremental::ProcessTextureUpdates()
mUpdateList.Clear();
}
TextureSource*
ContentHostIncremental::GetTextureSource()
{
MOZ_ASSERT(mLocked);
return mSource;
}
TextureSource*
ContentHostIncremental::GetTextureSourceOnWhite()
{
MOZ_ASSERT(mLocked);
return mSourceOnWhite;
}
void
ContentHostIncremental::TextureCreationRequest::Execute(ContentHostIncremental* aHost)
{
@ -683,6 +854,35 @@ ContentHostTexture::GetRenderState()
return result;
}
TemporaryRef<TexturedEffect>
ContentHostTexture::GenEffect(const gfx::Filter& aFilter)
{
if (!mTextureHost) {
return nullptr;
}
if (!mTextureHost->BindTextureSource(mTextureSource)) {
return nullptr;
}
if (!mTextureHostOnWhite) {
mTextureSourceOnWhite = nullptr;
}
if (mTextureHostOnWhite && !mTextureHostOnWhite->BindTextureSource(mTextureSourceOnWhite)) {
return nullptr;
}
return CreateTexturedEffect(mTextureSource.get(),
mTextureSourceOnWhite.get(),
aFilter, true);
}
TemporaryRef<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()

View File

@ -96,18 +96,6 @@ public:
explicit ContentHostBase(const TextureInfo& aTextureInfo);
virtual ~ContentHostBase();
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr);
virtual TextureSource* GetTextureSource() = 0;
virtual TextureSource* GetTextureSourceOnWhite() = 0;
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
protected:
virtual nsIntPoint GetOriginOffset()
{
@ -132,6 +120,13 @@ public:
, mLocked(false)
{ }
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr);
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
#ifdef MOZ_DUMP_PAINTING
@ -173,23 +168,15 @@ public:
mLocked = false;
}
virtual TextureSource* GetTextureSource() MOZ_OVERRIDE {
MOZ_ASSERT(mLocked);
return mTextureHost->GetTextureSources();
}
virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE {
MOZ_ASSERT(mLocked);
if (mTextureHostOnWhite) {
return mTextureHostOnWhite->GetTextureSources();
}
return nullptr;
}
LayerRenderState GetRenderState();
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
protected:
RefPtr<TextureHost> mTextureHost;
RefPtr<TextureHost> mTextureHostOnWhite;
CompositableTextureSourceRef mTextureSource;
CompositableTextureSourceRef mTextureSourceOnWhite;
bool mLocked;
};
@ -277,6 +264,13 @@ public:
return false;
}
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr);
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE {
@ -291,8 +285,8 @@ public:
mLocked = false;
}
virtual TextureSource* GetTextureSource() MOZ_OVERRIDE;
virtual TextureSource* GetTextureSourceOnWhite() MOZ_OVERRIDE;
virtual TemporaryRef<TexturedEffect>
GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
private:

View File

@ -37,28 +37,21 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo)
ImageHost::~ImageHost()
{
if (mFrontBuffer) {
mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
}
void
ImageHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
{
CompositableHost::SetCompositableBackendSpecificData(aBackendData);
// ImageHost allows TextureHost sharing among ImageHosts.
if (aBackendData) {
aBackendData->SetAllowSharingTextureHost(true);
mFrontBuffer->UnbindTextureSource();
}
}
void
ImageHost::UseTextureHost(TextureHost* aTexture)
{
CompositableHost::UseTextureHost(aTexture);
if (mFrontBuffer) {
mFrontBuffer->UnsetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
if (mFrontBuffer && mFrontBuffer != aTexture) {
mFrontBuffer->UnbindTextureSource();
}
CompositableHost::UseTextureHost(aTexture);
mFrontBuffer = aTexture;
if (mFrontBuffer) {
mFrontBuffer->PrepareTextureSource(mTextureSource);
}
}
void
@ -66,7 +59,8 @@ ImageHost::RemoveTextureHost(TextureHost* aTexture)
{
CompositableHost::RemoveTextureHost(aTexture);
if (aTexture && mFrontBuffer == aTexture) {
aTexture->SetCompositableBackendSpecificData(nullptr);
mFrontBuffer->UnbindTextureSource();
mTextureSource = nullptr;
mFrontBuffer = nullptr;
}
}
@ -97,25 +91,34 @@ ImageHost::Composite(EffectChain& aEffectChain,
// Make sure the front buffer has a compositor
mFrontBuffer->SetCompositor(GetCompositor());
mFrontBuffer->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
AutoLockCompositableHost autoLock(this);
if (autoLock.Failed()) {
NS_WARNING("failed to lock front buffer");
return;
}
RefPtr<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);
@ -123,7 +126,7 @@ ImageHost::Composite(EffectChain& aEffectChain,
gfx::Rect pictureRect(0, 0,
mPictureRect.width,
mPictureRect.height);
BigImageIterator* it = source->AsBigImageIterator();
BigImageIterator* it = mTextureSource->AsBigImageIterator();
if (it) {
// This iteration does not work if we have multiple texture sources here
@ -139,7 +142,7 @@ ImageHost::Composite(EffectChain& aEffectChain,
// the corresponding source tiles from all planes, with appropriate
// per-plane per-tile texture coords.
// DrawQuad currently assumes that all planes use the same texture coords.
MOZ_ASSERT(it->GetTileCount() == 1 || !source->GetNextSibling(),
MOZ_ASSERT(it->GetTileCount() == 1 || !mTextureSource->GetNextSibling(),
"Can't handle multi-plane BigImages");
it->BeginBigImageIteration();
@ -170,7 +173,7 @@ ImageHost::Composite(EffectChain& aEffectChain,
gfxPictureRect, aClipRect,
aTransform, mFlashCounter);
} else {
IntSize textureSize = source->GetSize();
IntSize textureSize = mTextureSource->GetSize();
gfx::Rect rect;
if (mHasPictureRect) {
effect->mTextureCoords = Rect(Float(mPictureRect.x) / textureSize.width,
@ -273,18 +276,10 @@ ImageHost::Unlock()
mLocked = false;
}
TemporaryRef<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;
@ -292,7 +287,7 @@ ImageHost::GenEffect(const gfx::Filter& aFilter)
isAlphaPremultiplied = false;
return CreateTexturedEffect(mFrontBuffer->GetFormat(),
source,
mTextureSource,
aFilter,
isAlphaPremultiplied);
}

View File

@ -45,8 +45,6 @@ public:
virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
@ -84,13 +82,12 @@ public:
virtual void Unlock() MOZ_OVERRIDE;
virtual TemporaryRef<TextureSource> GetTextureSource();
virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
protected:
RefPtr<TextureHost> mFrontBuffer;
CompositableTextureSourceRef mTextureSource;
nsIntRect mPictureRect;
bool mHasPictureRect;
bool mLocked;

View File

@ -144,6 +144,13 @@ TextureHost::GetIPDLActor()
return mActor;
}
bool
TextureHost::BindTextureSource(CompositableTextureSourceRef& texture)
{
texture = GetTextureSources();
return !!texture;
}
FenceHandle
TextureHost::GetAndResetReleaseFenceHandle()
{
@ -277,18 +284,6 @@ TextureHost::CompositorRecycle()
static_cast<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)
@ -322,9 +317,11 @@ TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
}
TextureSource::TextureSource()
: mCompositableCount(0)
{
MOZ_COUNT_CTOR(TextureSource);
}
TextureSource::~TextureSource()
{
MOZ_COUNT_DTOR(TextureSource);
@ -844,8 +841,9 @@ SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor
GLenum target = surf->ConsTextureTarget();
GLuint tex = surf->ConsTexture(gl);
texSource = new GLTextureSource(compositorOGL, tex, format, target,
surf->mSize);
texSource = new GLTextureSource(compositorOGL, tex, target,
surf->mSize, format,
true/*externally owned*/);
break;
}
case gl::SharedSurfaceType::EGLImageShare: {
@ -860,8 +858,9 @@ SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor
GLuint tex = 0;
surf->AcquireConsumerTexture(gl, &tex, &target);
texSource = new GLTextureSource(compositorOGL, tex, format, target,
surf->mSize);
texSource = new GLTextureSource(compositorOGL, tex, target,
surf->mSize, format,
true/*externally owned*/);
break;
}
#ifdef XP_MACOSX

View File

@ -46,7 +46,6 @@ namespace layers {
class Compositor;
class CompositableHost;
class CompositableBackendSpecificData;
class CompositableParentManager;
class SurfaceDescriptor;
class SharedSurfaceDescriptor;
@ -150,10 +149,69 @@ public:
return nullptr;
}
void AddCompositableRef() { ++mCompositableCount; }
void ReleaseCompositableRef() {
--mCompositableCount;
MOZ_ASSERT(mCompositableCount >= 0);
}
int NumCompositableRefs() const { return mCompositableCount; }
protected:
virtual ~TextureSource();
RefPtr<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;
};
/**
@ -302,6 +360,25 @@ public:
*/
virtual TextureSource* GetTextureSources() = 0;
/**
* Called during the transaction. The TextureSource may or may not be composited.
*
* Note that this is called outside of lock/unlock.
*/
virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) {}
/**
* Called at composition time, just before compositing the TextureSource composited.
*
* Note that this is called only withing lock/unlock.
*/
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture);
/**
* Called when another TextureHost will take over.
*/
virtual void UnbindTextureSource() {}
/**
* Is called before compositing if the shared data has changed since last
* composition.
@ -406,10 +483,6 @@ public:
return LayerRenderState();
}
virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData);
virtual void UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData);
// If a texture host holds a reference to shmem, it should override this method
// to forget about the shmem _without_ releasing it.
virtual void OnShutdown() {}
@ -435,7 +508,6 @@ public:
protected:
PTextureParent* mActor;
TextureFlags mFlags;
RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
friend class TextureParent;
};

View File

@ -136,17 +136,6 @@ GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(textureTarget, tex);
if (mTextureBackendSpecificData) {
// There are two paths for locking/unlocking - if mTextureBackendSpecificData is
// set, we use the texture on there, otherwise we use
// CompositorBackendSpecificData from the compositor and bind the EGLImage
// only in Lock().
if (!mEGLImage) {
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
}
BindEGLImage();
}
ApplyFilterToBoundTexture(gl(), aFilter, textureTarget);
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
@ -159,10 +148,6 @@ GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
bool GrallocTextureSourceOGL::Lock()
{
if (mTextureBackendSpecificData) {
return true;
}
MOZ_ASSERT(IsValid());
if (!IsValid()) {
return false;
@ -188,7 +173,7 @@ bool GrallocTextureSourceOGL::Lock()
bool
GrallocTextureSourceOGL::IsValid() const
{
return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mTextureBackendSpecificData);
return !!gl() && !!mGraphicBuffer.get() && !!mCompositor;
}
gl::GLContext*
@ -230,62 +215,6 @@ GrallocTextureSourceOGL::GetTextureTarget() const
return TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
}
void
GrallocTextureSourceOGL::SetTextureBackendSpecificData(TextureSharedDataGonkOGL* aBackendData)
{
if (!aBackendData) {
DeallocateDeviceData();
// Update mTextureBackendSpecificData after calling DeallocateDeviceData().
mTextureBackendSpecificData = nullptr;
return;
}
if (mTextureBackendSpecificData != aBackendData) {
mNeedsReset = true;
}
if (!gl() || !gl()->MakeCurrent()) {
NS_WARNING("Failed to make the context current");
return;
}
if (!mNeedsReset) {
// Update binding to the EGLImage
GLuint tex = GetGLTexture();
GLuint textureTarget = GetTextureTarget();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(textureTarget, tex);
BindEGLImage();
return;
}
if (!mCompositor) {
mTextureBackendSpecificData = aBackendData;
return;
}
// delete old EGLImage
DeallocateDeviceData();
// Update mTextureBackendSpecificData after calling DeallocateDeviceData().
mTextureBackendSpecificData = aBackendData;
GLuint tex = GetGLTexture();
GLuint textureTarget = GetTextureTarget();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
gl()->fBindTexture(textureTarget, tex);
// Setup texure parameters at the first binding.
gl()->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_T, GetWrapMode());
gl()->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_S, GetWrapMode());
// create new EGLImage
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
BindEGLImage();
mNeedsReset = false;
}
gfx::IntSize
GrallocTextureSourceOGL::GetSize() const
{
@ -304,9 +233,6 @@ GrallocTextureSourceOGL::DeallocateDeviceData()
if (!gl() || !gl()->MakeCurrent()) {
return;
}
if (mTextureBackendSpecificData) {
mTextureBackendSpecificData->ClearBoundEGLImage(mEGLImage);
}
EGLImageDestroy(gl(), mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}
@ -315,49 +241,48 @@ GrallocTextureSourceOGL::DeallocateDeviceData()
GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
const NewSurfaceDescriptorGralloc& aDescriptor)
: TextureHost(aFlags)
, mGrallocHandle(aDescriptor)
, mSize(0, 0)
, mDescriptorSize(aDescriptor.size())
, mFormat(gfx::SurfaceFormat::UNKNOWN)
, mEGLImage(EGL_NO_IMAGE)
{
gfx::SurfaceFormat format = gfx::SurfaceFormat::UNKNOWN;
mGrallocHandle = aDescriptor;
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
MOZ_ASSERT(graphicBuffer);
mSize = aDescriptor.size();
if (graphicBuffer) {
format =
mFormat =
SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
aFlags & TextureFlags::RB_SWAPPED);
mTextureSource = new GrallocTextureSourceOGL(nullptr,
this,
graphicBuffer,
format);
mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
} else {
printf_stderr("gralloc buffer is nullptr");
}
}
GrallocTextureHostOGL::~GrallocTextureHostOGL()
{
MOZ_ASSERT(!mTextureSource || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
"Leaking our buffer");
}
{}
void
GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
{
if (mTextureSource) {
mTextureSource->SetCompositor(static_cast<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
@ -369,28 +294,29 @@ GrallocTextureHostOGL::Unlock()
bool
GrallocTextureHostOGL::IsValid() const
{
if (!mTextureSource) {
return false;
}
return mTextureSource->IsValid();
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
return graphicBuffer != nullptr;
}
gfx::SurfaceFormat
GrallocTextureHostOGL::GetFormat() const
{
if (!mTextureSource) {
return gfx::SurfaceFormat::UNKNOWN;
}
return mTextureSource->GetFormat();
return mFormat;
}
void
GrallocTextureHostOGL::DeallocateSharedData()
{
if (mTextureSource) {
mTextureSource->ForgetBuffer();
mTextureSource = nullptr;
if (mTilingTextureSource) {
mTilingTextureSource->ForgetBuffer();
mTilingTextureSource = nullptr;
}
if (mGLTextureSource) {
mGLTextureSource = nullptr;
}
DestroyEGLImage();
if (mGrallocHandle.buffer().type() != SurfaceDescriptor::Tnull_t) {
MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer();
base::ProcessId owner;
@ -408,24 +334,33 @@ GrallocTextureHostOGL::DeallocateSharedData()
void
GrallocTextureHostOGL::ForgetSharedData()
{
if (mTextureSource) {
mTextureSource->ForgetBuffer();
mTextureSource = nullptr;
if (mTilingTextureSource) {
mTilingTextureSource->ForgetBuffer();
mTilingTextureSource = nullptr;
}
if (mGLTextureSource) {
mGLTextureSource = nullptr;
}
}
void
GrallocTextureHostOGL::DeallocateDeviceData()
{
if (mTextureSource) {
mTextureSource->DeallocateDeviceData();
if (mTilingTextureSource) {
mTilingTextureSource->DeallocateDeviceData();
}
if (mGLTextureSource) {
mGLTextureSource = nullptr;
}
DestroyEGLImage();
}
LayerRenderState
GrallocTextureHostOGL::GetRenderState()
{
if (IsValid()) {
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
if (graphicBuffer) {
LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
if (mFlags & TextureFlags::NEEDS_Y_FLIP) {
flags |= LayerRenderStateFlags::Y_FLIPPED;
@ -433,8 +368,8 @@ GrallocTextureHostOGL::GetRenderState()
if (mFlags & TextureFlags::RB_SWAPPED) {
flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
}
return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
gfx::ThebesIntSize(mSize),
return LayerRenderState(graphicBuffer,
gfx::ThebesIntSize(mDescriptorSize),
flags,
this);
}
@ -444,8 +379,8 @@ GrallocTextureHostOGL::GetRenderState()
TemporaryRef<gfx::DataSourceSurface>
GrallocTextureHostOGL::GetAsSurface() {
return mTextureSource ? mTextureSource->GetAsSurface()
: nullptr;
return mTilingTextureSource ? mTilingTextureSource->GetAsSurface()
: nullptr;
}
TemporaryRef<gfx::DataSourceSurface>
@ -473,103 +408,186 @@ GrallocTextureSourceOGL::GetAsSurface() {
GLuint
GrallocTextureSourceOGL::GetGLTexture()
{
if (mTextureBackendSpecificData) {
mTextureBackendSpecificData->SetCompositor(mCompositor);
return mTextureBackendSpecificData->GetTexture();
}
return mTexture;
}
void
GrallocTextureSourceOGL::BindEGLImage()
{
if (mTextureBackendSpecificData) {
mTextureBackendSpecificData->BindEGLImage(GetTextureTarget(), mEGLImage);
gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
}
TextureSource*
GrallocTextureHostOGL::GetTextureSources()
{
// This is now only used with tiled layers, and will eventually be removed.
// Other layer types use BindTextureSource instead.
MOZ_ASSERT(!mGLTextureSource);
if (!mTilingTextureSource) {
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
MOZ_ASSERT(graphicBuffer);
if (!graphicBuffer) {
return nullptr;
}
mTilingTextureSource = new GrallocTextureSourceOGL(mCompositor, this,
graphicBuffer, mFormat);
}
mTilingTextureSource->Lock();
return mTilingTextureSource;
}
void
GrallocTextureHostOGL::UnbindTextureSource()
{
// Clear the reference to the TextureSource (if any), because we know that
// another TextureHost is being bound to the TextureSource. This means that
// we will have to re-do gl->fEGLImageTargetTexture2D next time we go through
// BindTextureSource (otherwise we would have skipped it).
// Note that this doesn't "unlock" the gralloc buffer or force it to be
// detached, Although decreasing the refcount of the TextureSource may lead
// to the gl handle being destroyed, which would unlock the gralloc buffer.
// That said, this method is called before another TextureHost attaches to the
// TextureSource, which has the effect of unlocking the gralloc buffer. So when
// this is called we know we are going to be unlocked soon.
mGLTextureSource = nullptr;
}
GLenum GetTextureTarget(gl::GLContext* aGL, android::PixelFormat aFormat) {
MOZ_ASSERT(aGL);
if (aGL->Renderer() == gl::GLRenderer::SGX530 ||
aGL->Renderer() == gl::GLRenderer::SGX540) {
// SGX has a quirk that only TEXTURE_EXTERNAL works and any other value will
// result in black pixels when trying to draw from bound textures.
// Unfortunately, using TEXTURE_EXTERNAL on Adreno has a terrible effect on
// performance.
// See Bug 950050.
return LOCAL_GL_TEXTURE_EXTERNAL;
} else {
gl()->fEGLImageTargetTexture2D(GetTextureTarget(), mEGLImage);
return TextureTargetForAndroidPixelFormat(aFormat);
}
}
void
GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
GrallocTextureHostOGL::DestroyEGLImage()
{
if(!aBackendData) {
return;
// Only called when we want to get rid of the gralloc buffer, usually
// around the end of life of the TextureHost.
if (mEGLImage != EGL_NO_IMAGE && GetGLContext()) {
EGLImageDestroy(GetGLContext(), mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}
// Update mTextureBackendSpecificData if it is not set yet.
if (!mTextureBackendSpecificData) {
MOZ_ASSERT(!mCompositableBackendData);
mCompositableBackendData = aBackendData;
CompositableDataGonkOGL* backend = static_cast<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();
}
// 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 (mTextureSource) {
mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
}
}
void
GrallocTextureHostOGL::UnsetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextureSource)
{
if(!aBackendData ||
!mTextureBackendSpecificData) {
// This happens during the layers transaction.
// All of the gralloc magic goes here. The only thing that happens externally
// and that is good to keep in mind is that when the TextureSource is deleted,
// it destroys its gl texture handle which is important for genlock.
// If this TextureHost's mGLTextureSource member is non-null, it means we are
// still bound to the TextureSource, in which case we can skip the driver
// overhead of binding the texture again (fEGLImageTargetTexture2D)
// As a result, if the TextureHost is used with several CompositableHosts,
// it will be bound to only one TextureSource, and we'll do the driver work
// only once, which is great. This means that all of the compositables that
// use this TextureHost will keep a reference to this TextureSource at least
// for the duration of this frame.
// If the compositable already has a TextureSource (the aTextureSource parameter),
// that is compatible and is not in use by several compositable, we try to
// attach to it. This has the effect of unlocking the previous TextureHost that
// we attached to the TextureSource (the previous frame)
// If the TextureSource used by the compositable is also used by other
// compositables (see NumCompositableRefs), we have to create a new TextureSource,
// because otherwise we would be modifying the content of every layer that uses
// the TextureSource in question, even thoug they don't use this TextureHost.
MOZ_ASSERT(!mTilingTextureSource);
android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
MOZ_ASSERT(graphicBuffer);
if (!graphicBuffer) {
mGLTextureSource = nullptr;
return;
}
if (mBackendDatas)
{
// Handle a case that TextureHost has ownership of TextureSharedDataGonkOGL.
mBackendDatas->erase(aBackendData->GetId());
if (mBackendDatas->size() == 0) {
mCompositableBackendData = nullptr;
mTextureBackendSpecificData = nullptr;
}
} else {
// Handle a case that CompositableHost has ownership of TextureSharedDataGonkOGL.
mCompositableBackendData = nullptr;
mTextureBackendSpecificData = nullptr;
if (mGLTextureSource && !mGLTextureSource->IsValid()) {
mGLTextureSource = nullptr;
}
if (mTextureSource) {
mTextureSource->SetTextureBackendSpecificData(mTextureBackendSpecificData);
if (mGLTextureSource) {
// We are already attached to a TextureSource, nothing to do except tell
// the compositable to use it.
aTextureSource = mGLTextureSource.get();
return;
}
gl::GLContext* gl = GetGLContext();
if (!gl || !gl->MakeCurrent()) {
mGLTextureSource = nullptr;
return;
}
if (mEGLImage == EGL_NO_IMAGE) {
// Should only happen the first time.
mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer());
}
GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat());
GLTextureSource* glSource = aTextureSource.get() ?
aTextureSource->AsSourceOGL()->AsGLTextureSource() : nullptr;
bool shouldCreateTextureSource = !glSource || !glSource->IsValid()
|| glSource->NumCompositableRefs() > 1
|| glSource->GetTextureTarget() != textureTarget;
if (shouldCreateTextureSource) {
GLuint textureHandle;
gl->fGenTextures(1, &textureHandle);
gl->fBindTexture(textureTarget, textureHandle);
gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
gl->fTexParameteri(textureTarget, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
mGLTextureSource = new GLTextureSource(mCompositor, textureHandle, textureTarget,
mSize, mFormat);
aTextureSource = mGLTextureSource.get();
} else {
gl->fBindTexture(textureTarget, glSource->GetTextureHandle());
gl->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
glSource->SetSize(mSize);
glSource->SetFormat(mFormat);
mGLTextureSource = glSource;
}
}
bool
GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource)
{
// This happens at composition time.
// If mGLTextureSource is null it means PrepareTextureSource failed.
if (!mGLTextureSource) {
return false;
}
// If Prepare didn't fail, we expect our TextureSource to be the same as aTextureSource,
// otherwise it means something has fiddled with the TextureSource between Prepare and
// now.
MOZ_ASSERT(mGLTextureSource == aTextureSource);
aTextureSource = mGLTextureSource.get();
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
// Wait until it's ready.
WaitAcquireFenceSyncComplete();
#endif
return true;
}
} // namepsace layers

View File

@ -17,6 +17,7 @@ namespace layers {
class GrallocTextureHostOGL;
// Progressively getting replaced by GLTextureSource
class GrallocTextureSourceOGL : public TextureSource
, public TextureSourceOGL
{
@ -47,8 +48,6 @@ public:
return LOCAL_GL_CLAMP_TO_EDGE;
}
virtual void SetTextureBackendSpecificData(TextureSharedDataGonkOGL* aBackendData);
void DeallocateDeviceData();
gl::GLContext* gl() const;
@ -75,7 +74,6 @@ public:
bool Lock();
protected:
RefPtr<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
RefPtr<CompositorOGL> mCompositor;
GrallocTextureHostOGL* mTextureHost;
android::sp<android::GraphicBuffer> mGraphicBuffer;
@ -113,14 +111,17 @@ public:
virtual gfx::SurfaceFormat GetFormat() const;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mDescriptorSize; }
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
virtual TextureSource* GetTextureSources() MOZ_OVERRIDE
{
return mTextureSource;
}
virtual void PrepareTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE;
virtual bool BindTextureSource(CompositableTextureSourceRef& aTextureSource) MOZ_OVERRIDE;
virtual void UnbindTextureSource() MOZ_OVERRIDE;
virtual TextureSource* GetTextureSources() MOZ_OVERRIDE;
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
@ -131,21 +132,27 @@ public:
virtual TemporaryRef<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"; }
private:
NewSurfaceDescriptorGralloc mGrallocHandle;
RefPtr<GrallocTextureSourceOGL> mTextureSource;
gfx::IntSize mSize; // See comment in textureClientOGL.h
gl::GLContext* GetGLContext() const { return mCompositor ? mCompositor->gl() : nullptr; }
RefPtr<TextureSharedDataGonkOGL> mTextureBackendSpecificData;
UniquePtr<std::map<uint64_t, RefPtr<CompositableBackendSpecificData> > > mBackendDatas;
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;
};
} // namespace layers

View File

@ -40,16 +40,6 @@ 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,
@ -119,174 +109,6 @@ FlagsToGLFlags(TextureFlags aFlags)
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)
@ -529,27 +351,56 @@ TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilt
// GLTextureSource
GLTextureSource::GLTextureSource(CompositorOGL* aCompositor,
GLuint aTex,
gfx::SurfaceFormat aFormat,
GLuint aTextureHandle,
GLenum aTarget,
gfx::IntSize aSize)
: mSize(aSize)
, mCompositor(aCompositor)
, mTex(aTex)
, mFormat(aFormat)
gfx::IntSize aSize,
gfx::SurfaceFormat aFormat,
bool aExternallyOwned)
: mCompositor(aCompositor)
, mTextureHandle(aTextureHandle)
, mTextureTarget(aTarget)
, mSize(aSize)
, mFormat(aFormat)
, mExternallyOwned(aExternallyOwned)
{
MOZ_COUNT_CTOR(GLTextureSource);
}
GLTextureSource::~GLTextureSource()
{
MOZ_COUNT_DTOR(GLTextureSource);
if (!mExternallyOwned) {
DeleteTextureHandle();
}
}
void
GLTextureSource::DeallocateDeviceData()
{
if (!mExternallyOwned) {
DeleteTextureHandle();
}
}
void
GLTextureSource::DeleteTextureHandle()
{
if (mTextureHandle != 0 && gl() && gl()->MakeCurrent()) {
gl()->fDeleteTextures(1, &mTextureHandle);
}
mTextureHandle = 0;
}
void
GLTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
{
MOZ_ASSERT(gl());
MOZ_ASSERT(mTextureHandle != 0);
if (!gl()) {
NS_WARNING("Trying to bind a texture without a GLContext");
return;
}
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, mTex);
gl()->fBindTexture(mTextureTarget, mTextureHandle);
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
@ -562,7 +413,7 @@ GLTextureSource::SetCompositor(Compositor* aCompositor)
bool
GLTextureSource::IsValid() const
{
return !!gl();
return !!gl() && mTextureHandle != 0;
}
gl::GLContext*
@ -614,6 +465,10 @@ SurfaceTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
void
SurfaceTextureSource::SetCompositor(Compositor* aCompositor)
{
if (mCompositor != aCompositor) {
DeallocateDeviceData();
}
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}

View File

@ -58,99 +58,7 @@ class Compositor;
class CompositorOGL;
class TextureImageTextureSourceOGL;
class TextureSharedDataGonkOGL;
/**
* CompositableBackendSpecificData implementation for the Gonk OpenGL backend.
* Share a same texture between TextureHosts in the same CompositableHost.
* By shareing the texture among the TextureHosts, number of texture allocations
* can be reduced than texture allocation in every TextureHosts.
* From Bug 912134, use only one texture among all TextureHosts degrade
* the rendering performance.
* CompositableDataGonkOGL chooses in a middile of them.
*/
class CompositableDataGonkOGL : public CompositableBackendSpecificData
{
protected:
virtual ~CompositableDataGonkOGL();
public:
CompositableDataGonkOGL();
virtual void ClearData() MOZ_OVERRIDE;
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
TextureSharedDataGonkOGL* GetTextureBackendSpecificData();
protected:
nsRefPtr<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,
@ -205,6 +113,8 @@ public:
virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() { return nullptr; }
virtual GLTextureSource* AsGLTextureSource() { return nullptr; }
void SetFilter(gl::GLContext* aGL, gfx::Filter aFilter)
{
if (mHasCachedFilter &&
@ -373,10 +283,15 @@ class GLTextureSource : public TextureSource
{
public:
GLTextureSource(CompositorOGL* aCompositor,
GLuint aTex,
gfx::SurfaceFormat aFormat,
GLuint aTextureHandle,
GLenum aTarget,
gfx::IntSize aSize);
gfx::IntSize aSize,
gfx::SurfaceFormat aFormat,
bool aExternallyOwned = false);
~GLTextureSource();
virtual GLTextureSource* AsGLTextureSource() MOZ_OVERRIDE { return this; }
virtual TextureSourceOGL* AsSourceOGL() MOZ_OVERRIDE { return this; }
@ -392,18 +307,29 @@ public:
virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return LOCAL_GL_CLAMP_TO_EDGE; }
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void DeallocateDeviceData() MOZ_OVERRIDE;
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
void SetSize(gfx::IntSize aSize) { mSize = aSize; }
void SetFormat(gfx::SurfaceFormat aFormat) { mFormat = aFormat; }
GLuint GetTextureHandle() const { return mTextureHandle; }
gl::GLContext* gl() const;
protected:
const gfx::IntSize mSize;
void DeleteTextureHandle();
RefPtr<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;
};
////////////////////////////////////////////////////////////////////////