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 "LayerTransactionParent.h" michael@0: #include // for vector michael@0: #include "CompositableHost.h" // for CompositableParent, Get, etc michael@0: #include "ImageLayers.h" // for ImageLayer michael@0: #include "Layers.h" // for Layer, ContainerLayer, etc michael@0: #include "ShadowLayerParent.h" // for ShadowLayerParent michael@0: #include "gfx3DMatrix.h" // for gfx3DMatrix michael@0: #include "gfxPoint3D.h" // for gfxPoint3D michael@0: #include "CompositableTransactionParent.h" // for EditReplyVector michael@0: #include "ShadowLayersManager.h" // for ShadowLayersManager michael@0: #include "mozilla/gfx/BasePoint3D.h" // for BasePoint3D michael@0: #include "mozilla/layers/CanvasLayerComposite.h" michael@0: #include "mozilla/layers/ColorLayerComposite.h" michael@0: #include "mozilla/layers/Compositor.h" // for Compositor michael@0: #include "mozilla/layers/ContainerLayerComposite.h" michael@0: #include "mozilla/layers/ImageLayerComposite.h" michael@0: #include "mozilla/layers/LayerManagerComposite.h" michael@0: #include "mozilla/layers/LayersMessages.h" // for EditReply, etc michael@0: #include "mozilla/layers/LayersSurfaces.h" // for PGrallocBufferParent michael@0: #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG michael@0: #include "mozilla/layers/PCompositableParent.h" michael@0: #include "mozilla/layers/PLayerParent.h" // for PLayerParent michael@0: #include "mozilla/layers/ThebesLayerComposite.h" michael@0: #include "mozilla/mozalloc.h" // for operator delete, etc michael@0: #include "nsCoord.h" // for NSAppUnitsToFloatPixels michael@0: #include "nsDebug.h" // for NS_RUNTIMEABORT michael@0: #include "nsDeviceContext.h" // for AppUnitsPerCSSPixel michael@0: #include "nsISupportsImpl.h" // for Layer::Release, etc michael@0: #include "nsLayoutUtils.h" // for nsLayoutUtils michael@0: #include "nsMathUtils.h" // for NS_round michael@0: #include "nsPoint.h" // for nsPoint michael@0: #include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc michael@0: #include "GeckoProfiler.h" michael@0: #include "mozilla/layers/TextureHost.h" michael@0: #include "mozilla/layers/AsyncCompositionManager.h" michael@0: #include "mozilla/layers/AsyncPanZoomController.h" michael@0: michael@0: typedef std::vector EditReplyVector; michael@0: michael@0: using mozilla::layout::RenderFrameParent; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: class PGrallocBufferParent; michael@0: michael@0: //-------------------------------------------------- michael@0: // Convenience accessors michael@0: static ShadowLayerParent* michael@0: cast(const PLayerParent* in) michael@0: { michael@0: return const_cast( michael@0: static_cast(in)); michael@0: } michael@0: michael@0: template michael@0: static ShadowLayerParent* michael@0: AsLayerComposite(const OpCreateT& op) michael@0: { michael@0: return cast(op.layerParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: AsLayerComposite(const OpSetRoot& op) michael@0: { michael@0: return cast(op.rootParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: ShadowContainer(const OpInsertAfter& op) michael@0: { michael@0: return cast(op.containerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowChild(const OpInsertAfter& op) michael@0: { michael@0: return cast(op.childLayerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowAfter(const OpInsertAfter& op) michael@0: { michael@0: return cast(op.afterParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: ShadowContainer(const OpPrependChild& op) michael@0: { michael@0: return cast(op.containerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowChild(const OpPrependChild& op) michael@0: { michael@0: return cast(op.childLayerParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: ShadowContainer(const OpRemoveChild& op) michael@0: { michael@0: return cast(op.containerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowChild(const OpRemoveChild& op) michael@0: { michael@0: return cast(op.childLayerParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: ShadowContainer(const OpRepositionChild& op) michael@0: { michael@0: return cast(op.containerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowChild(const OpRepositionChild& op) michael@0: { michael@0: return cast(op.childLayerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowAfter(const OpRepositionChild& op) michael@0: { michael@0: return cast(op.afterParent()); michael@0: } michael@0: michael@0: static ShadowLayerParent* michael@0: ShadowContainer(const OpRaiseToTopChild& op) michael@0: { michael@0: return cast(op.containerParent()); michael@0: } michael@0: static ShadowLayerParent* michael@0: ShadowChild(const OpRaiseToTopChild& op) michael@0: { michael@0: return cast(op.childLayerParent()); michael@0: } michael@0: michael@0: //-------------------------------------------------- michael@0: // LayerTransactionParent michael@0: LayerTransactionParent::LayerTransactionParent(LayerManagerComposite* aManager, michael@0: ShadowLayersManager* aLayersManager, michael@0: uint64_t aId) michael@0: : mLayerManager(aManager) michael@0: , mShadowLayersManager(aLayersManager) michael@0: , mId(aId) michael@0: , mDestroyed(false) michael@0: , mIPCOpen(false) michael@0: { michael@0: MOZ_COUNT_CTOR(LayerTransactionParent); michael@0: } michael@0: michael@0: LayerTransactionParent::~LayerTransactionParent() michael@0: { michael@0: MOZ_COUNT_DTOR(LayerTransactionParent); michael@0: } michael@0: michael@0: void michael@0: LayerTransactionParent::Destroy() michael@0: { michael@0: mDestroyed = true; michael@0: for (size_t i = 0; i < ManagedPLayerParent().Length(); ++i) { michael@0: ShadowLayerParent* slp = michael@0: static_cast(ManagedPLayerParent()[i]); michael@0: slp->Destroy(); michael@0: } michael@0: } michael@0: michael@0: LayersBackend michael@0: LayerTransactionParent::GetCompositorBackendType() const michael@0: { michael@0: return mLayerManager->GetBackendType(); michael@0: } michael@0: michael@0: /* virtual */ michael@0: bool michael@0: LayerTransactionParent::RecvUpdateNoSwap(const InfallibleTArray& cset, michael@0: const TargetConfig& targetConfig, michael@0: const bool& isFirstPaint, michael@0: const bool& scheduleComposite) michael@0: { michael@0: return RecvUpdate(cset, targetConfig, isFirstPaint, scheduleComposite, nullptr); michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvUpdate(const InfallibleTArray& cset, michael@0: const TargetConfig& targetConfig, michael@0: const bool& isFirstPaint, michael@0: const bool& scheduleComposite, michael@0: InfallibleTArray* reply) michael@0: { michael@0: profiler_tracing("Paint", "Composite", TRACING_INTERVAL_START); michael@0: PROFILER_LABEL("LayerTransactionParent", "RecvUpdate"); michael@0: #ifdef COMPOSITOR_PERFORMANCE_WARNING michael@0: TimeStamp updateStart = TimeStamp::Now(); michael@0: #endif michael@0: michael@0: MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length())); michael@0: michael@0: if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { michael@0: return true; michael@0: } michael@0: michael@0: if (mLayerManager && mLayerManager->GetCompositor() && michael@0: !targetConfig.naturalBounds().IsEmpty()) { michael@0: mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation()); michael@0: } michael@0: michael@0: // Clear fence handles used in previsou transaction. michael@0: ClearPrevFenceHandles(); michael@0: michael@0: EditReplyVector replyv; michael@0: michael@0: { michael@0: AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this)); michael@0: layer_manager()->BeginTransaction(); michael@0: } michael@0: michael@0: for (EditArray::index_type i = 0; i < cset.Length(); ++i) { michael@0: const Edit& edit = cset[i]; michael@0: michael@0: switch (edit.type()) { michael@0: // Create* ops michael@0: case Edit::TOpCreateThebesLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateThebesLayer")); michael@0: michael@0: nsRefPtr layer = michael@0: layer_manager()->CreateThebesLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateThebesLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: case Edit::TOpCreateContainerLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateContainerLayer")); michael@0: michael@0: nsRefPtr layer = layer_manager()->CreateContainerLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateContainerLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: case Edit::TOpCreateImageLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateImageLayer")); michael@0: michael@0: nsRefPtr layer = michael@0: layer_manager()->CreateImageLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateImageLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: case Edit::TOpCreateColorLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateColorLayer")); michael@0: michael@0: nsRefPtr layer = layer_manager()->CreateColorLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateColorLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: case Edit::TOpCreateCanvasLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateCanvasLayer")); michael@0: michael@0: nsRefPtr layer = michael@0: layer_manager()->CreateCanvasLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateCanvasLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: case Edit::TOpCreateRefLayer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] CreateRefLayer")); michael@0: michael@0: nsRefPtr layer = michael@0: layer_manager()->CreateRefLayerComposite(); michael@0: AsLayerComposite(edit.get_OpCreateRefLayer())->Bind(layer); michael@0: break; michael@0: } michael@0: michael@0: // Attributes michael@0: case Edit::TOpSetLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes")); michael@0: michael@0: const OpSetLayerAttributes& osla = edit.get_OpSetLayerAttributes(); michael@0: ShadowLayerParent* layerParent = AsLayerComposite(osla); michael@0: Layer* layer = layerParent->AsLayer(); michael@0: if (!layer) { michael@0: return false; michael@0: } michael@0: const LayerAttributes& attrs = osla.attrs(); michael@0: michael@0: const CommonLayerAttributes& common = attrs.common(); michael@0: layer->SetVisibleRegion(common.visibleRegion()); michael@0: layer->SetEventRegions(common.eventRegions()); michael@0: layer->SetContentFlags(common.contentFlags()); michael@0: layer->SetOpacity(common.opacity()); michael@0: layer->SetClipRect(common.useClipRect() ? &common.clipRect() : nullptr); michael@0: layer->SetBaseTransform(common.transform().value()); michael@0: layer->SetPostScale(common.postXScale(), common.postYScale()); michael@0: layer->SetIsFixedPosition(common.isFixedPosition()); michael@0: layer->SetFixedPositionAnchor(common.fixedPositionAnchor()); michael@0: layer->SetFixedPositionMargins(common.fixedPositionMargin()); michael@0: if (common.isStickyPosition()) { michael@0: layer->SetStickyPositionData(common.stickyScrollContainerId(), michael@0: common.stickyScrollRangeOuter(), michael@0: common.stickyScrollRangeInner()); michael@0: } michael@0: layer->SetScrollbarData(common.scrollbarTargetContainerId(), michael@0: static_cast(common.scrollbarDirection())); michael@0: if (PLayerParent* maskLayer = common.maskLayerParent()) { michael@0: layer->SetMaskLayer(cast(maskLayer)->AsLayer()); michael@0: } else { michael@0: layer->SetMaskLayer(nullptr); michael@0: } michael@0: layer->SetAnimations(common.animations()); michael@0: layer->SetInvalidRegion(common.invalidRegion()); michael@0: michael@0: typedef SpecificLayerAttributes Specific; michael@0: const SpecificLayerAttributes& specific = attrs.specific(); michael@0: switch (specific.type()) { michael@0: case Specific::Tnull_t: michael@0: break; michael@0: michael@0: case Specific::TThebesLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] thebes layer")); michael@0: michael@0: ThebesLayerComposite* thebesLayer = layerParent->AsThebesLayerComposite(); michael@0: if (!thebesLayer) { michael@0: return false; michael@0: } michael@0: const ThebesLayerAttributes& attrs = michael@0: specific.get_ThebesLayerAttributes(); michael@0: michael@0: thebesLayer->SetValidRegion(attrs.validRegion()); michael@0: michael@0: break; michael@0: } michael@0: case Specific::TContainerLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] container layer")); michael@0: michael@0: ContainerLayerComposite* containerLayer = layerParent->AsContainerLayerComposite(); michael@0: if (!containerLayer) { michael@0: return false; michael@0: } michael@0: const ContainerLayerAttributes& attrs = michael@0: specific.get_ContainerLayerAttributes(); michael@0: containerLayer->SetFrameMetrics(attrs.metrics()); michael@0: containerLayer->SetScrollHandoffParentId(attrs.scrollParentId()); michael@0: containerLayer->SetPreScale(attrs.preXScale(), attrs.preYScale()); michael@0: containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale()); michael@0: break; michael@0: } michael@0: case Specific::TColorLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] color layer")); michael@0: michael@0: ColorLayerComposite* colorLayer = layerParent->AsColorLayerComposite(); michael@0: if (!colorLayer) { michael@0: return false; michael@0: } michael@0: colorLayer->SetColor(specific.get_ColorLayerAttributes().color().value()); michael@0: colorLayer->SetBounds(specific.get_ColorLayerAttributes().bounds()); michael@0: break; michael@0: } michael@0: case Specific::TCanvasLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] canvas layer")); michael@0: michael@0: CanvasLayerComposite* canvasLayer = layerParent->AsCanvasLayerComposite(); michael@0: if (!canvasLayer) { michael@0: return false; michael@0: } michael@0: canvasLayer->SetFilter(specific.get_CanvasLayerAttributes().filter()); michael@0: canvasLayer->SetBounds(specific.get_CanvasLayerAttributes().bounds()); michael@0: break; michael@0: } michael@0: case Specific::TRefLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] ref layer")); michael@0: michael@0: RefLayerComposite* refLayer = layerParent->AsRefLayerComposite(); michael@0: if (!refLayer) { michael@0: return false; michael@0: } michael@0: refLayer->SetReferentId(specific.get_RefLayerAttributes().id()); michael@0: break; michael@0: } michael@0: case Specific::TImageLayerAttributes: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] image layer")); michael@0: michael@0: ImageLayerComposite* imageLayer = layerParent->AsImageLayerComposite(); michael@0: if (!imageLayer) { michael@0: return false; michael@0: } michael@0: const ImageLayerAttributes& attrs = specific.get_ImageLayerAttributes(); michael@0: imageLayer->SetFilter(attrs.filter()); michael@0: imageLayer->SetScaleToSize(attrs.scaleToSize(), attrs.scaleMode()); michael@0: break; michael@0: } michael@0: default: michael@0: NS_RUNTIMEABORT("not reached"); michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpSetDiagnosticTypes: { michael@0: mLayerManager->GetCompositor()->SetDiagnosticTypes( michael@0: edit.get_OpSetDiagnosticTypes().diagnostics()); michael@0: break; michael@0: } michael@0: // Tree ops michael@0: case Edit::TOpSetRoot: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] SetRoot")); michael@0: michael@0: Layer* newRoot = AsLayerComposite(edit.get_OpSetRoot())->AsLayer(); michael@0: if (!newRoot) { michael@0: return false; michael@0: } michael@0: if (newRoot->GetParent()) { michael@0: // newRoot is not a root! michael@0: return false; michael@0: } michael@0: mRoot = newRoot; michael@0: break; michael@0: } michael@0: case Edit::TOpInsertAfter: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] InsertAfter")); michael@0: michael@0: const OpInsertAfter& oia = edit.get_OpInsertAfter(); michael@0: Layer* child = ShadowChild(oia)->AsLayer(); michael@0: if (!child) { michael@0: return false; michael@0: } michael@0: ContainerLayerComposite* container = ShadowContainer(oia)->AsContainerLayerComposite(); michael@0: if (!container || michael@0: !container->InsertAfter(child, ShadowAfter(oia)->AsLayer())) michael@0: { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpPrependChild: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] PrependChild")); michael@0: michael@0: const OpPrependChild& oac = edit.get_OpPrependChild(); michael@0: Layer* child = ShadowChild(oac)->AsLayer(); michael@0: if (!child) { michael@0: return false; michael@0: } michael@0: ContainerLayerComposite* container = ShadowContainer(oac)->AsContainerLayerComposite(); michael@0: if (!container || michael@0: !container->InsertAfter(child, nullptr)) michael@0: { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpRemoveChild: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] RemoveChild")); michael@0: michael@0: const OpRemoveChild& orc = edit.get_OpRemoveChild(); michael@0: Layer* childLayer = ShadowChild(orc)->AsLayer(); michael@0: if (!childLayer) { michael@0: return false; michael@0: } michael@0: ContainerLayerComposite* container = ShadowContainer(orc)->AsContainerLayerComposite(); michael@0: if (!container || michael@0: !container->RemoveChild(childLayer)) michael@0: { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpRepositionChild: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] RepositionChild")); michael@0: michael@0: const OpRepositionChild& orc = edit.get_OpRepositionChild(); michael@0: Layer* child = ShadowChild(orc)->AsLayer(); michael@0: if (!child) { michael@0: return false; michael@0: } michael@0: ContainerLayerComposite* container = ShadowContainer(orc)->AsContainerLayerComposite(); michael@0: if (!container || michael@0: !container->RepositionChild(child, ShadowAfter(orc)->AsLayer())) michael@0: { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpRaiseToTopChild: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] RaiseToTopChild")); michael@0: michael@0: const OpRaiseToTopChild& rtc = edit.get_OpRaiseToTopChild(); michael@0: Layer* child = ShadowChild(rtc)->AsLayer(); michael@0: if (!child) { michael@0: return false; michael@0: } michael@0: ContainerLayerComposite* container = ShadowContainer(rtc)->AsContainerLayerComposite(); michael@0: if (!container || michael@0: !container->RepositionChild(child, nullptr)) michael@0: { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TCompositableOperation: { michael@0: if (!ReceiveCompositableUpdate(edit.get_CompositableOperation(), michael@0: replyv)) { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case Edit::TOpAttachCompositable: { michael@0: const OpAttachCompositable& op = edit.get_OpAttachCompositable(); michael@0: CompositableHost* host = CompositableHost::FromIPDLActor(op.compositableParent()); michael@0: if (!Attach(cast(op.layerParent()), host, false)) { michael@0: return false; michael@0: } michael@0: host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID()); michael@0: break; michael@0: } michael@0: case Edit::TOpAttachAsyncCompositable: { michael@0: const OpAttachAsyncCompositable& op = edit.get_OpAttachAsyncCompositable(); michael@0: PCompositableParent* compositableParent = CompositableMap::Get(op.containerID()); michael@0: if (!compositableParent) { michael@0: NS_ERROR("CompositableParent not found in the map"); michael@0: return false; michael@0: } michael@0: CompositableHost* host = CompositableHost::FromIPDLActor(compositableParent); michael@0: if (!Attach(cast(op.layerParent()), host, true)) { michael@0: return false; michael@0: } michael@0: michael@0: host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID()); michael@0: break; michael@0: } michael@0: default: michael@0: NS_RUNTIMEABORT("not reached"); michael@0: } michael@0: } michael@0: michael@0: { michael@0: AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this)); michael@0: layer_manager()->EndTransaction(nullptr, nullptr, LayerManager::END_NO_IMMEDIATE_REDRAW); michael@0: } michael@0: michael@0: if (reply) { michael@0: reply->SetCapacity(replyv.size()); michael@0: if (replyv.size() > 0) { michael@0: reply->AppendElements(&replyv.front(), replyv.size()); michael@0: } michael@0: } michael@0: michael@0: // Ensure that any pending operations involving back and front michael@0: // buffers have completed, so that neither process stomps on the michael@0: // other's buffer contents. michael@0: LayerManagerComposite::PlatformSyncBeforeReplyUpdate(); michael@0: michael@0: mShadowLayersManager->ShadowLayersUpdated(this, targetConfig, isFirstPaint, scheduleComposite); michael@0: michael@0: #ifdef COMPOSITOR_PERFORMANCE_WARNING michael@0: int compositeTime = (int)(mozilla::TimeStamp::Now() - updateStart).ToMilliseconds(); michael@0: if (compositeTime > 15) { michael@0: printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n", compositeTime); michael@0: } michael@0: #endif michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvSetTestSampleTime(const TimeStamp& aTime) michael@0: { michael@0: return mShadowLayersManager->SetTestSampleTime(this, aTime); michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvLeaveTestMode() michael@0: { michael@0: mShadowLayersManager->LeaveTestMode(this); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvGetOpacity(PLayerParent* aParent, michael@0: float* aOpacity) michael@0: { michael@0: if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { michael@0: return false; michael@0: } michael@0: michael@0: Layer* layer = cast(aParent)->AsLayer(); michael@0: if (!layer) { michael@0: return false; michael@0: } michael@0: michael@0: *aOpacity = layer->GetLocalOpacity(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent, michael@0: MaybeTransform* aTransform) michael@0: { michael@0: if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { michael@0: return false; michael@0: } michael@0: michael@0: Layer* layer = cast(aParent)->AsLayer(); michael@0: if (!layer) { michael@0: return false; michael@0: } michael@0: michael@0: // This method is specific to transforms applied by animation. michael@0: // This is because this method uses the information stored with an animation michael@0: // such as the origin of the reference frame corresponding to the layer, to michael@0: // recover the untranslated transform from the shadow transform. For michael@0: // transforms that are not set by animation we don't have this information michael@0: // available. michael@0: if (!layer->AsLayerComposite()->GetShadowTransformSetByAnimation()) { michael@0: *aTransform = mozilla::void_t(); michael@0: return true; michael@0: } michael@0: michael@0: // The following code recovers the untranslated transform michael@0: // from the shadow transform by undoing the translations in michael@0: // AsyncCompositionManager::SampleValue. michael@0: michael@0: gfx3DMatrix transform; michael@0: gfx::To3DMatrix(layer->AsLayerComposite()->GetShadowTransform(), transform); michael@0: if (ContainerLayer* c = layer->AsContainerLayer()) { michael@0: // Undo the scale transform applied by AsyncCompositionManager::SampleValue michael@0: transform.ScalePost(1.0f/c->GetInheritedXScale(), michael@0: 1.0f/c->GetInheritedYScale(), michael@0: 1.0f); michael@0: } michael@0: float scale = 1; michael@0: gfxPoint3D scaledOrigin; michael@0: gfxPoint3D transformOrigin; michael@0: for (uint32_t i=0; i < layer->GetAnimations().Length(); i++) { michael@0: if (layer->GetAnimations()[i].data().type() == AnimationData::TTransformData) { michael@0: const TransformData& data = layer->GetAnimations()[i].data().get_TransformData(); michael@0: scale = data.appUnitsPerDevPixel(); michael@0: scaledOrigin = michael@0: gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(data.origin().x, scale)), michael@0: NS_round(NSAppUnitsToFloatPixels(data.origin().y, scale)), michael@0: 0.0f); michael@0: double cssPerDev = michael@0: double(nsDeviceContext::AppUnitsPerCSSPixel()) / double(scale); michael@0: transformOrigin = data.transformOrigin() * cssPerDev; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: // Undo the translation to the origin of the reference frame applied by michael@0: // AsyncCompositionManager::SampleValue michael@0: transform.Translate(-scaledOrigin); michael@0: michael@0: // Undo the rebasing applied by michael@0: // nsDisplayTransform::GetResultingTransformMatrixInternal michael@0: transform = nsLayoutUtils::ChangeMatrixBasis(-scaledOrigin - transformOrigin, michael@0: transform); michael@0: michael@0: // Convert to CSS pixels (this undoes the operations performed by michael@0: // nsStyleTransformMatrix::ProcessTranslatePart which is called from michael@0: // nsDisplayTransform::GetResultingTransformMatrix) michael@0: double devPerCss = michael@0: double(scale) / double(nsDeviceContext::AppUnitsPerCSSPixel()); michael@0: transform._41 *= devPerCss; michael@0: transform._42 *= devPerCss; michael@0: transform._43 *= devPerCss; michael@0: michael@0: *aTransform = transform; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvSetAsyncScrollOffset(PLayerParent* aLayer, michael@0: const int32_t& aX, const int32_t& aY) michael@0: { michael@0: if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { michael@0: return false; michael@0: } michael@0: michael@0: Layer* layer = cast(aLayer)->AsLayer(); michael@0: if (!layer) { michael@0: return false; michael@0: } michael@0: ContainerLayer* containerLayer = layer->AsContainerLayer(); michael@0: if (!containerLayer) { michael@0: return false; michael@0: } michael@0: AsyncPanZoomController* controller = containerLayer->GetAsyncPanZoomController(); michael@0: if (!controller) { michael@0: return false; michael@0: } michael@0: controller->SetTestAsyncScrollOffset(CSSPoint(aX, aY)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::Attach(ShadowLayerParent* aLayerParent, michael@0: CompositableHost* aCompositable, michael@0: bool aIsAsync) michael@0: { michael@0: if (!aCompositable) { michael@0: return false; michael@0: } michael@0: michael@0: Layer* baselayer = aLayerParent->AsLayer(); michael@0: if (!baselayer) { michael@0: return false; michael@0: } michael@0: LayerComposite* layer = baselayer->AsLayerComposite(); michael@0: if (!layer) { michael@0: return false; michael@0: } michael@0: michael@0: Compositor* compositor michael@0: = static_cast(aLayerParent->AsLayer()->Manager())->GetCompositor(); michael@0: michael@0: if (!layer->SetCompositableHost(aCompositable)) { michael@0: // not all layer types accept a compositable, see bug 967824 michael@0: return false; michael@0: } michael@0: aCompositable->Attach(aLayerParent->AsLayer(), michael@0: compositor, michael@0: aIsAsync michael@0: ? CompositableHost::ALLOW_REATTACH michael@0: | CompositableHost::KEEP_ATTACHED michael@0: : CompositableHost::NO_FLAGS); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvClearCachedResources() michael@0: { michael@0: if (mRoot) { michael@0: // NB: |mRoot| here is the *child* context's root. In this parent michael@0: // context, it's just a subtree root. We need to scope the clear michael@0: // of resources to exactly that subtree, so we specify it here. michael@0: mLayerManager->ClearCachedResources(mRoot); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::RecvForceComposite() michael@0: { michael@0: mShadowLayersManager->ForceComposite(this); michael@0: return true; michael@0: } michael@0: michael@0: michael@0: PGrallocBufferParent* michael@0: LayerTransactionParent::AllocPGrallocBufferParent(const IntSize& aSize, michael@0: const uint32_t& aFormat, michael@0: const uint32_t& aUsage, michael@0: MaybeMagicGrallocBufferHandle* aOutHandle) michael@0: { michael@0: #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC michael@0: return GrallocBufferActor::Create(aSize, aFormat, aUsage, aOutHandle); michael@0: #else michael@0: NS_RUNTIMEABORT("No gralloc buffers for you"); michael@0: return nullptr; michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::DeallocPGrallocBufferParent(PGrallocBufferParent* actor) michael@0: { michael@0: #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC michael@0: delete actor; michael@0: return true; michael@0: #else michael@0: NS_RUNTIMEABORT("Um, how did we get here?"); michael@0: return false; michael@0: #endif michael@0: } michael@0: michael@0: PLayerParent* michael@0: LayerTransactionParent::AllocPLayerParent() michael@0: { michael@0: return new ShadowLayerParent(); michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::DeallocPLayerParent(PLayerParent* actor) michael@0: { michael@0: delete actor; michael@0: return true; michael@0: } michael@0: michael@0: PCompositableParent* michael@0: LayerTransactionParent::AllocPCompositableParent(const TextureInfo& aInfo) michael@0: { michael@0: return CompositableHost::CreateIPDLActor(this, aInfo, 0); michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* aActor) michael@0: { michael@0: return CompositableHost::DestroyIPDLActor(aActor); michael@0: } michael@0: michael@0: PTextureParent* michael@0: LayerTransactionParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData, michael@0: const TextureFlags& aFlags) michael@0: { michael@0: return TextureHost::CreateIPDLActor(this, aSharedData, aFlags); michael@0: } michael@0: michael@0: bool michael@0: LayerTransactionParent::DeallocPTextureParent(PTextureParent* actor) michael@0: { michael@0: return TextureHost::DestroyIPDLActor(actor); michael@0: } michael@0: michael@0: bool LayerTransactionParent::IsSameProcess() const michael@0: { michael@0: return OtherProcess() == ipc::kInvalidProcessHandle; michael@0: } michael@0: michael@0: } // namespace layers michael@0: } // namespace mozilla