michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=8 et : michael@0: */ 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 "ShadowLayers.h" michael@0: #include // for _Rb_tree_const_iterator, etc michael@0: #include // for vector michael@0: #include "GeckoProfiler.h" // for PROFILER_LABEL michael@0: #include "ISurfaceAllocator.h" // for IsSurfaceDescriptorValid michael@0: #include "Layers.h" // for Layer michael@0: #include "RenderTrace.h" // for RenderTraceScope michael@0: #include "ShadowLayerChild.h" // for ShadowLayerChild michael@0: #include "gfx2DGlue.h" // for Moz2D transition helpers michael@0: #include "gfxPlatform.h" // for gfxImageFormat, gfxPlatform michael@0: #include "gfxSharedImageSurface.h" // for gfxSharedImageSurface michael@0: #include "ipc/IPCMessageUtils.h" // for gfxContentType, null_t michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/gfx/Point.h" // for IntSize michael@0: #include "mozilla/layers/CompositableClient.h" // for CompositableClient, etc michael@0: #include "mozilla/layers/LayersMessages.h" // for Edit, etc michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc michael@0: #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG michael@0: #include "mozilla/layers/LayerTransactionChild.h" michael@0: #include "ShadowLayerUtils.h" michael@0: #include "mozilla/layers/TextureClient.h" // for TextureClient michael@0: #include "mozilla/mozalloc.h" // for operator new, etc michael@0: #include "nsAutoPtr.h" // for nsRefPtr, getter_AddRefs, etc michael@0: #include "nsDebug.h" // for NS_ABORT_IF_FALSE, etc michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nsSize.h" // for nsIntSize michael@0: #include "nsTArray.h" // for nsAutoTArray, nsTArray, etc michael@0: #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc michael@0: michael@0: struct nsIntPoint; michael@0: michael@0: using namespace mozilla::ipc; michael@0: using namespace mozilla::gl; michael@0: using namespace mozilla::dom; michael@0: michael@0: namespace mozilla { michael@0: namespace ipc { michael@0: class Shmem; michael@0: } michael@0: michael@0: namespace layers { michael@0: michael@0: class ClientTiledLayerBuffer; michael@0: michael@0: typedef nsTArray BufferArray; michael@0: typedef std::vector EditVector; michael@0: typedef std::set ShadowableLayerSet; michael@0: michael@0: class Transaction michael@0: { michael@0: public: michael@0: Transaction() michael@0: : mTargetRotation(ROTATION_0) michael@0: , mSwapRequired(false) michael@0: , mOpen(false) michael@0: , mRotationChanged(false) michael@0: {} michael@0: michael@0: void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation, michael@0: const nsIntRect& aClientBounds, ScreenOrientation aOrientation) michael@0: { michael@0: mOpen = true; michael@0: mTargetBounds = aTargetBounds; michael@0: if (aRotation != mTargetRotation) { michael@0: // the first time this is called, mRotationChanged will be false if michael@0: // aRotation is 0, but we should be OK because for the first transaction michael@0: // we should only compose if it is non-empty. See the caller(s) of michael@0: // RotationChanged. michael@0: mRotationChanged = true; michael@0: } michael@0: mTargetRotation = aRotation; michael@0: mClientBounds = aClientBounds; michael@0: mTargetOrientation = aOrientation; michael@0: } michael@0: void MarkSyncTransaction() michael@0: { michael@0: mSwapRequired = true; michael@0: } michael@0: void AddEdit(const Edit& aEdit) michael@0: { michael@0: NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?"); michael@0: mCset.push_back(aEdit); michael@0: } michael@0: void AddEdit(const CompositableOperation& aEdit) michael@0: { michael@0: AddEdit(Edit(aEdit)); michael@0: } michael@0: void AddPaint(const Edit& aPaint) michael@0: { michael@0: AddNoSwapPaint(aPaint); michael@0: mSwapRequired = true; michael@0: } michael@0: void AddPaint(const CompositableOperation& aPaint) michael@0: { michael@0: AddNoSwapPaint(Edit(aPaint)); michael@0: mSwapRequired = true; michael@0: } michael@0: michael@0: void AddNoSwapPaint(const Edit& aPaint) michael@0: { michael@0: NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?"); michael@0: mPaints.push_back(aPaint); michael@0: } michael@0: void AddNoSwapPaint(const CompositableOperation& aPaint) michael@0: { michael@0: NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?"); michael@0: mPaints.push_back(Edit(aPaint)); michael@0: } michael@0: void AddMutant(ShadowableLayer* aLayer) michael@0: { michael@0: NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?"); michael@0: mMutants.insert(aLayer); michael@0: } michael@0: void End() michael@0: { michael@0: mCset.clear(); michael@0: mPaints.clear(); michael@0: mMutants.clear(); michael@0: mOpen = false; michael@0: mSwapRequired = false; michael@0: mRotationChanged = false; michael@0: } michael@0: michael@0: bool Empty() const { michael@0: return mCset.empty() && mPaints.empty() && mMutants.empty(); michael@0: } michael@0: bool RotationChanged() const { michael@0: return mRotationChanged; michael@0: } michael@0: bool Finished() const { return !mOpen && Empty(); } michael@0: michael@0: EditVector mCset; michael@0: EditVector mPaints; michael@0: ShadowableLayerSet mMutants; michael@0: nsIntRect mTargetBounds; michael@0: ScreenRotation mTargetRotation; michael@0: nsIntRect mClientBounds; michael@0: ScreenOrientation mTargetOrientation; michael@0: bool mSwapRequired; michael@0: michael@0: private: michael@0: bool mOpen; michael@0: bool mRotationChanged; michael@0: michael@0: // disabled michael@0: Transaction(const Transaction&); michael@0: Transaction& operator=(const Transaction&); michael@0: }; michael@0: struct AutoTxnEnd { michael@0: AutoTxnEnd(Transaction* aTxn) : mTxn(aTxn) {} michael@0: ~AutoTxnEnd() { mTxn->End(); } michael@0: Transaction* mTxn; michael@0: }; michael@0: michael@0: void michael@0: CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier) michael@0: { michael@0: mTextureFactoryIdentifier = aIdentifier; michael@0: } michael@0: michael@0: ShadowLayerForwarder::ShadowLayerForwarder() michael@0: : mDiagnosticTypes(DIAGNOSTIC_NONE) michael@0: , mIsFirstPaint(false) michael@0: , mWindowOverlayChanged(false) michael@0: { michael@0: mTxn = new Transaction(); michael@0: } michael@0: michael@0: ShadowLayerForwarder::~ShadowLayerForwarder() michael@0: { michael@0: NS_ABORT_IF_FALSE(mTxn->Finished(), "unfinished transaction?"); michael@0: delete mTxn; michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::BeginTransaction(const nsIntRect& aTargetBounds, michael@0: ScreenRotation aRotation, michael@0: const nsIntRect& aClientBounds, michael@0: ScreenOrientation aOrientation) michael@0: { michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to"); michael@0: NS_ABORT_IF_FALSE(mTxn->Finished(), "uncommitted txn?"); michael@0: mTxn->Begin(aTargetBounds, aRotation, aClientBounds, aOrientation); michael@0: } michael@0: michael@0: static PLayerChild* michael@0: Shadow(ShadowableLayer* aLayer) michael@0: { michael@0: return aLayer->GetShadow(); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: CreatedLayer(Transaction* aTxn, ShadowableLayer* aLayer) michael@0: { michael@0: aTxn->AddEdit(OpCreateT(nullptr, Shadow(aLayer))); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::CreatedThebesLayer(ShadowableLayer* aThebes) michael@0: { michael@0: CreatedLayer(mTxn, aThebes); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::CreatedContainerLayer(ShadowableLayer* aContainer) michael@0: { michael@0: CreatedLayer(mTxn, aContainer); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::CreatedImageLayer(ShadowableLayer* aImage) michael@0: { michael@0: CreatedLayer(mTxn, aImage); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::CreatedColorLayer(ShadowableLayer* aColor) michael@0: { michael@0: CreatedLayer(mTxn, aColor); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas) michael@0: { michael@0: CreatedLayer(mTxn, aCanvas); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::CreatedRefLayer(ShadowableLayer* aRef) michael@0: { michael@0: CreatedLayer(mTxn, aRef); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::Mutated(ShadowableLayer* aMutant) michael@0: { michael@0: mTxn->AddMutant(aMutant); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::SetRoot(ShadowableLayer* aRoot) michael@0: { michael@0: mTxn->AddEdit(OpSetRoot(nullptr, Shadow(aRoot))); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::InsertAfter(ShadowableLayer* aContainer, michael@0: ShadowableLayer* aChild, michael@0: ShadowableLayer* aAfter) michael@0: { michael@0: if (aAfter) michael@0: mTxn->AddEdit(OpInsertAfter(nullptr, Shadow(aContainer), michael@0: nullptr, Shadow(aChild), michael@0: nullptr, Shadow(aAfter))); michael@0: else michael@0: mTxn->AddEdit(OpPrependChild(nullptr, Shadow(aContainer), michael@0: nullptr, Shadow(aChild))); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::RemoveChild(ShadowableLayer* aContainer, michael@0: ShadowableLayer* aChild) michael@0: { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] OpRemoveChild container=%p child=%p\n", michael@0: aContainer->AsLayer(), aChild->AsLayer())); michael@0: michael@0: mTxn->AddEdit(OpRemoveChild(nullptr, Shadow(aContainer), michael@0: nullptr, Shadow(aChild))); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::RepositionChild(ShadowableLayer* aContainer, michael@0: ShadowableLayer* aChild, michael@0: ShadowableLayer* aAfter) michael@0: { michael@0: if (aAfter) { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] OpRepositionChild container=%p child=%p after=%p", michael@0: aContainer->AsLayer(), aChild->AsLayer(), aAfter->AsLayer())); michael@0: mTxn->AddEdit(OpRepositionChild(nullptr, Shadow(aContainer), michael@0: nullptr, Shadow(aChild), michael@0: nullptr, Shadow(aAfter))); michael@0: } else { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] OpRaiseToTopChild container=%p child=%p", michael@0: aContainer->AsLayer(), aChild->AsLayer())); michael@0: mTxn->AddEdit(OpRaiseToTopChild(nullptr, Shadow(aContainer), michael@0: nullptr, Shadow(aChild))); michael@0: } michael@0: } michael@0: michael@0: michael@0: #ifdef DEBUG michael@0: void michael@0: ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const michael@0: { michael@0: if (!aDescriptor) { michael@0: return; michael@0: } michael@0: michael@0: if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorShmem) { michael@0: const SurfaceDescriptorShmem& shmem = aDescriptor->get_SurfaceDescriptorShmem(); michael@0: shmem.data().AssertInvariants(); michael@0: MOZ_ASSERT(mShadowManager && michael@0: mShadowManager->IsTrackingSharedMemory(shmem.data().mSegment)); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: ShadowLayerForwarder::UseTiledLayerBuffer(CompositableClient* aCompositable, michael@0: const SurfaceDescriptorTiles& aTileLayerDescriptor) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: mTxn->AddNoSwapPaint(OpUseTiledLayerBuffer(nullptr, aCompositable->GetIPDLActor(), michael@0: aTileLayerDescriptor)); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::UpdateTextureRegion(CompositableClient* aCompositable, michael@0: const ThebesBufferData& aThebesBufferData, michael@0: const nsIntRegion& aUpdatedRegion) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: mTxn->AddPaint(OpPaintTextureRegion(nullptr, aCompositable->GetIPDLActor(), michael@0: aThebesBufferData, michael@0: aUpdatedRegion)); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::UpdateTextureIncremental(CompositableClient* aCompositable, michael@0: TextureIdentifier aTextureId, michael@0: SurfaceDescriptor& aDescriptor, michael@0: const nsIntRegion& aUpdatedRegion, michael@0: const nsIntRect& aBufferRect, michael@0: const nsIntPoint& aBufferRotation) michael@0: { michael@0: CheckSurfaceDescriptor(&aDescriptor); michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: mTxn->AddNoSwapPaint(OpPaintTextureIncremental(nullptr, aCompositable->GetIPDLActor(), michael@0: aTextureId, michael@0: aDescriptor, michael@0: aUpdatedRegion, michael@0: aBufferRect, michael@0: aBufferRotation)); michael@0: } michael@0: michael@0: michael@0: void michael@0: ShadowLayerForwarder::UpdatePictureRect(CompositableClient* aCompositable, michael@0: const nsIntRect& aRect) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: mTxn->AddNoSwapPaint(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect)); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::UpdatedTexture(CompositableClient* aCompositable, michael@0: TextureClient* aTexture, michael@0: nsIntRegion* aRegion) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aTexture); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: MOZ_ASSERT(aTexture->GetIPDLActor()); michael@0: MaybeRegion region = aRegion ? MaybeRegion(*aRegion) michael@0: : MaybeRegion(null_t()); michael@0: if (aTexture->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) { michael@0: mTxn->AddPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(), michael@0: nullptr, aTexture->GetIPDLActor(), michael@0: region)); michael@0: } else { michael@0: mTxn->AddNoSwapPaint(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(), michael@0: nullptr, aTexture->GetIPDLActor(), michael@0: region)); michael@0: } michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable, michael@0: TextureClient* aTexture) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aTexture); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: MOZ_ASSERT(aTexture->GetIPDLActor()); michael@0: mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(), michael@0: nullptr, aTexture->GetIPDLActor())); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositable, michael@0: TextureClient* aTextureOnBlack, michael@0: TextureClient* aTextureOnWhite) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aTextureOnWhite); michael@0: MOZ_ASSERT(aTextureOnBlack); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: MOZ_ASSERT(aTextureOnBlack->GetIPDLActor()); michael@0: MOZ_ASSERT(aTextureOnWhite->GetIPDLActor()); michael@0: MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize()); michael@0: mTxn->AddEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(), michael@0: nullptr, aTextureOnBlack->GetIPDLActor(), michael@0: nullptr, aTextureOnWhite->GetIPDLActor())); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::RemoveTextureFromCompositable(CompositableClient* aCompositable, michael@0: TextureClient* aTexture) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aTexture); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: MOZ_ASSERT(aTexture->GetIPDLActor()); michael@0: mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(), michael@0: nullptr, aTexture->GetIPDLActor())); michael@0: if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) { michael@0: mTxn->MarkSyncTransaction(); michael@0: } michael@0: // Hold texture until transaction complete. michael@0: HoldUntilTransaction(aTexture); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::RemoveTexture(TextureClient* aTexture) michael@0: { michael@0: MOZ_ASSERT(aTexture); michael@0: aTexture->ForceRemove(); michael@0: } michael@0: michael@0: bool michael@0: ShadowLayerForwarder::EndTransaction(InfallibleTArray* aReplies, michael@0: const nsIntRegion& aRegionToClear, michael@0: bool aScheduleComposite, michael@0: bool* aSent) michael@0: { michael@0: *aSent = false; michael@0: michael@0: PROFILER_LABEL("ShadowLayerForwarder", "EndTranscation"); michael@0: RenderTraceScope rendertrace("Foward Transaction", "000091"); michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to"); michael@0: NS_ABORT_IF_FALSE(!mTxn->Finished(), "forgot BeginTransaction?"); michael@0: michael@0: DiagnosticTypes diagnostics = gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes(); michael@0: if (mDiagnosticTypes != diagnostics) { michael@0: mDiagnosticTypes = diagnostics; michael@0: mTxn->AddEdit(OpSetDiagnosticTypes(diagnostics)); michael@0: } michael@0: michael@0: AutoTxnEnd _(mTxn); michael@0: michael@0: if (mTxn->Empty() && !mTxn->RotationChanged() && !mWindowOverlayChanged) { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] 0-length cset (?) and no rotation event, skipping Update()")); michael@0: return true; michael@0: } michael@0: michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers...")); michael@0: michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] building transaction...")); michael@0: michael@0: // We purposely add attribute-change ops to the final changeset michael@0: // before we add paint ops. This allows layers to record the michael@0: // attribute changes before new pixels arrive, which can be useful michael@0: // for setting up back/front buffers. michael@0: RenderTraceScope rendertrace2("Foward Transaction", "000092"); michael@0: for (ShadowableLayerSet::const_iterator it = mTxn->mMutants.begin(); michael@0: it != mTxn->mMutants.end(); ++it) { michael@0: ShadowableLayer* shadow = *it; michael@0: Layer* mutant = shadow->AsLayer(); michael@0: NS_ABORT_IF_FALSE(!!mutant, "unshadowable layer?"); michael@0: michael@0: LayerAttributes attrs; michael@0: CommonLayerAttributes& common = attrs.common(); michael@0: common.visibleRegion() = mutant->GetVisibleRegion(); michael@0: common.eventRegions() = mutant->GetEventRegions(); michael@0: common.postXScale() = mutant->GetPostXScale(); michael@0: common.postYScale() = mutant->GetPostYScale(); michael@0: common.transform() = mutant->GetBaseTransform(); michael@0: common.contentFlags() = mutant->GetContentFlags(); michael@0: common.opacity() = mutant->GetOpacity(); michael@0: common.useClipRect() = !!mutant->GetClipRect(); michael@0: common.clipRect() = (common.useClipRect() ? michael@0: *mutant->GetClipRect() : nsIntRect()); michael@0: common.isFixedPosition() = mutant->GetIsFixedPosition(); michael@0: common.fixedPositionAnchor() = mutant->GetFixedPositionAnchor(); michael@0: common.fixedPositionMargin() = mutant->GetFixedPositionMargins(); michael@0: common.isStickyPosition() = mutant->GetIsStickyPosition(); michael@0: if (mutant->GetIsStickyPosition()) { michael@0: common.stickyScrollContainerId() = mutant->GetStickyScrollContainerId(); michael@0: common.stickyScrollRangeOuter() = mutant->GetStickyScrollRangeOuter(); michael@0: common.stickyScrollRangeInner() = mutant->GetStickyScrollRangeInner(); michael@0: } michael@0: common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId(); michael@0: common.scrollbarDirection() = mutant->GetScrollbarDirection(); michael@0: if (Layer* maskLayer = mutant->GetMaskLayer()) { michael@0: common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer()); michael@0: } else { michael@0: common.maskLayerChild() = nullptr; michael@0: } michael@0: common.maskLayerParent() = nullptr; michael@0: common.animations() = mutant->GetAnimations(); michael@0: common.invalidRegion() = mutant->GetInvalidRegion(); michael@0: attrs.specific() = null_t(); michael@0: mutant->FillSpecificAttributes(attrs.specific()); michael@0: michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] OpSetLayerAttributes(%p)\n", mutant)); michael@0: michael@0: mTxn->AddEdit(OpSetLayerAttributes(nullptr, Shadow(shadow), attrs)); michael@0: } michael@0: michael@0: AutoInfallibleTArray cset; michael@0: size_t nCsets = mTxn->mCset.size() + mTxn->mPaints.size(); michael@0: NS_ABORT_IF_FALSE(nCsets > 0 || mWindowOverlayChanged, "should have bailed by now"); michael@0: michael@0: cset.SetCapacity(nCsets); michael@0: if (!mTxn->mCset.empty()) { michael@0: cset.AppendElements(&mTxn->mCset.front(), mTxn->mCset.size()); michael@0: } michael@0: // Paints after non-paint ops, including attribute changes. See michael@0: // above. michael@0: if (!mTxn->mPaints.empty()) { michael@0: cset.AppendElements(&mTxn->mPaints.front(), mTxn->mPaints.size()); michael@0: } michael@0: michael@0: mWindowOverlayChanged = false; michael@0: michael@0: TargetConfig targetConfig(mTxn->mTargetBounds, michael@0: mTxn->mTargetRotation, michael@0: mTxn->mClientBounds, michael@0: mTxn->mTargetOrientation, michael@0: aRegionToClear); michael@0: michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send...")); michael@0: PlatformSyncBeforeUpdate(); michael@0: michael@0: profiler_tracing("Paint", "Rasterize", TRACING_INTERVAL_END); michael@0: if (mTxn->mSwapRequired) { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction...")); michael@0: RenderTraceScope rendertrace3("Forward Transaction", "000093"); michael@0: if (!HasShadowManager() || michael@0: !mShadowManager->IPCOpen() || michael@0: !mShadowManager->SendUpdate(cset, targetConfig, mIsFirstPaint, michael@0: aScheduleComposite, aReplies)) { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!")); michael@0: return false; michael@0: } michael@0: } else { michael@0: // If we don't require a swap we can call SendUpdateNoSwap which michael@0: // assumes that aReplies is empty (DEBUG assertion) michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction...")); michael@0: RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093"); michael@0: if (!HasShadowManager() || michael@0: !mShadowManager->IPCOpen() || michael@0: !mShadowManager->SendUpdateNoSwap(cset, targetConfig, mIsFirstPaint, aScheduleComposite)) { michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!")); michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: *aSent = true; michael@0: mIsFirstPaint = false; michael@0: MOZ_LAYERS_LOG(("[LayersForwarder] ... done")); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: ShadowLayerForwarder::AllocShmem(size_t aSize, michael@0: ipc::SharedMemory::SharedMemoryType aType, michael@0: ipc::Shmem* aShmem) michael@0: { michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager"); michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return false; michael@0: } michael@0: return mShadowManager->AllocShmem(aSize, aType, aShmem); michael@0: } michael@0: bool michael@0: ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize, michael@0: ipc::SharedMemory::SharedMemoryType aType, michael@0: ipc::Shmem* aShmem) michael@0: { michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager"); michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return false; michael@0: } michael@0: return mShadowManager->AllocUnsafeShmem(aSize, aType, aShmem); michael@0: } michael@0: void michael@0: ShadowLayerForwarder::DeallocShmem(ipc::Shmem& aShmem) michael@0: { michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager"); michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return; michael@0: } michael@0: mShadowManager->DeallocShmem(aShmem); michael@0: } michael@0: michael@0: bool michael@0: ShadowLayerForwarder::IPCOpen() const michael@0: { michael@0: return mShadowManager->IPCOpen(); michael@0: } michael@0: michael@0: bool michael@0: ShadowLayerForwarder::IsSameProcess() const michael@0: { michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return false; michael@0: } michael@0: return mShadowManager->OtherProcess() == kInvalidProcessHandle; michael@0: } michael@0: michael@0: /** michael@0: * We bail out when we have no shadow manager. That can happen when the michael@0: * layer manager is created by the preallocated process. michael@0: * See bug 914843 for details. michael@0: */ michael@0: PLayerChild* michael@0: ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer) michael@0: { michael@0: NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to"); michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return nullptr; michael@0: } michael@0: return mShadowManager->SendPLayerConstructor(new ShadowLayerChild(aLayer)); michael@0: } michael@0: michael@0: #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS) michael@0: michael@0: /*static*/ void michael@0: ShadowLayerForwarder::PlatformSyncBeforeUpdate() michael@0: { michael@0: } michael@0: michael@0: #endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS) michael@0: michael@0: void michael@0: ShadowLayerForwarder::Connect(CompositableClient* aCompositable) michael@0: { michael@0: #ifdef GFX_COMPOSITOR_LOGGING michael@0: printf("ShadowLayerForwarder::Connect(Compositable)\n"); michael@0: #endif michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(mShadowManager); michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return; michael@0: } michael@0: PCompositableChild* actor = michael@0: mShadowManager->SendPCompositableConstructor(aCompositable->GetTextureInfo()); michael@0: MOZ_ASSERT(actor); michael@0: aCompositable->InitIPDLActor(actor); michael@0: } michael@0: michael@0: void michael@0: ShadowLayerForwarder::CreatedIncrementalBuffer(CompositableClient* aCompositable, michael@0: const TextureInfo& aTextureInfo, michael@0: const nsIntRect& aBufferRect) michael@0: { michael@0: MOZ_ASSERT(aCompositable); michael@0: mTxn->AddNoSwapPaint(OpCreatedIncrementalTexture(nullptr, aCompositable->GetIPDLActor(), michael@0: aTextureInfo, aBufferRect)); michael@0: } michael@0: michael@0: void ShadowLayerForwarder::Attach(CompositableClient* aCompositable, michael@0: ShadowableLayer* aLayer) michael@0: { michael@0: MOZ_ASSERT(aLayer); michael@0: MOZ_ASSERT(aCompositable); michael@0: MOZ_ASSERT(aCompositable->GetIPDLActor()); michael@0: mTxn->AddEdit(OpAttachCompositable(nullptr, Shadow(aLayer), michael@0: nullptr, aCompositable->GetIPDLActor())); michael@0: } michael@0: michael@0: void ShadowLayerForwarder::AttachAsyncCompositable(uint64_t aCompositableID, michael@0: ShadowableLayer* aLayer) michael@0: { michael@0: MOZ_ASSERT(aLayer); michael@0: MOZ_ASSERT(aCompositableID != 0); // zero is always an invalid compositable id. michael@0: mTxn->AddEdit(OpAttachAsyncCompositable(nullptr, Shadow(aLayer), michael@0: aCompositableID)); michael@0: } michael@0: michael@0: PTextureChild* michael@0: ShadowLayerForwarder::CreateTexture(const SurfaceDescriptor& aSharedData, michael@0: TextureFlags aFlags) michael@0: { michael@0: if (!mShadowManager->IPCOpen()) { michael@0: return nullptr; michael@0: } michael@0: return mShadowManager->SendPTextureConstructor(aSharedData, aFlags); michael@0: } michael@0: michael@0: michael@0: void ShadowLayerForwarder::SetShadowManager(PLayerTransactionChild* aShadowManager) michael@0: { michael@0: mShadowManager = static_cast(aShadowManager); michael@0: } michael@0: michael@0: michael@0: } // namespace layers michael@0: } // namespace mozilla