File: NativeLayerRootRemoteMacChild.mm

package info (click to toggle)
firefox 147.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,484 kB
  • sloc: cpp: 7,607,246; javascript: 6,533,185; ansic: 3,775,227; python: 1,415,393; xml: 634,561; asm: 438,951; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (203 lines) | stat: -rw-r--r-- 7,173 bytes parent folder | download
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