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 "CompositableTransactionParent.h" michael@0: #include "CompositableHost.h" // for CompositableParent, etc michael@0: #include "CompositorParent.h" // for CompositorParent michael@0: #include "GLContext.h" // for GLContext michael@0: #include "Layers.h" // for Layer michael@0: #include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc michael@0: #include "TiledLayerBuffer.h" // for TiledLayerComposer michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/RefPtr.h" // for RefPtr michael@0: #include "mozilla/layers/CompositorTypes.h" michael@0: #include "mozilla/layers/ContentHost.h" // for ContentHostBase michael@0: #include "mozilla/layers/LayerManagerComposite.h" michael@0: #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor michael@0: #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG michael@0: #include "mozilla/layers/TextureHost.h" // for TextureHost michael@0: #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL michael@0: #include "mozilla/layers/ThebesLayerComposite.h" michael@0: #include "mozilla/mozalloc.h" // for operator delete michael@0: #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION michael@0: #include "nsRegion.h" // for nsIntRegion michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: class ClientTiledLayerBuffer; michael@0: class Compositor; michael@0: michael@0: template michael@0: CompositableHost* AsCompositable(const Op& op) michael@0: { michael@0: return CompositableHost::FromIPDLActor(op.compositableParent()); michael@0: } michael@0: michael@0: // This function can in some cases fail and return false without it being a bug. michael@0: // This can theoretically happen if the ImageBridge sends frames before michael@0: // we created the layer tree. Since we can't enforce that the layer michael@0: // tree is already created before ImageBridge operates, there isn't much michael@0: // we can do about it, but in practice it is very rare. michael@0: // Typically when a tab with a video is dragged from a window to another, michael@0: // there can be a short time when the video is still sending frames michael@0: // asynchonously while the layer tree is not reconstructed. It's not a michael@0: // big deal. michael@0: // Note that Layers transactions do not need to call this because they always michael@0: // schedule the composition, in LayerManagerComposite::EndTransaction. michael@0: template michael@0: bool ScheduleComposition(const T& op) michael@0: { michael@0: CompositableHost* comp = AsCompositable(op); michael@0: uint64_t id = comp->GetCompositorID(); michael@0: if (!comp || !id) { michael@0: return false; michael@0: } michael@0: CompositorParent* cp = CompositorParent::GetCompositor(id); michael@0: if (!cp) { michael@0: return false; michael@0: } michael@0: cp->ScheduleComposition(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, michael@0: EditReplyVector& replyv) michael@0: { michael@0: switch (aEdit.type()) { michael@0: case CompositableOperation::TOpCreatedIncrementalTexture: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] Created texture")); michael@0: const OpCreatedIncrementalTexture& op = aEdit.get_OpCreatedIncrementalTexture(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: michael@0: bool success = michael@0: compositable->CreatedIncrementalTexture(this, michael@0: op.textureInfo(), michael@0: op.bufferRect()); michael@0: if (!success) { michael@0: return false; michael@0: } michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpPaintTextureRegion: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); michael@0: michael@0: const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: Layer* layer = compositable->GetLayer(); michael@0: if (!layer || layer->GetType() != Layer::TYPE_THEBES) { michael@0: return false; michael@0: } michael@0: ThebesLayerComposite* thebes = static_cast(layer); michael@0: michael@0: const ThebesBufferData& bufferData = op.bufferData(); michael@0: michael@0: RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds()); michael@0: michael@0: nsIntRegion frontUpdatedRegion; michael@0: if (!compositable->UpdateThebes(bufferData, michael@0: op.updatedRegion(), michael@0: thebes->GetValidRegion(), michael@0: &frontUpdatedRegion)) michael@0: { michael@0: return false; michael@0: } michael@0: replyv.push_back( michael@0: OpContentBufferSwap(op.compositableParent(), nullptr, frontUpdatedRegion)); michael@0: michael@0: RenderTraceInvalidateEnd(thebes, "FF00FF"); michael@0: // return texure data to client if necessary michael@0: ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpPaintTextureIncremental: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] Paint ThebesLayer")); michael@0: michael@0: const OpPaintTextureIncremental& op = aEdit.get_OpPaintTextureIncremental(); michael@0: michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: michael@0: SurfaceDescriptor desc = op.image(); michael@0: michael@0: compositable->UpdateIncremental(op.textureId(), michael@0: desc, michael@0: op.updatedRegion(), michael@0: op.bufferRect(), michael@0: op.bufferRotation()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpUpdatePictureRect: { michael@0: const OpUpdatePictureRect& op = aEdit.get_OpUpdatePictureRect(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: MOZ_ASSERT(compositable); michael@0: compositable->SetPictureRect(op.picture()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpUseTiledLayerBuffer: { michael@0: MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); michael@0: const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: michael@0: TiledLayerComposer* tileComposer = compositable->AsTiledLayerComposer(); michael@0: NS_ASSERTION(tileComposer, "compositable is not a tile composer"); michael@0: michael@0: const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor(); michael@0: tileComposer->UseTiledLayerBuffer(this, tileDesc); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpRemoveTexture: { michael@0: const OpRemoveTexture& op = aEdit.get_OpRemoveTexture(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: RefPtr tex = TextureHost::AsTextureHost(op.textureParent()); michael@0: michael@0: MOZ_ASSERT(tex.get()); michael@0: compositable->RemoveTextureHost(tex); michael@0: // return texure data to client if necessary michael@0: ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpUseTexture: { michael@0: const OpUseTexture& op = aEdit.get_OpUseTexture(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: RefPtr tex = TextureHost::AsTextureHost(op.textureParent()); michael@0: michael@0: MOZ_ASSERT(tex.get()); michael@0: compositable->UseTextureHost(tex); michael@0: michael@0: if (IsAsync()) { michael@0: ScheduleComposition(op); michael@0: // Async layer updates don't trigger invalidation, manually tell the layer michael@0: // that its content have changed. michael@0: if (compositable->GetLayer()) { michael@0: compositable->GetLayer()->SetInvalidRectToVisibleRegion(); michael@0: } michael@0: } michael@0: // return texure data to client if necessary michael@0: ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpUseComponentAlphaTextures: { michael@0: const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures(); michael@0: CompositableHost* compositable = AsCompositable(op); michael@0: RefPtr texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent()); michael@0: RefPtr texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent()); michael@0: michael@0: MOZ_ASSERT(texOnBlack && texOnWhite); michael@0: compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); michael@0: michael@0: if (IsAsync()) { michael@0: ScheduleComposition(op); michael@0: } michael@0: // return texure data to client if necessary michael@0: ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent()); michael@0: break; michael@0: } michael@0: case CompositableOperation::TOpUpdateTexture: { michael@0: const OpUpdateTexture& op = aEdit.get_OpUpdateTexture(); michael@0: RefPtr texture = TextureHost::AsTextureHost(op.textureParent()); michael@0: MOZ_ASSERT(texture); michael@0: michael@0: texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion michael@0: ? &op.region().get_nsIntRegion() michael@0: : nullptr); // no region means invalidate the entire surface michael@0: break; michael@0: } michael@0: michael@0: default: { michael@0: MOZ_ASSERT(false, "bad type"); michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 michael@0: void michael@0: CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, michael@0: EditReplyVector& replyv, michael@0: PCompositableParent* aParent) michael@0: { michael@0: if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { michael@0: return; michael@0: } michael@0: michael@0: const std::vector< RefPtr > textureList = michael@0: aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList(); michael@0: // Return pending Texture data michael@0: for (size_t i = 0; i < textureList.size(); i++) { michael@0: // File descriptor number is limited to 4 per IPC message. michael@0: // See Bug 986253 michael@0: if (mPrevFenceHandles.size() >= 4) { michael@0: break; michael@0: } michael@0: TextureHostOGL* hostOGL = textureList[i]->AsHostOGL(); michael@0: PTextureParent* actor = textureList[i]->GetIPDLActor(); michael@0: if (!hostOGL || !actor) { michael@0: continue; michael@0: } michael@0: android::sp fence = hostOGL->GetAndResetReleaseFence(); michael@0: if (fence.get() && fence->isValid()) { michael@0: FenceHandle handle = FenceHandle(fence); michael@0: replyv.push_back(ReturnReleaseFence(aParent, nullptr, actor, nullptr, handle)); michael@0: // Hold fence handle to prevent fence's file descriptor is closed before IPC happens. michael@0: mPrevFenceHandles.push_back(handle); michael@0: } michael@0: } michael@0: aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); michael@0: } michael@0: #else michael@0: void michael@0: CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable, michael@0: EditReplyVector& replyv, michael@0: PCompositableParent* aParent) michael@0: { michael@0: if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) { michael@0: return; michael@0: } michael@0: aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList(); michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: CompositableParentManager::ClearPrevFenceHandles() michael@0: { michael@0: mPrevFenceHandles.clear(); michael@0: } michael@0: michael@0: } // namespace michael@0: } // namespace michael@0: