Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/wr/WebRenderUserData.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 "WebRenderUserData.h"
8
9
#include "mozilla/layers/CompositorBridgeChild.h"
10
#include "mozilla/layers/ImageClient.h"
11
#include "mozilla/layers/WebRenderBridgeChild.h"
12
#include "mozilla/layers/WebRenderLayerManager.h"
13
#include "mozilla/layers/WebRenderMessages.h"
14
#include "mozilla/layers/IpcResourceUpdateQueue.h"
15
#include "mozilla/layers/SharedSurfacesChild.h"
16
#include "nsDisplayListInvalidation.h"
17
#include "nsIFrame.h"
18
#include "WebRenderCanvasRenderer.h"
19
20
namespace mozilla {
21
namespace layers {
22
23
void
24
WebRenderBackgroundData::AddWebRenderCommands(wr::DisplayListBuilder& aBuilder)
25
0
{
26
0
  aBuilder.PushRect(mBounds,
27
0
                    mBounds,
28
0
                    true,
29
0
                    mColor);
30
0
}
31
32
/* static */ bool
33
WebRenderUserData::SupportsAsyncUpdate(nsIFrame* aFrame)
34
0
{
35
0
  if (!aFrame) {
36
0
    return false;
37
0
  }
38
0
  RefPtr<WebRenderImageData> data = GetWebRenderUserData<WebRenderImageData>(aFrame, static_cast<uint32_t>(DisplayItemType::TYPE_VIDEO));
39
0
  if (data) {
40
0
    return data->IsAsync();
41
0
  }
42
0
43
0
  return false;
44
0
}
45
46
WebRenderUserData::WebRenderUserData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
47
  : mWRManager(aWRManager)
48
  , mFrame(aItem->Frame())
49
  , mDisplayItemKey(aItem->GetPerFrameKey())
50
  , mTable(aWRManager->GetWebRenderUserDataTable())
51
  , mUsed(false)
52
0
{
53
0
}
54
55
WebRenderUserData::~WebRenderUserData()
56
0
{
57
0
}
58
59
void
60
WebRenderUserData::RemoveFromTable()
61
0
{
62
0
  mTable->RemoveEntry(this);
63
0
}
64
65
WebRenderBridgeChild*
66
WebRenderUserData::WrBridge() const
67
0
{
68
0
  return mWRManager->WrBridge();
69
0
}
70
71
WebRenderImageData::WebRenderImageData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
72
  : WebRenderUserData(aWRManager, aItem)
73
  , mOwnsKey(false)
74
0
{
75
0
}
76
77
WebRenderImageData::~WebRenderImageData()
78
0
{
79
0
  ClearImageKey();
80
0
81
0
  if (mPipelineId) {
82
0
    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
83
0
  }
84
0
}
85
86
void
87
WebRenderImageData::ClearImageKey()
88
0
{
89
0
  if (mKey) {
90
0
    // If we don't own the key, then the owner is responsible for discarding the
91
0
    // key when appropriate.
92
0
    if (mOwnsKey) {
93
0
      mWRManager->AddImageKeyForDiscard(mKey.value());
94
0
      if (mTextureOfImage) {
95
0
        WrBridge()->ReleaseTextureOfImage(mKey.value());
96
0
        mTextureOfImage = nullptr;
97
0
      }
98
0
    }
99
0
    mKey.reset();
100
0
  }
101
0
  mOwnsKey = false;
102
0
  MOZ_ASSERT(!mTextureOfImage);
103
0
}
104
105
Maybe<wr::ImageKey>
106
WebRenderImageData::UpdateImageKey(ImageContainer* aContainer,
107
                                   wr::IpcResourceUpdateQueue& aResources,
108
                                   bool aFallback)
109
0
{
110
0
  MOZ_ASSERT(aContainer);
111
0
112
0
  if (mContainer != aContainer) {
113
0
    mContainer = aContainer;
114
0
  }
115
0
116
0
  wr::WrImageKey key;
117
0
  if (!aFallback) {
118
0
    nsresult rv = SharedSurfacesChild::Share(aContainer, mWRManager, aResources, key);
119
0
    if (NS_SUCCEEDED(rv)) {
120
0
      // Ensure that any previously owned keys are released before replacing. We
121
0
      // don't own this key, the surface itself owns it, so that it can be shared
122
0
      // across multiple elements.
123
0
      ClearImageKey();
124
0
      mKey = Some(key);
125
0
      return mKey;
126
0
    }
127
0
128
0
    if (rv != NS_ERROR_NOT_IMPLEMENTED) {
129
0
      // We should be using the shared surface but somehow sharing it failed.
130
0
      ClearImageKey();
131
0
      return Nothing();
132
0
    }
133
0
  }
134
0
135
0
  CreateImageClientIfNeeded();
136
0
  if (!mImageClient) {
137
0
    return Nothing();
138
0
  }
139
0
140
0
  MOZ_ASSERT(mImageClient->AsImageClientSingle());
141
0
142
0
  ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
143
0
  uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();
144
0
145
0
  bool ret = imageClient->UpdateImage(aContainer, /* unused */0);
146
0
  RefPtr<TextureClient> currentTexture = imageClient->GetForwardedTexture();
147
0
  if (!ret || !currentTexture) {
148
0
    // Delete old key
149
0
    ClearImageKey();
150
0
    return Nothing();
151
0
  }
152
0
153
0
  // Reuse old key if generation is not updated.
154
0
  if (!aFallback && oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
155
0
    return mKey;
156
0
  }
157
0
158
0
  // If we already had a texture and the format hasn't changed, better to reuse the image keys
159
0
  // than create new ones.
160
0
  bool useUpdate = mKey.isSome()
161
0
                   && !!mTextureOfImage
162
0
                   && !!currentTexture
163
0
                   && mTextureOfImage->GetSize() == currentTexture->GetSize()
164
0
                   && mTextureOfImage->GetFormat() == currentTexture->GetFormat();
165
0
166
0
  wr::MaybeExternalImageId extId = currentTexture->GetExternalImageKey();
167
0
  MOZ_RELEASE_ASSERT(extId.isSome());
168
0
169
0
  if (useUpdate) {
170
0
    MOZ_ASSERT(mKey.isSome());
171
0
    MOZ_ASSERT(mTextureOfImage);
172
0
    aResources.PushExternalImageForTexture(extId.ref(), mKey.ref(), currentTexture, /* aIsUpdate */ true);
173
0
  } else {
174
0
    ClearImageKey();
175
0
    key = WrBridge()->GetNextImageKey();
176
0
    aResources.PushExternalImageForTexture(extId.ref(), key, currentTexture, /* aIsUpdate */ false);
177
0
    mKey = Some(key);
178
0
  }
179
0
180
0
  mTextureOfImage = currentTexture;
181
0
  mOwnsKey = true;
182
0
183
0
  return mKey;
184
0
}
185
186
void
187
WebRenderImageData::SetKey(const wr::ImageKey& aKey)
188
0
{
189
0
  MOZ_ASSERT_IF(mKey, mKey.value() != aKey);
190
0
  ClearImageKey();
191
0
  mKey = Some(aKey);
192
0
  mOwnsKey = true;
193
0
}
194
195
already_AddRefed<ImageClient>
196
WebRenderImageData::GetImageClient()
197
0
{
198
0
  RefPtr<ImageClient> imageClient = mImageClient;
199
0
  return imageClient.forget();
200
0
}
201
202
void
203
WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
204
                                                      ImageContainer* aContainer,
205
                                                      const StackingContextHelper& aSc,
206
                                                      const LayoutDeviceRect& aBounds,
207
                                                      const LayoutDeviceRect& aSCBounds,
208
                                                      const gfx::Matrix4x4& aSCTransform,
209
                                                      const gfx::MaybeIntSize& aScaleToSize,
210
                                                      const wr::ImageRendering& aFilter,
211
                                                      const wr::MixBlendMode& aMixBlendMode,
212
                                                      bool aIsBackfaceVisible)
213
0
{
214
0
  MOZ_ASSERT(aContainer->IsAsync());
215
0
216
0
  if (mPipelineId.isSome() && mContainer != aContainer) {
217
0
    // In this case, we need to remove the existed pipeline and create new one
218
0
    // because the ImageContainer is changed.
219
0
    WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
220
0
    mPipelineId.reset();
221
0
  }
222
0
223
0
  if (!mPipelineId) {
224
0
    // Alloc async image pipeline id.
225
0
    mPipelineId = Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
226
0
    WrBridge()->AddPipelineIdForAsyncCompositable(mPipelineId.ref(),
227
0
                                                  aContainer->GetAsyncContainerHandle());
228
0
    mContainer = aContainer;
229
0
  }
230
0
  MOZ_ASSERT(!mImageClient);
231
0
232
0
  // Push IFrame for async image pipeline.
233
0
  //
234
0
  // We don't push a stacking context for this async image pipeline here.
235
0
  // Instead, we do it inside the iframe that hosts the image. As a result,
236
0
  // a bunch of the calculations normally done as part of that stacking
237
0
  // context need to be done manually and pushed over to the parent side,
238
0
  // where it will be done when we build the display list for the iframe.
239
0
  // That happens in AsyncImagePipelineManager.
240
0
  wr::LayoutRect r = wr::ToRoundedLayoutRect(aBounds);
241
0
  aBuilder.PushIFrame(r, aIsBackfaceVisible, mPipelineId.ref(), /*ignoreMissingPipelines*/ false);
242
0
243
0
  WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(mPipelineId.value(),
244
0
                                                                   aSCBounds,
245
0
                                                                   aSCTransform,
246
0
                                                                   aScaleToSize,
247
0
                                                                   aFilter,
248
0
                                                                   aMixBlendMode));
249
0
}
250
251
void
252
WebRenderImageData::CreateImageClientIfNeeded()
253
0
{
254
0
  if (!mImageClient) {
255
0
    mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
256
0
                                                  WrBridge(),
257
0
                                                  TextureFlags::DEFAULT);
258
0
    if (!mImageClient) {
259
0
      return;
260
0
    }
261
0
262
0
    mImageClient->Connect();
263
0
  }
264
0
}
265
266
WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
267
  : WebRenderImageData(aWRManager, aItem)
268
  , mInvalid(false)
269
0
{
270
0
}
271
272
WebRenderFallbackData::~WebRenderFallbackData()
273
0
{
274
0
}
275
276
nsDisplayItemGeometry*
277
WebRenderFallbackData::GetGeometry()
278
0
{
279
0
  return mGeometry.get();
280
0
}
281
282
void
283
WebRenderFallbackData::SetGeometry(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
284
0
{
285
0
  mGeometry = aGeometry;
286
0
}
287
288
WebRenderAnimationData::WebRenderAnimationData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
289
  : WebRenderUserData(aWRManager, aItem)
290
  , mAnimationInfo(aWRManager)
291
0
{
292
0
}
293
294
WebRenderAnimationData::~WebRenderAnimationData()
295
0
{
296
0
  // It may be the case that nsDisplayItem that created this WebRenderUserData
297
0
  // gets destroyed without getting a chance to discard the compositor animation
298
0
  // id, so we should do it as part of cleanup here.
299
0
  uint64_t animationId = mAnimationInfo.GetCompositorAnimationsId();
300
0
  // animationId might be 0 if mAnimationInfo never held any active animations.
301
0
  if (animationId) {
302
0
    mWRManager->AddCompositorAnimationsIdForDiscard(animationId);
303
0
  }
304
0
}
305
306
WebRenderCanvasData::WebRenderCanvasData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
307
  : WebRenderUserData(aWRManager, aItem)
308
0
{
309
0
}
310
311
WebRenderCanvasData::~WebRenderCanvasData()
312
0
{
313
0
  if (mCanvasRenderer) {
314
0
    mCanvasRenderer->ClearCachedResources();
315
0
  }
316
0
}
317
318
void
319
WebRenderCanvasData::ClearCanvasRenderer()
320
0
{
321
0
  mCanvasRenderer = nullptr;
322
0
}
323
324
WebRenderCanvasRendererAsync*
325
WebRenderCanvasData::GetCanvasRenderer()
326
0
{
327
0
  return mCanvasRenderer.get();
328
0
}
329
330
WebRenderCanvasRendererAsync*
331
WebRenderCanvasData::CreateCanvasRenderer()
332
0
{
333
0
  mCanvasRenderer = MakeUnique<WebRenderCanvasRendererAsync>(mWRManager);
334
0
  return mCanvasRenderer.get();
335
0
}
336
337
void
338
DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable)
339
0
{
340
0
  for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
341
0
    iter.UserData()->RemoveFromTable();
342
0
  }
343
0
  delete aTable;
344
0
}
345
346
347
} // namespace layers
348
} // namespace mozilla