void ParamTraits<FenceHandle>::Write(Message* aMsg, const paramType& aParam) { FenceHandle handle = aParam; MOZ_ASSERT(handle.IsValid()); #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 RefPtr<FenceHandle::FdObj> fence = handle.GetAndResetFdObj(); aMsg->WriteFileDescriptor(base::FileDescriptor(fence->GetAndResetFd(), true)); #endif }
bool TextureHost::SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle) { if (!aReleaseFenceHandle.IsValid()) { // HWC might not provide Fence. // In this case, HWC implicitly handles buffer's fence. return false; } mReleaseFenceHandle.Merge(aReleaseFenceHandle); return true; }
bool HwcComposer2D::Commit(nsScreenGonk* aScreen) { for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) { mList->hwLayers[j].acquireFenceFd = -1; if (mHwcLayerMap.IsEmpty() || (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER)) { continue; } LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); if (!state.mTexture) { continue; } FenceHandle fence = state.mTexture->GetAndResetAcquireFenceHandle(); if (fence.IsValid()) { RefPtr<FenceHandle::FdObj> fdObj = fence.GetAndResetFdObj(); mList->hwLayers[j].acquireFenceFd = fdObj->GetAndResetFd(); } } int err = mHal->Set(mList, aScreen->GetDisplayType()); mPrevRetireFence.TransferToAnotherFenceHandle(mPrevDisplayFence); for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) { if (mList->hwLayers[j].releaseFenceFd >= 0) { int fd = mList->hwLayers[j].releaseFenceFd; mList->hwLayers[j].releaseFenceFd = -1; RefPtr<FenceHandle::FdObj> fdObj = new FenceHandle::FdObj(fd); FenceHandle fence(fdObj); LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); if (!state.mTexture) { continue; } state.mTexture->SetReleaseFenceHandle(fence); } } if (mList->retireFenceFd >= 0) { mPrevRetireFence = FenceHandle(new FenceHandle::FdObj(mList->retireFenceFd)); } // Set DisplaySurface layer fence DisplaySurface* displaySurface = aScreen->GetDisplaySurface(); displaySurface->setReleaseFenceFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd); mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd = -1; mPrepared = false; return !err; }
void FenceHandle::Merge(const FenceHandle& aFenceHandle) { #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 if (!aFenceHandle.IsValid()) { return; } if (!IsValid()) { mFence = aFenceHandle.mFence; } else { int result = sync_merge("FenceHandle", mFence->mFd, aFenceHandle.mFence->mFd); if (result == -1) { mFence = aFenceHandle.mFence; } else { mFence = new FdObj(result); } } #endif }
/*static*/ void ImageBridgeParent::SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId, uint64_t aTransactionId, PTextureParent* aTexture) { RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture); if (!texture) { return; } FenceHandle fence = texture->GetAndResetReleaseFenceHandle(); if (!fence.IsValid()) { return; } RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence); HoldUntilComplete(tracker); InfallibleTArray<AsyncParentMessageData> messages; messages.AppendElement(OpDeliverFenceToTracker(tracker->GetId(), aDestHolderId, aTransactionId, fence)); mozilla::unused << SendParentAsyncMessages(messages); }
void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { if (mForwarder->GetSyncObject()) { mForwarder->GetSyncObject()->FinalizeFrame(); } mPhase = PHASE_FORWARD; mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(); TimeStamp transactionStart; if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) { transactionStart = mTransactionIdAllocator->GetTransactionStart(); } else { transactionStart = mTransactionStart; } // forward this transaction's changeset to our LayerManagerComposite bool sent; AutoInfallibleTArray<EditReply, 10> replies; if (mForwarder->EndTransaction(&replies, mRegionToClear, mLatestTransactionId, aScheduleComposite, mPaintSequenceNumber, mIsRepeatTransaction, transactionStart, &sent)) { for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) { const EditReply& reply = replies[i]; switch (reply.type()) { case EditReply::TOpContentBufferSwap: { MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap")); const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap(); CompositableClient* compositable = CompositableClient::FromIPDLActor(obs.compositableChild()); ContentClientRemote* contentClient = static_cast<ContentClientRemote*>(compositable); MOZ_ASSERT(contentClient); contentClient->SwapBuffers(obs.frontUpdatedRegion()); break; } case EditReply::TReturnReleaseFence: { const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence(); FenceHandle fence = rep.fence(); PTextureChild* child = rep.textureChild(); if (!fence.IsValid() || !child) { break; } RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child); if (texture) { texture->SetReleaseFenceHandle(fence); } break; } default: NS_RUNTIMEABORT("not reached"); } } if (sent) { mNeedsComposite = false; } } else if (HasShadowManager()) { NS_WARNING("failed to forward Layers transaction"); } if (!sent) { // Clear the transaction id so that it doesn't get returned // unless we forwarded to somewhere that doesn't actually // have a compositor. mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId); } mForwarder->RemoveTexturesIfNecessary(); mForwarder->SendPendingAsyncMessges(); mPhase = PHASE_NONE; // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() mKeepAlive.Clear(); }
bool CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit, EditReplyVector& replyv) { switch (aEdit.type()) { case CompositableOperation::TOpPaintTextureRegion: { MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer")); const OpPaintTextureRegion& op = aEdit.get_OpPaintTextureRegion(); CompositableHost* compositable = AsCompositable(op); 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(op.compositableParent(), nullptr, frontUpdatedRegion)); RenderTraceInvalidateEnd(thebes, "FF00FF"); break; } case CompositableOperation::TOpUseTiledLayerBuffer: { MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer")); const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer(); TiledContentHost* compositable = AsCompositable(op)->AsTiledContentHost(); NS_ASSERTION(compositable, "The compositable is not tiled"); const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor(); bool success = compositable->UseTiledLayerBuffer(this, tileDesc); if (!success) { return false; } break; } case CompositableOperation::TOpRemoveTexture: { const OpRemoveTexture& op = aEdit.get_OpRemoveTexture(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); MOZ_ASSERT(tex.get()); compositable->RemoveTextureHost(tex); // send FenceHandle if present. SendFenceHandleIfPresent(op.textureParent(), compositable); break; } case CompositableOperation::TOpRemoveTextureAsync: { const OpRemoveTextureAsync& op = aEdit.get_OpRemoveTextureAsync(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent()); MOZ_ASSERT(tex.get()); compositable->RemoveTextureHost(tex); if (!IsAsync() && ImageBridgeParent::GetInstance(GetChildProcessId())) { // send FenceHandle if present via ImageBridge. ImageBridgeParent::AppendDeliverFenceMessage( GetChildProcessId(), op.holderId(), op.transactionId(), op.textureParent(), compositable); // If the message is recievied via PLayerTransaction, // Send message back via PImageBridge. ImageBridgeParent::ReplyRemoveTexture( GetChildProcessId(), OpReplyRemoveTexture(op.holderId(), op.transactionId())); } else { // send FenceHandle if present. SendFenceHandleIfPresent(op.textureParent(), compositable); ReplyRemoveTexture(OpReplyRemoveTexture(op.holderId(), op.transactionId())); } break; } case CompositableOperation::TOpUseTexture: { const OpUseTexture& op = aEdit.get_OpUseTexture(); CompositableHost* compositable = AsCompositable(op); nsAutoTArray<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(); MOZ_ASSERT(ValidatePictureRect(t->mTexture->GetSize(), t->mPictureRect)); MaybeFence maybeFence = timedTexture.fence(); if (maybeFence.type() == MaybeFence::TFenceHandle) { FenceHandle fence = maybeFence.get_FenceHandle(); if (fence.IsValid()) { t->mTexture->SetAcquireFenceHandle(fence); } } } compositable->UseTextureHost(textures); if (IsAsync() && compositable->GetLayer()) { ScheduleComposition(op); } break; } case CompositableOperation::TOpUseComponentAlphaTextures: { const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures(); CompositableHost* compositable = AsCompositable(op); RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent()); RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent()); MOZ_ASSERT(texOnBlack && texOnWhite); compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite); if (IsAsync()) { ScheduleComposition(op); } break; } #ifdef MOZ_WIDGET_GONK case CompositableOperation::TOpUseOverlaySource: { const OpUseOverlaySource& op = aEdit.get_OpUseOverlaySource(); CompositableHost* compositable = AsCompositable(op); MOZ_ASSERT(compositable->GetType() == CompositableType::IMAGE_OVERLAY, "Invalid operation!"); if (!ValidatePictureRect(op.overlay().size(), op.picture())) { return false; } compositable->UseOverlaySource(op.overlay(), op.picture()); break; } #endif default: { MOZ_ASSERT(false, "bad type"); } } return true; }
void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) { mPhase = PHASE_FORWARD; // forward this transaction's changeset to our LayerManagerComposite bool sent; AutoInfallibleTArray<EditReply, 10> replies; if (HasShadowManager() && mForwarder->EndTransaction(&replies, mRegionToClear, aScheduleComposite, &sent)) { for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) { const EditReply& reply = replies[i]; switch (reply.type()) { case EditReply::TOpContentBufferSwap: { MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap")); const OpContentBufferSwap& obs = reply.get_OpContentBufferSwap(); CompositableClient* compositable = CompositableClient::FromIPDLActor(obs.compositableChild()); ContentClientRemote* contentClient = static_cast<ContentClientRemote*>(compositable); MOZ_ASSERT(contentClient); contentClient->SwapBuffers(obs.frontUpdatedRegion()); break; } case EditReply::TOpTextureSwap: { MOZ_LAYERS_LOG(("[LayersForwarder] TextureSwap")); const OpTextureSwap& ots = reply.get_OpTextureSwap(); CompositableClient* compositable = CompositableClient::FromIPDLActor(ots.compositableChild()); MOZ_ASSERT(compositable); compositable->SetDescriptorFromReply(ots.textureId(), ots.image()); break; } case EditReply::TReturnReleaseFence: { const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence(); FenceHandle fence = rep.fence(); PTextureChild* child = rep.textureChild(); if (!fence.IsValid() || !child) { break; } RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child); if (texture) { texture->SetReleaseFenceHandle(fence); } break; } default: NS_RUNTIMEABORT("not reached"); } } if (sent) { mNeedsComposite = false; } } else if (HasShadowManager()) { NS_WARNING("failed to forward Layers transaction"); } mForwarder->RemoveTexturesIfNecessary(); mForwarder->SendPendingAsyncMessge(); mPhase = PHASE_NONE; // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() mKeepAlive.Clear(); }