michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "CompositableHost.h" michael@0: #include // for _Rb_tree_iterator, map, etc michael@0: #include // for pair michael@0: #include "ContentHost.h" // for ContentHostDoubleBuffered, etc michael@0: #include "Effects.h" // for EffectMask, Effect, etc michael@0: #include "ImageHost.h" // for ImageHostBuffered, etc michael@0: #include "TiledContentHost.h" // for TiledContentHost michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor michael@0: #include "mozilla/layers/TextureHost.h" // for TextureHost, etc michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsDebug.h" // for NS_WARNING michael@0: #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc michael@0: #include "gfxPlatform.h" // for gfxPlatform michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: class Compositor; michael@0: michael@0: /** michael@0: * IPDL actor used by CompositableHost to match with its corresponding michael@0: * CompositableClient on the content side. michael@0: * michael@0: * CompositableParent is owned by the IPDL system. It's deletion is triggered michael@0: * by either the CompositableChild's deletion, or by the IPDL communication michael@0: * goind down. michael@0: */ michael@0: class CompositableParent : public PCompositableParent michael@0: { michael@0: public: michael@0: CompositableParent(CompositableParentManager* aMgr, michael@0: const TextureInfo& aTextureInfo, michael@0: uint64_t aID = 0) michael@0: { michael@0: MOZ_COUNT_CTOR(CompositableParent); michael@0: mHost = CompositableHost::Create(aTextureInfo); michael@0: mHost->SetAsyncID(aID); michael@0: if (aID) { michael@0: CompositableMap::Set(aID, this); michael@0: } michael@0: } michael@0: michael@0: ~CompositableParent() michael@0: { michael@0: MOZ_COUNT_DTOR(CompositableParent); michael@0: CompositableMap::Erase(mHost->GetAsyncID()); michael@0: } michael@0: michael@0: virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE michael@0: { michael@0: if (mHost) { michael@0: mHost->Detach(nullptr, CompositableHost::FORCE_DETACH); michael@0: } michael@0: } michael@0: michael@0: RefPtr mHost; michael@0: }; michael@0: michael@0: CompositableHost::CompositableHost(const TextureInfo& aTextureInfo) michael@0: : mTextureInfo(aTextureInfo) michael@0: , mAsyncID(0) michael@0: , mCompositorID(0) michael@0: , mCompositor(nullptr) michael@0: , mLayer(nullptr) michael@0: , mFlashCounter(0) michael@0: , mAttached(false) michael@0: , mKeepAttached(false) michael@0: { michael@0: MOZ_COUNT_CTOR(CompositableHost); michael@0: } michael@0: michael@0: CompositableHost::~CompositableHost() michael@0: { michael@0: MOZ_COUNT_DTOR(CompositableHost); michael@0: if (mBackendData) { michael@0: mBackendData->ClearData(); michael@0: } michael@0: } michael@0: michael@0: PCompositableParent* michael@0: CompositableHost::CreateIPDLActor(CompositableParentManager* aMgr, michael@0: const TextureInfo& aTextureInfo, michael@0: uint64_t aID) michael@0: { michael@0: return new CompositableParent(aMgr, aTextureInfo, aID); michael@0: } michael@0: michael@0: bool michael@0: CompositableHost::DestroyIPDLActor(PCompositableParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: CompositableHost* michael@0: CompositableHost::FromIPDLActor(PCompositableParent* aActor) michael@0: { michael@0: MOZ_ASSERT(aActor); michael@0: return static_cast(aActor)->mHost; michael@0: } michael@0: michael@0: void michael@0: CompositableHost::UseTextureHost(TextureHost* aTexture) michael@0: { michael@0: if (!aTexture) { michael@0: return; michael@0: } michael@0: aTexture->SetCompositor(GetCompositor()); michael@0: aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); michael@0: } michael@0: michael@0: void michael@0: CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, michael@0: TextureHost* aTextureOnWhite) michael@0: { michael@0: MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite); michael@0: aTextureOnBlack->SetCompositor(GetCompositor()); michael@0: aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); michael@0: aTextureOnWhite->SetCompositor(GetCompositor()); michael@0: aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData()); michael@0: } michael@0: michael@0: void michael@0: CompositableHost::RemoveTextureHost(TextureHost* aTexture) michael@0: { michael@0: // Clear strong refrence to CompositableBackendSpecificData michael@0: aTexture->SetCompositableBackendSpecificData(nullptr); michael@0: } michael@0: michael@0: void michael@0: CompositableHost::SetCompositor(Compositor* aCompositor) michael@0: { michael@0: mCompositor = aCompositor; michael@0: } michael@0: michael@0: bool michael@0: CompositableHost::AddMaskEffect(EffectChain& aEffects, michael@0: const gfx::Matrix4x4& aTransform, michael@0: bool aIs3D) michael@0: { michael@0: RefPtr source; michael@0: RefPtr host = GetAsTextureHost(); michael@0: if (host && host->Lock()) { michael@0: source = host->GetTextureSources(); michael@0: } michael@0: michael@0: if (!source) { michael@0: NS_WARNING("Using compositable with no texture host as mask layer"); michael@0: return false; michael@0: } michael@0: michael@0: RefPtr effect = new EffectMask(source, michael@0: source->GetSize(), michael@0: aTransform); michael@0: effect->mIs3D = aIs3D; michael@0: aEffects.mSecondaryEffects[EFFECT_MASK] = effect; michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: CompositableHost::RemoveMaskEffect() michael@0: { michael@0: RefPtr host = GetAsTextureHost(); michael@0: if (host) { michael@0: host->Unlock(); michael@0: } michael@0: } michael@0: michael@0: // implemented in TextureHostOGL.cpp michael@0: TemporaryRef CreateCompositableBackendSpecificDataOGL(); michael@0: michael@0: /* static */ TemporaryRef michael@0: CompositableHost::Create(const TextureInfo& aTextureInfo) michael@0: { michael@0: RefPtr result; michael@0: switch (aTextureInfo.mCompositableType) { michael@0: case BUFFER_BRIDGE: michael@0: NS_ERROR("Cannot create an image bridge compositable this way"); michael@0: break; michael@0: case BUFFER_CONTENT_INC: michael@0: result = new ContentHostIncremental(aTextureInfo); michael@0: break; michael@0: case BUFFER_TILED: michael@0: case BUFFER_SIMPLE_TILED: michael@0: result = new TiledContentHost(aTextureInfo); michael@0: break; michael@0: case COMPOSITABLE_IMAGE: michael@0: result = new ImageHost(aTextureInfo); michael@0: break; michael@0: case COMPOSITABLE_CONTENT_SINGLE: michael@0: result = new ContentHostSingleBuffered(aTextureInfo); michael@0: break; michael@0: case COMPOSITABLE_CONTENT_DOUBLE: michael@0: result = new ContentHostDoubleBuffered(aTextureInfo); michael@0: break; michael@0: default: michael@0: NS_ERROR("Unknown CompositableType"); michael@0: } michael@0: // We know that Tiled buffers don't use the compositable backend-specific michael@0: // data, so don't bother creating it. michael@0: if (result && aTextureInfo.mCompositableType != BUFFER_TILED) { michael@0: RefPtr data = CreateCompositableBackendSpecificDataOGL(); michael@0: result->SetCompositableBackendSpecificData(data); michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: #ifdef MOZ_DUMP_PAINTING michael@0: void michael@0: CompositableHost::DumpTextureHost(FILE* aFile, TextureHost* aTexture) michael@0: { michael@0: if (!aTexture) { michael@0: return; michael@0: } michael@0: RefPtr dSurf = aTexture->GetAsSurface(); michael@0: if (!dSurf) { michael@0: return; michael@0: } michael@0: gfxPlatform *platform = gfxPlatform::GetPlatform(); michael@0: RefPtr dt = platform->CreateDrawTargetForData(dSurf->GetData(), michael@0: dSurf->GetSize(), michael@0: dSurf->Stride(), michael@0: dSurf->GetFormat()); michael@0: nsRefPtr surf = platform->GetThebesSurfaceForDrawTarget(dt); michael@0: if (!surf) { michael@0: return; michael@0: } michael@0: surf->DumpAsDataURL(aFile ? aFile : stderr); michael@0: } michael@0: #endif michael@0: michael@0: namespace CompositableMap { michael@0: michael@0: typedef std::map CompositableMap_t; michael@0: static CompositableMap_t* sCompositableMap = nullptr; michael@0: bool IsCreated() { michael@0: return sCompositableMap != nullptr; michael@0: } michael@0: PCompositableParent* Get(uint64_t aID) michael@0: { michael@0: if (!IsCreated() || aID == 0) { michael@0: return nullptr; michael@0: } michael@0: CompositableMap_t::iterator it = sCompositableMap->find(aID); michael@0: if (it == sCompositableMap->end()) { michael@0: return nullptr; michael@0: } michael@0: return it->second; michael@0: } michael@0: void Set(uint64_t aID, PCompositableParent* aParent) michael@0: { michael@0: if (!IsCreated() || aID == 0) { michael@0: return; michael@0: } michael@0: (*sCompositableMap)[aID] = aParent; michael@0: } michael@0: void Erase(uint64_t aID) michael@0: { michael@0: if (!IsCreated() || aID == 0) { michael@0: return; michael@0: } michael@0: CompositableMap_t::iterator it = sCompositableMap->find(aID); michael@0: if (it != sCompositableMap->end()) { michael@0: sCompositableMap->erase(it); michael@0: } michael@0: } michael@0: void Clear() michael@0: { michael@0: if (!IsCreated()) { michael@0: return; michael@0: } michael@0: sCompositableMap->clear(); michael@0: } michael@0: void Create() michael@0: { michael@0: if (sCompositableMap == nullptr) { michael@0: sCompositableMap = new CompositableMap_t; michael@0: } michael@0: } michael@0: void Destroy() michael@0: { michael@0: Clear(); michael@0: delete sCompositableMap; michael@0: sCompositableMap = nullptr; michael@0: } michael@0: michael@0: } // namespace CompositableMap michael@0: michael@0: } // namespace layers michael@0: } // namespace mozilla