NativeLayerRootRemoteMacChild.mm (7173B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "mozilla/layers/NativeLayerRemoteMac.h" 7 #include "mozilla/layers/NativeLayerRootRemoteMacChild.h" 8 #include "mozilla/layers/SurfacePool.h" 9 10 namespace mozilla { 11 namespace layers { 12 13 already_AddRefed<NativeLayer> NativeLayerRootRemoteMacChild::CreateLayer( 14 const gfx::IntSize& aSize, bool aIsOpaque, 15 SurfacePoolHandle* aSurfacePoolHandle) { 16 RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac( 17 aSize, aIsOpaque, aSurfacePoolHandle->AsSurfacePoolHandleCA()); 18 mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayer( 19 reinterpret_cast<uint64_t>(layer.get()), aSize, aIsOpaque)); 20 // Share our command queue. 21 layer->mCommandQueue = mCommandQueue; 22 return layer.forget(); 23 } 24 25 already_AddRefed<NativeLayer> 26 NativeLayerRootRemoteMacChild::CreateLayerForExternalTexture(bool aIsOpaque) { 27 RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac(aIsOpaque); 28 mCommandQueue->AppendCommand( 29 mozilla::layers::CommandCreateLayerForExternalTexture( 30 reinterpret_cast<uint64_t>(layer.get()), aIsOpaque)); 31 // Share our command queue. 32 layer->mCommandQueue = mCommandQueue; 33 return layer.forget(); 34 } 35 36 already_AddRefed<NativeLayer> 37 NativeLayerRootRemoteMacChild::CreateLayerForColor(gfx::DeviceColor aColor) { 38 RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac(aColor); 39 mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayerForColor( 40 reinterpret_cast<uint64_t>(layer.get()), aColor)); 41 // Share our command queue. 42 layer->mCommandQueue = mCommandQueue; 43 return layer.forget(); 44 } 45 46 void NativeLayerRootRemoteMacChild::AppendLayer(NativeLayer* aLayer) {} 47 48 void NativeLayerRootRemoteMacChild::RemoveLayer(NativeLayer* aLayer) {} 49 50 void NativeLayerRootRemoteMacChild::SetLayers( 51 const nsTArray<RefPtr<NativeLayer>>& aLayers) { 52 // We don't create a command for this, because we don't care 53 // about the layers until CommitToScreen(). 54 nsTArray<RefPtr<NativeLayerRemoteMac>> layers(aLayers.Length()); 55 for (const auto& layer : aLayers) { 56 RefPtr<NativeLayerRemoteMac> layerRemoteMac = 57 layer->AsNativeLayerRemoteMac(); 58 MOZ_ASSERT(layerRemoteMac); 59 layers.AppendElement(std::move(layerRemoteMac)); 60 } 61 62 if (mNativeLayers == layers) { 63 // A no-op. 64 return; 65 } 66 67 mNativeLayersChanged = true; 68 mNativeLayersChangedForSnapshot = true; 69 mNativeLayers.Clear(); 70 mNativeLayers.AppendElements(layers); 71 } 72 73 UniquePtr<NativeLayerRootSnapshotter> 74 NativeLayerRootRemoteMacChild::CreateSnapshotter() { 75 #ifdef XP_MACOSX 76 MOZ_RELEASE_ASSERT(!mWeakSnapshotter, 77 "No NativeLayerRootSnapshotter for this NativeLayerRoot " 78 "should exist when this is called"); 79 auto cr = NativeLayerRootSnapshotterCA::Create( 80 MakeUnique<SnapshotterDelegate>(this)); 81 if (cr) { 82 mWeakSnapshotter = cr.get(); 83 } 84 return cr; 85 #else 86 return nullptr; 87 #endif 88 } 89 90 void NativeLayerRootRemoteMacChild::OnNativeLayerRootSnapshotterDestroyed( 91 NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter) { 92 MOZ_RELEASE_ASSERT(mWeakSnapshotter == aNativeLayerRootSnapshotter); 93 mWeakSnapshotter = nullptr; 94 } 95 96 void NativeLayerRootRemoteMacChild::PrepareForCommit() { 97 // Intentionally ignored. 98 } 99 100 bool NativeLayerRootRemoteMacChild::CommitToScreen() { 101 // Prepare and send all commands to the parent actor. 102 103 // Our shared command queue has all of our CreateLayer and LayerDestroyed 104 // commands. That's good, because the commands that we're adding to the 105 // queue rely upon those CreateLayer commands appearing first. 106 107 // Iterate our layers to get the LayerInfo and ChangedSurface commands 108 // into our shared command queue. 109 for (const auto& layer : mNativeLayers) { 110 layer->FlushDirtyLayerInfoToCommandQueue(); 111 } 112 113 if (mNativeLayersChanged) { 114 // If mNativeLayersChanged is set, we will send a SetLayers 115 // command of this array filled with the IDs of everything 116 // in mNativeLayers. 117 nsTArray<uint64_t> setLayerIDs; 118 for (const auto& layer : mNativeLayers) { 119 auto ID = reinterpret_cast<uint64_t>(layer.get()); 120 setLayerIDs.AppendElement(ID); 121 } 122 mCommandQueue->AppendCommand( 123 mozilla::layers::CommandSetLayers(setLayerIDs)); 124 mNativeLayersChanged = false; 125 } 126 127 // Now flush the shared command queue to our local command array, 128 // which is suitable for sending to the parent process. 129 nsTArray<NativeLayerCommand> commands; 130 mCommandQueue->FlushToArray(commands); 131 132 if (!commands.IsEmpty()) { 133 // Send all the queued commands, including the ones we just added. 134 MOZ_ASSERT(mRemoteChild); 135 mRemoteChild->SendCommitNativeLayerCommands(std::move(commands)); 136 } 137 return true; 138 } 139 140 void NativeLayerRootRemoteMacChild::WaitUntilCommitToScreenHasBeenProcessed() { 141 mRemoteChild->SendFlush(); 142 } 143 144 void NativeLayerRootRemoteMacChild::CommitForSnapshot(CALayer* aRootCALayer) { 145 [CATransaction begin]; 146 [CATransaction setDisableActions:YES]; // disable cross-fade 147 148 NSMutableArray<CALayer*>* sublayers = 149 [NSMutableArray arrayWithCapacity:mNativeLayers.Length()]; 150 for (const auto& layer : mNativeLayers) { 151 layer->UpdateSnapshotLayer(); 152 if (CALayer* caLayer = layer->CALayerForSnapshot()) { 153 [sublayers addObject:caLayer]; 154 } 155 } 156 157 aRootCALayer.sublayers = sublayers; 158 [CATransaction commit]; 159 160 mNativeLayersChangedForSnapshot = false; 161 } 162 163 bool NativeLayerRootRemoteMacChild::ReadbackPixelsFromParent( 164 const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat, 165 const Range<uint8_t>& aBuffer) { 166 // In this process we only have the pixels of the individual layers, 167 // but here we're asked to return the result of compositing all the 168 // layers together. Computing the composited result is currently 169 // only implemented in NativeLayerRootCA, which runs in the parent 170 // process, so we send a sync IPC message to the parent to ask for 171 // the composited result. 172 if (aFormat != gfx::SurfaceFormat::B8G8R8A8) { 173 return false; 174 } 175 176 ipc::Shmem pixels; 177 if (!mRemoteChild->SendRequestReadback(aSize, &pixels)) { 178 return false; 179 } 180 181 // Copy pixels into aBuffer. 182 // TODO: Figure out a more idiomatic way to do this. 183 auto byteCount = pixels.Size<uint8_t>(); 184 MOZ_RELEASE_ASSERT(aBuffer.length() >= byteCount); 185 PodCopy(aBuffer.begin().get(), pixels.get<uint8_t>(), byteCount); 186 187 return true; 188 } 189 190 NativeLayerRootRemoteMacChild::NativeLayerRootRemoteMacChild() 191 : mRemoteChild(MakeRefPtr<NativeLayerRemoteChild>()), 192 mCommandQueue(MakeRefPtr<NativeLayerCommandQueue>()) {} 193 194 NativeLayerRootRemoteMacChild::~NativeLayerRootRemoteMacChild() {} 195 196 NativeLayerRootRemoteMacChild::SnapshotterDelegate::SnapshotterDelegate( 197 NativeLayerRootRemoteMacChild* aLayerRoot) 198 : mLayerRoot(aLayerRoot) {} 199 NativeLayerRootRemoteMacChild::SnapshotterDelegate::~SnapshotterDelegate() = 200 default; 201 202 } // namespace layers 203 } // namespace mozilla