1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
/* -*- 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<NativeLayer> NativeLayerRootRemoteMacChild::CreateLayer(
const gfx::IntSize& aSize, bool aIsOpaque,
SurfacePoolHandle* aSurfacePoolHandle) {
RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac(
aSize, aIsOpaque, aSurfacePoolHandle->AsSurfacePoolHandleCA());
mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayer(
reinterpret_cast<uint64_t>(layer.get()), aSize, aIsOpaque));
// Share our command queue.
layer->mCommandQueue = mCommandQueue;
return layer.forget();
}
already_AddRefed<NativeLayer>
NativeLayerRootRemoteMacChild::CreateLayerForExternalTexture(bool aIsOpaque) {
RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac(aIsOpaque);
mCommandQueue->AppendCommand(
mozilla::layers::CommandCreateLayerForExternalTexture(
reinterpret_cast<uint64_t>(layer.get()), aIsOpaque));
// Share our command queue.
layer->mCommandQueue = mCommandQueue;
return layer.forget();
}
already_AddRefed<NativeLayer>
NativeLayerRootRemoteMacChild::CreateLayerForColor(gfx::DeviceColor aColor) {
RefPtr<NativeLayerRemoteMac> layer = new NativeLayerRemoteMac(aColor);
mCommandQueue->AppendCommand(mozilla::layers::CommandCreateLayerForColor(
reinterpret_cast<uint64_t>(layer.get()), aColor));
// Share our command queue.
layer->mCommandQueue = mCommandQueue;
return layer.forget();
}
void NativeLayerRootRemoteMacChild::AppendLayer(NativeLayer* aLayer) {}
void NativeLayerRootRemoteMacChild::RemoveLayer(NativeLayer* aLayer) {}
void NativeLayerRootRemoteMacChild::SetLayers(
const nsTArray<RefPtr<NativeLayer>>& aLayers) {
// We don't create a command for this, because we don't care
// about the layers until CommitToScreen().
nsTArray<RefPtr<NativeLayerRemoteMac>> layers(aLayers.Length());
for (const auto& layer : aLayers) {
RefPtr<NativeLayerRemoteMac> 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<NativeLayerRootSnapshotter>
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<SnapshotterDelegate>(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<uint64_t> setLayerIDs;
for (const auto& layer : mNativeLayers) {
auto ID = reinterpret_cast<uint64_t>(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<NativeLayerCommand> 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<CALayer*>* 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<uint8_t>& 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<uint8_t>();
MOZ_RELEASE_ASSERT(aBuffer.length() >= byteCount);
PodCopy(aBuffer.begin().get(), pixels.get<uint8_t>(), byteCount);
return true;
}
NativeLayerRootRemoteMacChild::NativeLayerRootRemoteMacChild()
: mRemoteChild(MakeRefPtr<NativeLayerRemoteChild>()),
mCommandQueue(MakeRefPtr<NativeLayerCommandQueue>()) {}
NativeLayerRootRemoteMacChild::~NativeLayerRootRemoteMacChild() {}
NativeLayerRootRemoteMacChild::SnapshotterDelegate::SnapshotterDelegate(
NativeLayerRootRemoteMacChild* aLayerRoot)
: mLayerRoot(aLayerRoot) {}
NativeLayerRootRemoteMacChild::SnapshotterDelegate::~SnapshotterDelegate() =
default;
} // namespace layers
} // namespace mozilla
|