Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/ipc/CompositableTransactionParent.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "CompositableTransactionParent.h"
8
#include "CompositableHost.h"           // for CompositableParent, etc
9
#include "CompositorBridgeParent.h"     // for CompositorBridgeParent
10
#include "GLContext.h"                  // for GLContext
11
#include "Layers.h"                     // for Layer
12
#include "RenderTrace.h"                // for RenderTraceInvalidateEnd, etc
13
#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
14
#include "mozilla/RefPtr.h"             // for RefPtr
15
#include "mozilla/layers/CompositorTypes.h"
16
#include "mozilla/layers/ContentHost.h"  // for ContentHostBase
17
#include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
18
#include "mozilla/layers/LayerManagerComposite.h"
19
#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
20
#include "mozilla/layers/LayersTypes.h"  // for MOZ_LAYERS_LOG
21
#include "mozilla/layers/TextureHost.h"  // for TextureHost
22
#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
23
#include "mozilla/layers/TiledContentHost.h"
24
#include "mozilla/layers/PaintedLayerComposite.h"
25
#include "mozilla/mozalloc.h"           // for operator delete
26
#include "mozilla/Unused.h"
27
#include "nsDebug.h"                    // for NS_WARNING, NS_ASSERTION
28
#include "nsRegion.h"                   // for nsIntRegion
29
30
namespace mozilla {
31
namespace layers {
32
33
class ClientTiledLayerBuffer;
34
class Compositor;
35
36
// This function can in some cases fail and return false without it being a bug.
37
// This can theoretically happen if the ImageBridge sends frames before
38
// we created the layer tree. Since we can't enforce that the layer
39
// tree is already created before ImageBridge operates, there isn't much
40
// we can do about it, but in practice it is very rare.
41
// Typically when a tab with a video is dragged from a window to another,
42
// there can be a short time when the video is still sending frames
43
// asynchonously while the layer tree is not reconstructed. It's not a
44
// big deal.
45
// Note that Layers transactions do not need to call this because they always
46
// schedule the composition, in LayerManagerComposite::EndTransaction.
47
static bool
48
ScheduleComposition(CompositableHost* aCompositable)
49
0
{
50
0
  uint64_t id = aCompositable->GetCompositorBridgeID();
51
0
  if (!id) {
52
0
    return false;
53
0
  }
54
0
  CompositorBridgeParent* cp = CompositorBridgeParent::GetCompositorBridgeParent(id);
55
0
  if (!cp) {
56
0
    return false;
57
0
  }
58
0
  cp->ScheduleComposition();
59
0
  return true;
60
0
}
61
62
bool
63
CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit)
64
0
{
65
0
  // Ignore all operations on compositables created on stale compositors. We
66
0
  // return true because the child is unable to handle errors.
67
0
  RefPtr<CompositableHost> compositable = FindCompositable(aEdit.compositable());
68
0
  if (!compositable) {
69
0
    return false;
70
0
  }
71
0
  return ReceiveCompositableUpdate(aEdit.detail(), WrapNotNull(compositable));
72
0
}
73
74
bool
75
CompositableParentManager::ReceiveCompositableUpdate(
76
  const CompositableOperationDetail& aDetail,
77
  NotNull<CompositableHost*> aCompositable)
78
0
{
79
0
  if (TextureSourceProvider* provider = aCompositable->GetTextureSourceProvider()) {
80
0
    if (!provider->IsValid()) {
81
0
      return false;
82
0
    }
83
0
  }
84
0
85
0
  switch (aDetail.type()) {
86
0
    case CompositableOperationDetail::TOpPaintTextureRegion: {
87
0
      MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
88
0
89
0
      const OpPaintTextureRegion& op = aDetail.get_OpPaintTextureRegion();
90
0
      Layer* layer = aCompositable->GetLayer();
91
0
      if (!layer || layer->GetType() != Layer::TYPE_PAINTED) {
92
0
        return false;
93
0
      }
94
0
      PaintedLayerComposite* thebes = static_cast<PaintedLayerComposite*>(layer);
95
0
96
0
      const ThebesBufferData& bufferData = op.bufferData();
97
0
98
0
      RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds());
99
0
100
0
      if (!aCompositable->UpdateThebes(bufferData,
101
0
                                       op.updatedRegion(),
102
0
                                       thebes->GetValidRegion())) {
103
0
        return false;
104
0
      }
105
0
106
0
      RenderTraceInvalidateEnd(thebes, "FF00FF");
107
0
      break;
108
0
    }
109
0
    case CompositableOperationDetail::TOpUseTiledLayerBuffer: {
110
0
      MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
111
0
      const OpUseTiledLayerBuffer& op = aDetail.get_OpUseTiledLayerBuffer();
112
0
      TiledContentHost* tiledHost = aCompositable->AsTiledContentHost();
113
0
114
0
      NS_ASSERTION(tiledHost, "The compositable is not tiled");
115
0
116
0
      const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
117
0
118
0
      bool success = tiledHost->UseTiledLayerBuffer(this, tileDesc);
119
0
120
0
      const InfallibleTArray<TileDescriptor>& tileDescriptors = tileDesc.tiles();
121
0
      for (size_t i = 0; i < tileDescriptors.Length(); i++) {
122
0
        const TileDescriptor& tileDesc = tileDescriptors[i];
123
0
        if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
124
0
          continue;
125
0
        }
126
0
        const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
127
0
        RefPtr<TextureHost> texture = TextureHost::AsTextureHost(texturedDesc.textureParent());
128
0
        if (texture) {
129
0
          texture->SetLastFwdTransactionId(mFwdTransactionId);
130
0
          // Make sure that each texture was handled by the compositable
131
0
          // because the recycling logic depends on it.
132
0
          MOZ_ASSERT(texture->NumCompositableRefs() > 0);
133
0
        }
134
0
        if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
135
0
          texture = TextureHost::AsTextureHost(texturedDesc.textureOnWhite().get_PTextureParent());
136
0
          if (texture) {
137
0
            texture->SetLastFwdTransactionId(mFwdTransactionId);
138
0
            // Make sure that each texture was handled by the compositable
139
0
            // because the recycling logic depends on it.
140
0
            MOZ_ASSERT(texture->NumCompositableRefs() > 0);
141
0
          }
142
0
        }
143
0
      }
144
0
      if (!success) {
145
0
        return false;
146
0
      }
147
0
      break;
148
0
    }
149
0
    case CompositableOperationDetail::TOpRemoveTexture: {
150
0
      const OpRemoveTexture& op = aDetail.get_OpRemoveTexture();
151
0
152
0
      RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
153
0
154
0
      MOZ_ASSERT(tex.get());
155
0
      aCompositable->RemoveTextureHost(tex);
156
0
      break;
157
0
    }
158
0
    case CompositableOperationDetail::TOpUseTexture: {
159
0
      const OpUseTexture& op = aDetail.get_OpUseTexture();
160
0
161
0
      AutoTArray<CompositableHost::TimedTexture,4> textures;
162
0
      for (auto& timedTexture : op.textures()) {
163
0
        CompositableHost::TimedTexture* t = textures.AppendElement();
164
0
        t->mTexture =
165
0
            TextureHost::AsTextureHost(timedTexture.textureParent());
166
0
        MOZ_ASSERT(t->mTexture);
167
0
        t->mTimeStamp = timedTexture.timeStamp();
168
0
        t->mPictureRect = timedTexture.picture();
169
0
        t->mFrameID = timedTexture.frameID();
170
0
        t->mProducerID = timedTexture.producerID();
171
0
        if (timedTexture.readLocked()) {
172
0
          t->mTexture->SetReadLocked();
173
0
        }
174
0
      }
175
0
      if (textures.Length() > 0) {
176
0
        aCompositable->UseTextureHost(textures);
177
0
178
0
        for (auto& timedTexture : op.textures()) {
179
0
          RefPtr<TextureHost> texture = TextureHost::AsTextureHost(timedTexture.textureParent());
180
0
          if (texture) {
181
0
            texture->SetLastFwdTransactionId(mFwdTransactionId);
182
0
            // Make sure that each texture was handled by the compositable
183
0
            // because the recycling logic depends on it.
184
0
            MOZ_ASSERT(texture->NumCompositableRefs() > 0);
185
0
          }
186
0
        }
187
0
      }
188
0
189
0
      if (UsesImageBridge() && aCompositable->GetLayer()) {
190
0
        ScheduleComposition(aCompositable);
191
0
      }
192
0
      break;
193
0
    }
194
0
    case CompositableOperationDetail::TOpUseComponentAlphaTextures: {
195
0
      const OpUseComponentAlphaTextures& op = aDetail.get_OpUseComponentAlphaTextures();
196
0
      RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
197
0
      RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
198
0
      if (op.readLockedBlack()) {
199
0
        texOnBlack->SetReadLocked();
200
0
      }
201
0
      if (op.readLockedWhite()) {
202
0
        texOnWhite->SetReadLocked();
203
0
      }
204
0
205
0
      MOZ_ASSERT(texOnBlack && texOnWhite);
206
0
      aCompositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
207
0
208
0
      if (texOnBlack) {
209
0
        texOnBlack->SetLastFwdTransactionId(mFwdTransactionId);
210
0
        // Make sure that each texture was handled by the compositable
211
0
        // because the recycling logic depends on it.
212
0
        MOZ_ASSERT(texOnBlack->NumCompositableRefs() > 0);
213
0
      }
214
0
215
0
      if (texOnWhite) {
216
0
        texOnWhite->SetLastFwdTransactionId(mFwdTransactionId);
217
0
        // Make sure that each texture was handled by the compositable
218
0
        // because the recycling logic depends on it.
219
0
        MOZ_ASSERT(texOnWhite->NumCompositableRefs() > 0);
220
0
      }
221
0
222
0
      if (UsesImageBridge()) {
223
0
        ScheduleComposition(aCompositable);
224
0
      }
225
0
      break;
226
0
    }
227
0
    default: {
228
0
      MOZ_ASSERT(false, "bad type");
229
0
    }
230
0
  }
231
0
232
0
  return true;
233
0
}
234
235
void
236
CompositableParentManager::DestroyActor(const OpDestroy& aOp)
237
0
{
238
0
  switch (aOp.type()) {
239
0
    case OpDestroy::TPTextureParent: {
240
0
      auto actor = aOp.get_PTextureParent();
241
0
      TextureHost::ReceivedDestroy(actor);
242
0
      break;
243
0
    }
244
0
    case OpDestroy::TCompositableHandle: {
245
0
      ReleaseCompositable(aOp.get_CompositableHandle());
246
0
      break;
247
0
    }
248
0
    default: {
249
0
      MOZ_ASSERT(false, "unsupported type");
250
0
    }
251
0
  }
252
0
}
253
254
RefPtr<CompositableHost>
255
CompositableParentManager::AddCompositable(const CompositableHandle& aHandle,
256
                   const TextureInfo& aInfo,
257
                                           bool aUseWebRender)
258
0
{
259
0
  if (mCompositables.find(aHandle.Value()) != mCompositables.end()) {
260
0
    NS_ERROR("Client should not allocate duplicate handles");
261
0
    return nullptr;
262
0
  }
263
0
  if (!aHandle) {
264
0
    NS_ERROR("Client should not allocate 0 as a handle");
265
0
    return nullptr;
266
0
  }
267
0
268
0
  RefPtr<CompositableHost> host = CompositableHost::Create(aInfo, aUseWebRender);
269
0
  if (!host) {
270
0
    return nullptr;
271
0
  }
272
0
273
0
  mCompositables[aHandle.Value()] = host;
274
0
  return host;
275
0
}
276
277
RefPtr<CompositableHost>
278
CompositableParentManager::FindCompositable(const CompositableHandle& aHandle)
279
0
{
280
0
  auto iter = mCompositables.find(aHandle.Value());
281
0
  if (iter == mCompositables.end()) {
282
0
    return nullptr;
283
0
  }
284
0
  return iter->second;
285
0
}
286
287
void
288
CompositableParentManager::ReleaseCompositable(const CompositableHandle& aHandle)
289
0
{
290
0
  auto iter = mCompositables.find(aHandle.Value());
291
0
  if (iter == mCompositables.end()) {
292
0
    return;
293
0
  }
294
0
295
0
  RefPtr<CompositableHost> host = iter->second;
296
0
  mCompositables.erase(iter);
297
0
298
0
  host->Detach(nullptr, CompositableHost::FORCE_DETACH);
299
0
}
300
301
} // namespace layers
302
} // namespace mozilla
303