summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/CompositableTransactionParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/CompositableTransactionParent.cpp')
-rw-r--r--gfx/layers/ipc/CompositableTransactionParent.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/gfx/layers/ipc/CompositableTransactionParent.cpp b/gfx/layers/ipc/CompositableTransactionParent.cpp
new file mode 100644
index 000000000..135011101
--- /dev/null
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -0,0 +1,245 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CompositableTransactionParent.h"
+#include "CompositableHost.h" // for CompositableParent, etc
+#include "CompositorBridgeParent.h" // for CompositorBridgeParent
+#include "GLContext.h" // for GLContext
+#include "Layers.h" // for Layer
+#include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc
+#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
+#include "mozilla/RefPtr.h" // for RefPtr
+#include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/layers/ContentHost.h" // for ContentHostBase
+#include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
+#include "mozilla/layers/LayerManagerComposite.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
+#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
+#include "mozilla/layers/TextureHost.h" // for TextureHost
+#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
+#include "mozilla/layers/TiledContentHost.h"
+#include "mozilla/layers/PaintedLayerComposite.h"
+#include "mozilla/mozalloc.h" // for operator delete
+#include "mozilla/Unused.h"
+#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
+#include "nsRegion.h" // for nsIntRegion
+
+namespace mozilla {
+namespace layers {
+
+class ClientTiledLayerBuffer;
+class Compositor;
+
+// This function can in some cases fail and return false without it being a bug.
+// This can theoretically happen if the ImageBridge sends frames before
+// we created the layer tree. Since we can't enforce that the layer
+// tree is already created before ImageBridge operates, there isn't much
+// we can do about it, but in practice it is very rare.
+// Typically when a tab with a video is dragged from a window to another,
+// there can be a short time when the video is still sending frames
+// asynchonously while the layer tree is not reconstructed. It's not a
+// big deal.
+// Note that Layers transactions do not need to call this because they always
+// schedule the composition, in LayerManagerComposite::EndTransaction.
+static bool
+ScheduleComposition(CompositableHost* aCompositable)
+{
+ uint64_t id = aCompositable->GetCompositorID();
+ if (!id) {
+ return false;
+ }
+ CompositorBridgeParent* cp = CompositorBridgeParent::GetCompositorBridgeParent(id);
+ if (!cp) {
+ return false;
+ }
+ cp->ScheduleComposition();
+ return true;
+}
+
+bool
+CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit,
+ EditReplyVector& replyv)
+{
+ // Ignore all operations on compositables created on stale compositors. We
+ // return true because the child is unable to handle errors.
+ CompositableHost* compositable = CompositableHost::FromIPDLActor(aEdit.compositableParent());
+ if (compositable->GetCompositor() && !compositable->GetCompositor()->IsValid()) {
+ return true;
+ }
+
+ switch (aEdit.detail().type()) {
+ case CompositableOperationDetail::TOpPaintTextureRegion: {
+ MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
+
+ const OpPaintTextureRegion& op = aEdit.detail().get_OpPaintTextureRegion();
+ Layer* layer = compositable->GetLayer();
+ if (!layer || layer->GetType() != Layer::TYPE_PAINTED) {
+ return false;
+ }
+ PaintedLayerComposite* thebes = static_cast<PaintedLayerComposite*>(layer);
+
+ const ThebesBufferData& bufferData = op.bufferData();
+
+ RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds());
+
+ nsIntRegion frontUpdatedRegion;
+ if (!compositable->UpdateThebes(bufferData,
+ op.updatedRegion(),
+ thebes->GetValidRegion(),
+ &frontUpdatedRegion))
+ {
+ return false;
+ }
+ replyv.push_back(
+ OpContentBufferSwap(aEdit.compositableParent(), nullptr, frontUpdatedRegion));
+
+ RenderTraceInvalidateEnd(thebes, "FF00FF");
+ break;
+ }
+ case CompositableOperationDetail::TOpUseTiledLayerBuffer: {
+ MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
+ const OpUseTiledLayerBuffer& op = aEdit.detail().get_OpUseTiledLayerBuffer();
+ TiledContentHost* tiledHost = compositable->AsTiledContentHost();
+
+ NS_ASSERTION(tiledHost, "The compositable is not tiled");
+
+ const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
+
+ bool success = tiledHost->UseTiledLayerBuffer(this, tileDesc);
+
+ const InfallibleTArray<TileDescriptor>& tileDescriptors = tileDesc.tiles();
+ for (size_t i = 0; i < tileDescriptors.Length(); i++) {
+ const TileDescriptor& tileDesc = tileDescriptors[i];
+ if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
+ continue;
+ }
+ const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
+ RefPtr<TextureHost> texture = TextureHost::AsTextureHost(texturedDesc.textureParent());
+ if (texture) {
+ texture->SetLastFwdTransactionId(mFwdTransactionId);
+ // Make sure that each texture was handled by the compositable
+ // because the recycling logic depends on it.
+ MOZ_ASSERT(texture->NumCompositableRefs() > 0);
+ }
+ if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
+ texture = TextureHost::AsTextureHost(texturedDesc.textureOnWhite().get_PTextureParent());
+ if (texture) {
+ texture->SetLastFwdTransactionId(mFwdTransactionId);
+ // Make sure that each texture was handled by the compositable
+ // because the recycling logic depends on it.
+ MOZ_ASSERT(texture->NumCompositableRefs() > 0);
+ }
+ }
+ }
+ if (!success) {
+ return false;
+ }
+ break;
+ }
+ case CompositableOperationDetail::TOpRemoveTexture: {
+ const OpRemoveTexture& op = aEdit.detail().get_OpRemoveTexture();
+
+ RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
+
+ MOZ_ASSERT(tex.get());
+ compositable->RemoveTextureHost(tex);
+ break;
+ }
+ case CompositableOperationDetail::TOpUseTexture: {
+ const OpUseTexture& op = aEdit.detail().get_OpUseTexture();
+
+ AutoTArray<CompositableHost::TimedTexture,4> textures;
+ for (auto& timedTexture : op.textures()) {
+ CompositableHost::TimedTexture* t = textures.AppendElement();
+ t->mTexture =
+ TextureHost::AsTextureHost(timedTexture.textureParent());
+ MOZ_ASSERT(t->mTexture);
+ t->mTimeStamp = timedTexture.timeStamp();
+ t->mPictureRect = timedTexture.picture();
+ t->mFrameID = timedTexture.frameID();
+ t->mProducerID = timedTexture.producerID();
+ t->mTexture->DeserializeReadLock(timedTexture.sharedLock(), this);
+ }
+ if (textures.Length() > 0) {
+ compositable->UseTextureHost(textures);
+
+ for (auto& timedTexture : op.textures()) {
+ RefPtr<TextureHost> texture = TextureHost::AsTextureHost(timedTexture.textureParent());
+ if (texture) {
+ texture->SetLastFwdTransactionId(mFwdTransactionId);
+ // Make sure that each texture was handled by the compositable
+ // because the recycling logic depends on it.
+ MOZ_ASSERT(texture->NumCompositableRefs() > 0);
+ }
+ }
+ }
+
+ if (UsesImageBridge() && compositable->GetLayer()) {
+ ScheduleComposition(compositable);
+ }
+ break;
+ }
+ case CompositableOperationDetail::TOpUseComponentAlphaTextures: {
+ const OpUseComponentAlphaTextures& op = aEdit.detail().get_OpUseComponentAlphaTextures();
+ RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
+ RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
+ texOnBlack->DeserializeReadLock(op.sharedLockBlack(), this);
+ texOnWhite->DeserializeReadLock(op.sharedLockWhite(), this);
+
+ MOZ_ASSERT(texOnBlack && texOnWhite);
+ compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
+
+ if (texOnBlack) {
+ texOnBlack->SetLastFwdTransactionId(mFwdTransactionId);
+ // Make sure that each texture was handled by the compositable
+ // because the recycling logic depends on it.
+ MOZ_ASSERT(texOnBlack->NumCompositableRefs() > 0);
+ }
+
+ if (texOnWhite) {
+ texOnWhite->SetLastFwdTransactionId(mFwdTransactionId);
+ // Make sure that each texture was handled by the compositable
+ // because the recycling logic depends on it.
+ MOZ_ASSERT(texOnWhite->NumCompositableRefs() > 0);
+ }
+
+ if (UsesImageBridge()) {
+ ScheduleComposition(compositable);
+ }
+ break;
+ }
+ default: {
+ MOZ_ASSERT(false, "bad type");
+ }
+ }
+
+ return true;
+}
+
+void
+CompositableParentManager::DestroyActor(const OpDestroy& aOp)
+{
+ switch (aOp.type()) {
+ case OpDestroy::TPTextureParent: {
+ auto actor = aOp.get_PTextureParent();
+ TextureHost::ReceivedDestroy(actor);
+ break;
+ }
+ case OpDestroy::TPCompositableParent: {
+ auto actor = aOp.get_PCompositableParent();
+ CompositableHost::ReceivedDestroy(actor);
+ break;
+ }
+ default: {
+ MOZ_ASSERT(false, "unsupported type");
+ }
+ }
+}
+
+} // namespace layers
+} // namespace mozilla
+