/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- * 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 "mozilla/layers/NativeLayerRemoteMac.h" #include "mozilla/layers/NativeLayerRootRemoteMacChild.h" #include "mozilla/layers/SurfacePool.h" namespace mozilla { namespace layers { already_AddRefed NativeLayerRootRemoteMacChild::CreateLayer( const gfx::IntSize& aSize, bool aIsOpaque, SurfacePoolHandle* aSurfacePoolHandle) { RefPtr layer = new NativeLayerRemoteMac( aSize, aIsOpaque, aSurfacePoolHandle->AsSurfacePoolHandleCA()); mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayer( reinterpret_cast(layer.get()), aSize, aIsOpaque)); // Share our command queue. layer->mCommandQueue = mCommandQueue; return layer.forget(); } already_AddRefed NativeLayerRootRemoteMacChild::CreateLayerForExternalTexture(bool aIsOpaque) { RefPtr layer = new NativeLayerRemoteMac(aIsOpaque); mCommandQueue->AppendCommand( mozilla::layers::CommandCreateLayerForExternalTexture( reinterpret_cast(layer.get()), aIsOpaque)); // Share our command queue. layer->mCommandQueue = mCommandQueue; return layer.forget(); } already_AddRefed NativeLayerRootRemoteMacChild::CreateLayerForColor(gfx::DeviceColor aColor) { RefPtr layer = new NativeLayerRemoteMac(aColor); mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayerForColor( reinterpret_cast(layer.get()), aColor)); // Share our command queue. layer->mCommandQueue = mCommandQueue; return layer.forget(); } void NativeLayerRootRemoteMacChild::AppendLayer(NativeLayer* aLayer) { RefPtr layerRemoteMac = aLayer->AsNativeLayerRemoteMac(); mNativeLayers.AppendElement(std::move(layerRemoteMac)); mNativeLayersChanged = true; mNativeLayersChangedForSnapshot = true; } void NativeLayerRootRemoteMacChild::RemoveLayer(NativeLayer* aLayer) { if (mNativeLayers.RemoveElement(aLayer)) { mNativeLayersChanged = true; mNativeLayersChangedForSnapshot = true; } } void NativeLayerRootRemoteMacChild::SetLayers( const nsTArray>& aLayers) { // We don't create a command for this, because we don't care // about the layers until CommitToScreen(). nsTArray> layers(aLayers.Length()); for (const auto& layer : aLayers) { RefPtr layerRemoteMac = layer->AsNativeLayerRemoteMac(); MOZ_ASSERT(layerRemoteMac); layers.AppendElement(std::move(layerRemoteMac)); } if (mNativeLayers == layers) { // A no-op. return; } mNativeLayersChanged = true; mNativeLayersChangedForSnapshot = true; mNativeLayers.Clear(); mNativeLayers.AppendElements(layers); } UniquePtr NativeLayerRootRemoteMacChild::CreateSnapshotter() { #ifdef XP_MACOSX MOZ_RELEASE_ASSERT(!mWeakSnapshotter, "No NativeLayerRootSnapshotter for this NativeLayerRoot " "should exist when this is called"); auto cr = NativeLayerRootSnapshotterCA::Create( MakeUnique(this)); if (cr) { mWeakSnapshotter = cr.get(); } return cr; #else return nullptr; #endif } void NativeLayerRootRemoteMacChild::OnNativeLayerRootSnapshotterDestroyed( NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter) { MOZ_RELEASE_ASSERT(mWeakSnapshotter == aNativeLayerRootSnapshotter); mWeakSnapshotter = nullptr; } void NativeLayerRootRemoteMacChild::PrepareForCommit() { // Intentionally ignored. } bool NativeLayerRootRemoteMacChild::CommitToScreen() { // Prepare and send all commands to the parent actor. // Our shared command queue has all of our CreateLayer and LayerDestroyed // commands. That's good, because the commands that we're adding to the // queue rely upon those CreateLayer commands appearing first. // Iterate our layers to get the LayerInfo and ChangedSurface commands // into our shared command queue. for (const auto& layer : mNativeLayers) { layer->FlushDirtyLayerInfoToCommandQueue(); } if (mNativeLayersChanged) { // If mNativeLayersChanged is set, we will send a SetLayers // command of this array filled with the IDs of everything // in mNativeLayers. nsTArray setLayerIDs; for (const auto& layer : mNativeLayers) { auto ID = reinterpret_cast(layer.get()); setLayerIDs.AppendElement(ID); } mCommandQueue->AppendCommand( mozilla::layers::CommandSetLayers(setLayerIDs)); mNativeLayersChanged = false; } // Now flush the shared command queue to our local command array, // which is suitable for sending to the parent process. nsTArray commands; mCommandQueue->FlushToArray(commands); if (!commands.IsEmpty()) { // Send all the queued commands, including the ones we just added. MOZ_ASSERT(mRemoteChild); mRemoteChild->SendCommitNativeLayerCommands(std::move(commands)); } return true; } void NativeLayerRootRemoteMacChild::WaitUntilCommitToScreenHasBeenProcessed() { mRemoteChild->SendFlush(); } void NativeLayerRootRemoteMacChild::CommitForSnapshot(CALayer* aRootCALayer) { [CATransaction begin]; [CATransaction setDisableActions:YES]; // disable cross-fade NSMutableArray* sublayers = [NSMutableArray arrayWithCapacity:mNativeLayers.Length()]; for (const auto& layer : mNativeLayers) { layer->UpdateSnapshotLayer(); if (CALayer* caLayer = layer->CALayerForSnapshot()) { [sublayers addObject:caLayer]; } } aRootCALayer.sublayers = sublayers; [CATransaction commit]; mNativeLayersChangedForSnapshot = false; } bool NativeLayerRootRemoteMacChild::ReadbackPixelsFromParent( const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat, const Range& aBuffer) { // In this process we only have the pixels of the individual layers, // but here we're asked to return the result of compositing all the // layers together. Computing the composited result is currently // only implemented in NativeLayerRootCA, which runs in the parent // process, so we send a sync IPC message to the parent to ask for // the composited result. if (aFormat != gfx::SurfaceFormat::B8G8R8A8) { return false; } ipc::Shmem pixels; if (!mRemoteChild->SendRequestReadback(aSize, &pixels)) { return false; } // Copy pixels into aBuffer. // TODO: Figure out a more idiomatic way to do this. auto byteCount = pixels.Size(); MOZ_RELEASE_ASSERT(aBuffer.length() >= byteCount); PodCopy(aBuffer.begin().get(), pixels.get(), byteCount); return true; } NativeLayerRootRemoteMacChild::NativeLayerRootRemoteMacChild() : mRemoteChild(MakeRefPtr()), mCommandQueue(MakeRefPtr()) {} NativeLayerRootRemoteMacChild::~NativeLayerRootRemoteMacChild() {} NativeLayerRootRemoteMacChild::SnapshotterDelegate::SnapshotterDelegate( NativeLayerRootRemoteMacChild* aLayerRoot) : mLayerRoot(aLayerRoot) {} NativeLayerRootRemoteMacChild::SnapshotterDelegate::~SnapshotterDelegate() = default; } // namespace layers } // namespace mozilla