Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/composite/TiledContentHost.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 "TiledContentHost.h"
8
#include "gfxPrefs.h"                   // for gfxPrefs
9
#include "PaintedLayerComposite.h"      // for PaintedLayerComposite
10
#include "mozilla/gfx/BaseSize.h"       // for BaseSize
11
#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
12
#include "mozilla/gfx/Point.h"          // for IntSize
13
#include "mozilla/layers/Compositor.h"  // for Compositor
14
//#include "mozilla/layers/CompositorBridgeParent.h"  // for CompositorBridgeParent
15
#include "mozilla/layers/Effects.h"     // for TexturedEffect, Effect, etc
16
#include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
17
#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
18
#ifdef XP_DARWIN
19
#include "mozilla/layers/TextureSync.h" // for TextureSync
20
#endif
21
#include "nsAString.h"
22
#include "nsDebug.h"                    // for NS_WARNING
23
#include "nsPoint.h"                    // for IntPoint
24
#include "nsPrintfCString.h"            // for nsPrintfCString
25
#include "nsRect.h"                     // for IntRect
26
#include "mozilla/layers/TextureClient.h"
27
28
namespace mozilla {
29
using namespace gfx;
30
namespace layers {
31
32
class Layer;
33
34
float
35
TileHost::GetFadeInOpacity(float aOpacity)
36
0
{
37
0
  TimeStamp now = TimeStamp::Now();
38
0
  if (!gfxPrefs::LayerTileFadeInEnabled() ||
39
0
      mFadeStart.IsNull() ||
40
0
      now < mFadeStart)
41
0
  {
42
0
    return aOpacity;
43
0
  }
44
0
45
0
  float duration = gfxPrefs::LayerTileFadeInDuration();
46
0
  float elapsed = (now - mFadeStart).ToMilliseconds();
47
0
  if (elapsed > duration) {
48
0
    mFadeStart = TimeStamp();
49
0
    return aOpacity;
50
0
  }
51
0
  return aOpacity * (elapsed / duration);
52
0
}
53
54
RefPtr<TextureSource>
55
TileHost::AcquireTextureSource() const
56
0
{
57
0
  if (!mTextureHost || !mTextureHost->AcquireTextureSource(mTextureSource)) {
58
0
    return nullptr;
59
0
  }
60
0
  return mTextureSource.get();
61
0
}
62
63
RefPtr<TextureSource>
64
TileHost::AcquireTextureSourceOnWhite() const
65
0
{
66
0
  if (!mTextureHostOnWhite ||
67
0
      !mTextureHostOnWhite->AcquireTextureSource(mTextureSourceOnWhite))
68
0
  {
69
0
    return nullptr;
70
0
  }
71
0
  return mTextureSourceOnWhite.get();
72
0
}
73
74
TiledLayerBufferComposite::TiledLayerBufferComposite()
75
  : mFrameResolution()
76
0
{}
77
78
TiledLayerBufferComposite::~TiledLayerBufferComposite()
79
0
{
80
0
  Clear();
81
0
}
82
83
void
84
TiledLayerBufferComposite::SetTextureSourceProvider(TextureSourceProvider* aProvider)
85
0
{
86
0
  MOZ_ASSERT(aProvider);
87
0
  for (TileHost& tile : mRetainedTiles) {
88
0
    if (tile.IsPlaceholderTile()) continue;
89
0
    tile.mTextureHost->SetTextureSourceProvider(aProvider);
90
0
    if (tile.mTextureHostOnWhite) {
91
0
      tile.mTextureHostOnWhite->SetTextureSourceProvider(aProvider);
92
0
    }
93
0
  }
94
0
}
95
96
void
97
TiledLayerBufferComposite::AddAnimationInvalidation(nsIntRegion& aRegion)
98
0
{
99
0
  // We need to invalidate rects where we have a tile that is in the
100
0
  // process of fading in.
101
0
  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
102
0
    if (!mRetainedTiles[i].mFadeStart.IsNull()) {
103
0
      TileCoordIntPoint coord = mTiles.TileCoord(i);
104
0
      IntPoint offset = GetTileOffset(coord);
105
0
      nsIntRegion tileRegion = IntRect(offset, GetScaledTileSize());
106
0
      aRegion.OrWith(tileRegion);
107
0
    }
108
0
  }
109
0
}
110
111
TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo)
112
  : ContentHost(aTextureInfo)
113
  , mTiledBuffer(TiledLayerBufferComposite())
114
  , mLowPrecisionTiledBuffer(TiledLayerBufferComposite())
115
0
{
116
0
  MOZ_COUNT_CTOR(TiledContentHost);
117
0
}
118
119
TiledContentHost::~TiledContentHost()
120
0
{
121
0
  MOZ_COUNT_DTOR(TiledContentHost);
122
0
}
123
124
already_AddRefed<TexturedEffect>
125
TiledContentHost::GenEffect(const gfx::SamplingFilter aSamplingFilter)
126
0
{
127
0
  MOZ_ASSERT(mTiledBuffer.GetTileCount() == 1 && mLowPrecisionTiledBuffer.GetTileCount() == 0);
128
0
  MOZ_ASSERT(mTiledBuffer.GetTile(0).mTextureHost);
129
0
130
0
  TileHost& tile = mTiledBuffer.GetTile(0);
131
0
  if (!tile.mTextureHost->BindTextureSource(tile.mTextureSource)) {
132
0
    return nullptr;
133
0
  }
134
0
135
0
  return CreateTexturedEffect(tile.mTextureSource,
136
0
                              nullptr,
137
0
                              aSamplingFilter,
138
0
                              true);
139
0
}
140
141
void
142
TiledContentHost::Attach(Layer* aLayer,
143
                         TextureSourceProvider* aProvider,
144
                         AttachFlags aFlags /* = NO_FLAGS */)
145
0
{
146
0
  CompositableHost::Attach(aLayer, aProvider, aFlags);
147
0
}
148
149
void
150
TiledContentHost::Detach(Layer* aLayer,
151
                         AttachFlags aFlags /* = NO_FLAGS */)
152
0
{
153
0
  if (!mKeepAttached || aLayer == mLayer || aFlags & FORCE_DETACH) {
154
0
    // Clear the TiledLayerBuffers, which will take care of releasing the
155
0
    // copy-on-write locks.
156
0
    mTiledBuffer.Clear();
157
0
    mLowPrecisionTiledBuffer.Clear();
158
0
  }
159
0
  CompositableHost::Detach(aLayer,aFlags);
160
0
}
161
162
bool
163
TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
164
                                      const SurfaceDescriptorTiles& aTiledDescriptor)
165
0
{
166
0
  HostLayerManager* lm = GetLayerManager();
167
0
  if (!lm) {
168
0
    return false;
169
0
  }
170
0
171
0
  if (aTiledDescriptor.resolution() < 1) {
172
0
    if (!mLowPrecisionTiledBuffer.UseTiles(aTiledDescriptor, lm, aAllocator)) {
173
0
      return false;
174
0
    }
175
0
  } else {
176
0
    if (!mTiledBuffer.UseTiles(aTiledDescriptor, lm, aAllocator)) {
177
0
      return false;
178
0
    }
179
0
  }
180
0
  return true;
181
0
}
182
183
void
184
UseTileTexture(CompositableTextureHostRef& aTexture,
185
               CompositableTextureSourceRef& aTextureSource,
186
               const IntRect& aUpdateRect,
187
               TextureSourceProvider* aProvider)
188
0
{
189
0
  MOZ_ASSERT(aTexture);
190
0
  if (!aTexture) {
191
0
    return;
192
0
  }
193
0
194
0
  if (aProvider) {
195
0
    aTexture->SetTextureSourceProvider(aProvider);
196
0
  }
197
0
198
0
  if (!aUpdateRect.IsEmpty()) {
199
0
    // For !HasIntermediateBuffer() textures, this is likely a no-op.
200
0
    nsIntRegion region = aUpdateRect;
201
0
    aTexture->Updated(&region);
202
0
  }
203
0
204
0
  aTexture->PrepareTextureSource(aTextureSource);
205
0
}
206
207
class TextureSourceRecycler
208
{
209
public:
210
  explicit TextureSourceRecycler(nsTArray<TileHost>&& aTileSet)
211
    : mTiles(std::move(aTileSet))
212
    , mFirstPossibility(0)
213
0
  {}
214
215
  // Attempts to recycle a texture source that is already bound to the
216
  // texture host for aTile.
217
0
  void RecycleTextureSourceForTile(TileHost& aTile) {
218
0
    for (size_t i = mFirstPossibility; i < mTiles.Length(); i++) {
219
0
      // Skip over existing tiles without a retained texture source
220
0
      // and make sure we don't iterate them in the future.
221
0
      if (!mTiles[i].mTextureSource) {
222
0
        if (i == mFirstPossibility) {
223
0
          mFirstPossibility++;
224
0
        }
225
0
        continue;
226
0
      }
227
0
228
0
      // If this tile matches, then copy across the retained texture source (if
229
0
      // any).
230
0
      if (aTile.mTextureHost == mTiles[i].mTextureHost) {
231
0
        aTile.mTextureSource = std::move(mTiles[i].mTextureSource);
232
0
        if (aTile.mTextureHostOnWhite) {
233
0
          aTile.mTextureSourceOnWhite = std::move(mTiles[i].mTextureSourceOnWhite);
234
0
        }
235
0
        break;
236
0
      }
237
0
    }
238
0
  }
239
240
  // Attempts to recycle any texture source to avoid needing to allocate
241
  // a new one.
242
0
  void RecycleTextureSource(TileHost& aTile) {
243
0
    for (size_t i = mFirstPossibility; i < mTiles.Length(); i++) {
244
0
      if (!mTiles[i].mTextureSource) {
245
0
        if (i == mFirstPossibility) {
246
0
          mFirstPossibility++;
247
0
        }
248
0
        continue;
249
0
      }
250
0
251
0
      if (mTiles[i].mTextureSource &&
252
0
          mTiles[i].mTextureHost->GetFormat() == aTile.mTextureHost->GetFormat()) {
253
0
        aTile.mTextureSource = std::move(mTiles[i].mTextureSource);
254
0
        if (aTile.mTextureHostOnWhite) {
255
0
          aTile.mTextureSourceOnWhite = std::move(mTiles[i].mTextureSourceOnWhite);
256
0
        }
257
0
        break;
258
0
      }
259
0
    }
260
0
  }
261
262
0
  void RecycleTileFading(TileHost& aTile) {
263
0
    for (size_t i = 0; i < mTiles.Length(); i++) {
264
0
      if (mTiles[i].mTextureHost == aTile.mTextureHost) {
265
0
        aTile.mFadeStart = mTiles[i].mFadeStart;
266
0
      }
267
0
    }
268
0
  }
269
270
protected:
271
  nsTArray<TileHost> mTiles;
272
  size_t mFirstPossibility;
273
};
274
275
bool
276
TiledLayerBufferComposite::UseTiles(const SurfaceDescriptorTiles& aTiles,
277
                                    HostLayerManager* aLayerManager,
278
                                    ISurfaceAllocator* aAllocator)
279
0
{
280
0
  if (mResolution != aTiles.resolution() ||
281
0
      aTiles.tileSize() != mTileSize) {
282
0
    Clear();
283
0
  }
284
0
  MOZ_ASSERT(aAllocator);
285
0
  MOZ_ASSERT(aLayerManager);
286
0
  if (!aAllocator || !aLayerManager) {
287
0
    return false;
288
0
  }
289
0
290
0
  if (aTiles.resolution() == 0 || IsNaN(aTiles.resolution())) {
291
0
    // There are divisions by mResolution so this protects the compositor process
292
0
    // against malicious content processes and fuzzing.
293
0
    return false;
294
0
  }
295
0
296
0
  TilesPlacement newTiles(aTiles.firstTileX(), aTiles.firstTileY(),
297
0
                          aTiles.retainedWidth(), aTiles.retainedHeight());
298
0
299
0
  const InfallibleTArray<TileDescriptor>& tileDescriptors = aTiles.tiles();
300
0
301
0
  TextureSourceRecycler oldRetainedTiles(std::move(mRetainedTiles));
302
0
  mRetainedTiles.SetLength(tileDescriptors.Length());
303
0
304
0
  AutoTArray<uint64_t, 10> lockedTextureSerials;
305
0
  base::ProcessId lockedTexturePid = 0;
306
0
307
0
  // Step 1, deserialize the incoming set of tiles into mRetainedTiles, and attempt
308
0
  // to recycle the TextureSource for any repeated tiles.
309
0
  //
310
0
  // Since we don't have any retained 'tile' object, we have to search for instances
311
0
  // of the same TextureHost in the old tile set. The cost of binding a TextureHost
312
0
  // to a TextureSource for gralloc (binding EGLImage to GL texture) can be really
313
0
  // high, so we avoid this whenever possible.
314
0
  for (size_t i = 0; i < tileDescriptors.Length(); i++) {
315
0
    const TileDescriptor& tileDesc = tileDescriptors[i];
316
0
317
0
    TileHost& tile = mRetainedTiles[i];
318
0
319
0
    if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
320
0
      NS_WARNING_ASSERTION(
321
0
        tileDesc.type() == TileDescriptor::TPlaceholderTileDescriptor,
322
0
        "Unrecognised tile descriptor type");
323
0
      continue;
324
0
    }
325
0
326
0
    const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
327
0
328
0
    tile.mTextureHost = TextureHost::AsTextureHost(texturedDesc.textureParent());
329
0
    if (texturedDesc.readLocked()) {
330
0
      tile.mTextureHost->SetReadLocked();
331
0
      auto actor = tile.mTextureHost->GetIPDLActor();
332
0
      if (actor && tile.mTextureHost->IsDirectMap()) {
333
0
        lockedTextureSerials.AppendElement(TextureHost::GetTextureSerial(actor));
334
0
335
0
        if (lockedTexturePid) {
336
0
          MOZ_ASSERT(lockedTexturePid == actor->OtherPid());
337
0
        }
338
0
        lockedTexturePid = actor->OtherPid();
339
0
      }
340
0
    }
341
0
342
0
    if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
343
0
      tile.mTextureHostOnWhite = TextureHost::AsTextureHost(
344
0
        texturedDesc.textureOnWhite().get_PTextureParent()
345
0
      );
346
0
      if (texturedDesc.readLockedOnWhite()) {
347
0
        tile.mTextureHostOnWhite->SetReadLocked();
348
0
        auto actor = tile.mTextureHostOnWhite->GetIPDLActor();
349
0
        if (actor && tile.mTextureHostOnWhite->IsDirectMap()) {
350
0
          lockedTextureSerials.AppendElement(TextureHost::GetTextureSerial(actor));
351
0
        }
352
0
      }
353
0
    }
354
0
355
0
    tile.mTileCoord = newTiles.TileCoord(i);
356
0
357
0
    // If this same tile texture existed in the old tile set then this will move the texture
358
0
    // source into our new tile.
359
0
    oldRetainedTiles.RecycleTextureSourceForTile(tile);
360
0
361
0
    // If this tile is in the process of fading, we need to keep that going
362
0
    oldRetainedTiles.RecycleTileFading(tile);
363
0
364
0
    if (aTiles.isProgressive() &&
365
0
        texturedDesc.wasPlaceholder())
366
0
    {
367
0
      // This is a progressive paint, and the tile used to be a placeholder.
368
0
      // We need to begin fading it in (if enabled via layers.tiles.fade-in.enabled)
369
0
      tile.mFadeStart = TimeStamp::Now();
370
0
371
0
      aLayerManager->CompositeUntil(
372
0
        tile.mFadeStart + TimeDuration::FromMilliseconds(gfxPrefs::LayerTileFadeInDuration()));
373
0
    }
374
0
  }
375
0
376
  #ifdef XP_DARWIN
377
  if (lockedTextureSerials.Length() > 0) {
378
    TextureSync::SetTexturesLocked(lockedTexturePid, lockedTextureSerials);
379
  }
380
  #endif
381
382
0
  // Step 2, attempt to recycle unused texture sources from the old tile set into new tiles.
383
0
  //
384
0
  // For gralloc, binding a new TextureHost to the existing TextureSource is the fastest way
385
0
  // to ensure that any implicit locking on the old gralloc image is released.
386
0
  for (TileHost& tile : mRetainedTiles) {
387
0
    if (!tile.mTextureHost || tile.mTextureSource) {
388
0
      continue;
389
0
    }
390
0
    oldRetainedTiles.RecycleTextureSource(tile);
391
0
  }
392
0
393
0
  // Step 3, handle the texture uploads, texture source binding and release the
394
0
  // copy-on-write locks for textures with an internal buffer.
395
0
  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
396
0
    TileHost& tile = mRetainedTiles[i];
397
0
    if (!tile.mTextureHost) {
398
0
      continue;
399
0
    }
400
0
401
0
    const TileDescriptor& tileDesc = tileDescriptors[i];
402
0
    const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
403
0
404
0
    UseTileTexture(tile.mTextureHost,
405
0
                   tile.mTextureSource,
406
0
                   texturedDesc.updateRect(),
407
0
                   aLayerManager->GetTextureSourceProvider());
408
0
409
0
    if (tile.mTextureHostOnWhite) {
410
0
      UseTileTexture(tile.mTextureHostOnWhite,
411
0
                     tile.mTextureSourceOnWhite,
412
0
                     texturedDesc.updateRect(),
413
0
                     aLayerManager->GetTextureSourceProvider());
414
0
    }
415
0
  }
416
0
417
0
  mTiles = newTiles;
418
0
  mTileSize = aTiles.tileSize();
419
0
  mTileOrigin = aTiles.tileOrigin();
420
0
  mValidRegion = aTiles.validRegion();
421
0
  mResolution = aTiles.resolution();
422
0
  mFrameResolution = CSSToParentLayerScale2D(aTiles.frameXResolution(),
423
0
                                             aTiles.frameYResolution());
424
0
425
0
  return true;
426
0
}
427
428
void
429
TiledLayerBufferComposite::Clear()
430
0
{
431
0
  mRetainedTiles.Clear();
432
0
  mTiles.mFirst = TileCoordIntPoint();
433
0
  mTiles.mSize = TileCoordIntSize();
434
0
  mValidRegion = nsIntRegion();
435
0
  mResolution = 1.0;
436
0
}
437
438
void
439
TiledContentHost::Composite(Compositor* aCompositor,
440
                            LayerComposite* aLayer,
441
                            EffectChain& aEffectChain,
442
                            float aOpacity,
443
                            const gfx::Matrix4x4& aTransform,
444
                            const gfx::SamplingFilter aSamplingFilter,
445
                            const gfx::IntRect& aClipRect,
446
                            const nsIntRegion* aVisibleRegion /* = nullptr */,
447
                            const Maybe<gfx::Polygon>& aGeometry)
448
0
{
449
0
  // Reduce the opacity of the low-precision buffer to make it a
450
0
  // little more subtle and less jarring. In particular, text
451
0
  // rendered at low-resolution and scaled tends to look pretty
452
0
  // heavy and this helps mitigate that. When we reduce the opacity
453
0
  // we also make sure to draw the background color behind the
454
0
  // reduced-opacity tile so that content underneath doesn't show
455
0
  // through.
456
0
  // However, in cases where the background is transparent, or the layer
457
0
  // already has some opacity, we want to skip this behaviour. Otherwise
458
0
  // we end up changing the expected overall transparency of the content,
459
0
  // and it just looks wrong.
460
0
  Color backgroundColor;
461
0
  if (aOpacity == 1.0f && gfxPrefs::LowPrecisionOpacity() < 1.0f) {
462
0
    // Background colors are only stored on scrollable layers. Grab
463
0
    // the one from the nearest scrollable ancestor layer.
464
0
    for (LayerMetricsWrapper ancestor(GetLayer(), LayerMetricsWrapper::StartAt::BOTTOM); ancestor; ancestor = ancestor.GetParent()) {
465
0
      if (ancestor.Metrics().IsScrollable()) {
466
0
        backgroundColor = ancestor.Metadata().GetBackgroundColor();
467
0
        break;
468
0
      }
469
0
    }
470
0
  }
471
0
  float lowPrecisionOpacityReduction =
472
0
        (aOpacity == 1.0f && backgroundColor.a == 1.0f)
473
0
        ? gfxPrefs::LowPrecisionOpacity() : 1.0f;
474
0
475
0
  nsIntRegion tmpRegion;
476
0
  const nsIntRegion* renderRegion = aVisibleRegion;
477
0
#ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
478
0
  if (PaintWillResample()) {
479
0
    // If we're resampling, then the texture image will contain exactly the
480
0
    // entire visible region's bounds, and we should draw it all in one quad
481
0
    // to avoid unexpected aliasing.
482
0
    tmpRegion = aVisibleRegion->GetBounds();
483
0
    renderRegion = &tmpRegion;
484
0
  }
485
0
#endif
486
0
487
0
  // Render the low and high precision buffers.
488
0
  RenderLayerBuffer(mLowPrecisionTiledBuffer, aCompositor,
489
0
                    lowPrecisionOpacityReduction < 1.0f ? &backgroundColor : nullptr,
490
0
                    aEffectChain, lowPrecisionOpacityReduction * aOpacity,
491
0
                    aSamplingFilter, aClipRect, *renderRegion, aTransform, aGeometry);
492
0
493
0
  RenderLayerBuffer(mTiledBuffer, aCompositor, nullptr, aEffectChain, aOpacity, aSamplingFilter,
494
0
                    aClipRect, *renderRegion, aTransform, aGeometry);
495
0
}
496
497
498
void
499
TiledContentHost::RenderTile(TileHost& aTile,
500
                             Compositor* aCompositor,
501
                             EffectChain& aEffectChain,
502
                             float aOpacity,
503
                             const gfx::Matrix4x4& aTransform,
504
                             const gfx::SamplingFilter aSamplingFilter,
505
                             const gfx::IntRect& aClipRect,
506
                             const nsIntRegion& aScreenRegion,
507
                             const IntPoint& aTextureOffset,
508
                             const IntSize& aTextureBounds,
509
                             const gfx::Rect& aVisibleRect,
510
                             const Maybe<gfx::Polygon>& aGeometry)
511
0
{
512
0
  MOZ_ASSERT(!aTile.IsPlaceholderTile());
513
0
514
0
  AutoLockTextureHost autoLock(aTile.mTextureHost);
515
0
  AutoLockTextureHost autoLockOnWhite(aTile.mTextureHostOnWhite);
516
0
  if (autoLock.Failed() ||
517
0
      autoLockOnWhite.Failed()) {
518
0
    NS_WARNING("Failed to lock tile");
519
0
    return;
520
0
  }
521
0
522
0
  if (!aTile.mTextureHost->BindTextureSource(aTile.mTextureSource)) {
523
0
    return;
524
0
  }
525
0
526
0
  if (aTile.mTextureHostOnWhite && !aTile.mTextureHostOnWhite->BindTextureSource(aTile.mTextureSourceOnWhite)) {
527
0
    return;
528
0
  }
529
0
530
0
  RefPtr<TexturedEffect> effect =
531
0
    CreateTexturedEffect(aTile.mTextureSource,
532
0
                         aTile.mTextureSourceOnWhite,
533
0
                         aSamplingFilter,
534
0
                         true);
535
0
  if (!effect) {
536
0
    return;
537
0
  }
538
0
539
0
  float opacity = aTile.GetFadeInOpacity(aOpacity);
540
0
  aEffectChain.mPrimaryEffect = effect;
541
0
542
0
  for (auto iter = aScreenRegion.RectIter(); !iter.Done(); iter.Next()) {
543
0
    const IntRect& rect = iter.Get();
544
0
    Rect graphicsRect(rect.X(), rect.Y(), rect.Width(), rect.Height());
545
0
    Rect textureRect(rect.X() - aTextureOffset.x, rect.Y() - aTextureOffset.y,
546
0
                     rect.Width(), rect.Height());
547
0
548
0
    effect->mTextureCoords.SetRect(textureRect.X() / aTextureBounds.width,
549
0
                                   textureRect.Y() / aTextureBounds.height,
550
0
                                   textureRect.Width() / aTextureBounds.width,
551
0
                                   textureRect.Height() / aTextureBounds.height);
552
0
553
0
    aCompositor->DrawGeometry(graphicsRect, aClipRect, aEffectChain, opacity,
554
0
                              aTransform, aVisibleRect, aGeometry);
555
0
  }
556
0
557
0
  DiagnosticFlags flags = DiagnosticFlags::CONTENT | DiagnosticFlags::TILE;
558
0
  if (aTile.mTextureHostOnWhite) {
559
0
    flags |= DiagnosticFlags::COMPONENT_ALPHA;
560
0
  }
561
0
  aCompositor->DrawDiagnostics(flags,
562
0
                               aScreenRegion, aClipRect, aTransform, mFlashCounter);
563
0
}
564
565
void
566
TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
567
                                    Compositor* aCompositor,
568
                                    const Color* aBackgroundColor,
569
                                    EffectChain& aEffectChain,
570
                                    float aOpacity,
571
                                    const gfx::SamplingFilter aSamplingFilter,
572
                                    const gfx::IntRect& aClipRect,
573
                                    nsIntRegion aVisibleRegion,
574
                                    gfx::Matrix4x4 aTransform,
575
                                    const Maybe<Polygon>& aGeometry)
576
0
{
577
0
  float resolution = aLayerBuffer.GetResolution();
578
0
  gfx::Size layerScale(1, 1);
579
0
580
0
  // We assume that the current frame resolution is the one used in our high
581
0
  // precision layer buffer. Compensate for a changing frame resolution when
582
0
  // rendering the low precision buffer.
583
0
  if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
584
0
    const CSSToParentLayerScale2D& layerResolution = aLayerBuffer.GetFrameResolution();
585
0
    const CSSToParentLayerScale2D& localResolution = mTiledBuffer.GetFrameResolution();
586
0
    layerScale.width = layerResolution.xScale / localResolution.xScale;
587
0
    layerScale.height = layerResolution.yScale / localResolution.yScale;
588
0
    aVisibleRegion.ScaleRoundOut(layerScale.width, layerScale.height);
589
0
  }
590
0
591
0
  // Make sure we don't render at low resolution where we have valid high
592
0
  // resolution content, to avoid overdraw and artifacts with semi-transparent
593
0
  // layers.
594
0
  nsIntRegion maskRegion;
595
0
  if (resolution != mTiledBuffer.GetResolution()) {
596
0
    maskRegion = mTiledBuffer.GetValidRegion();
597
0
    // XXX This should be ScaleRoundIn, but there is no such function on
598
0
    //     nsIntRegion.
599
0
    maskRegion.ScaleRoundOut(layerScale.width, layerScale.height);
600
0
  }
601
0
602
0
  // Make sure the resolution and difference in frame resolution are accounted
603
0
  // for in the layer transform.
604
0
  aTransform.PreScale(1/(resolution * layerScale.width),
605
0
                      1/(resolution * layerScale.height), 1);
606
0
607
0
  DiagnosticFlags componentAlphaDiagnostic = DiagnosticFlags::NO_DIAGNOSTIC;
608
0
609
0
  nsIntRegion compositeRegion = aLayerBuffer.GetValidRegion();
610
0
  compositeRegion.AndWith(aVisibleRegion);
611
0
  compositeRegion.SubOut(maskRegion);
612
0
613
0
  IntRect visibleRect = aVisibleRegion.GetBounds();
614
0
615
0
  if (compositeRegion.IsEmpty()) {
616
0
    return;
617
0
  }
618
0
619
0
  if (aBackgroundColor) {
620
0
    nsIntRegion backgroundRegion = compositeRegion;
621
0
    backgroundRegion.ScaleRoundOut(resolution, resolution);
622
0
    EffectChain effect;
623
0
    effect.mPrimaryEffect = new EffectSolidColor(*aBackgroundColor);
624
0
    for (auto iter = backgroundRegion.RectIter(); !iter.Done(); iter.Next()) {
625
0
      const IntRect& rect = iter.Get();
626
0
      Rect graphicsRect(rect.X(), rect.Y(), rect.Width(), rect.Height());
627
0
      aCompositor->DrawGeometry(graphicsRect, aClipRect, effect,
628
0
                                1.0, aTransform, aGeometry);
629
0
    }
630
0
  }
631
0
632
0
  for (size_t i = 0; i < aLayerBuffer.GetTileCount(); ++i) {
633
0
    TileHost& tile = aLayerBuffer.GetTile(i);
634
0
    if (tile.IsPlaceholderTile()) {
635
0
      continue;
636
0
    }
637
0
638
0
    TileCoordIntPoint tileCoord = aLayerBuffer.GetPlacement().TileCoord(i);
639
0
    // A sanity check that catches a lot of mistakes.
640
0
    MOZ_ASSERT(tileCoord.x == tile.mTileCoord.x && tileCoord.y == tile.mTileCoord.y);
641
0
642
0
    IntPoint tileOffset = aLayerBuffer.GetTileOffset(tileCoord);
643
0
    nsIntRegion tileDrawRegion = IntRect(tileOffset, aLayerBuffer.GetScaledTileSize());
644
0
    tileDrawRegion.AndWith(compositeRegion);
645
0
646
0
    if (tileDrawRegion.IsEmpty()) {
647
0
      continue;
648
0
    }
649
0
650
0
    tileDrawRegion.ScaleRoundOut(resolution, resolution);
651
0
    RenderTile(tile, aCompositor, aEffectChain, aOpacity,
652
0
               aTransform, aSamplingFilter, aClipRect, tileDrawRegion,
653
0
               tileOffset * resolution, aLayerBuffer.GetTileSize(),
654
0
               gfx::Rect(visibleRect.X(), visibleRect.Y(),
655
0
                         visibleRect.Width(), visibleRect.Height()),
656
0
               aGeometry);
657
0
658
0
    if (tile.mTextureHostOnWhite) {
659
0
      componentAlphaDiagnostic = DiagnosticFlags::COMPONENT_ALPHA;
660
0
    }
661
0
  }
662
0
663
0
  gfx::Rect rect(visibleRect.X(), visibleRect.Y(),
664
0
                 visibleRect.Width(), visibleRect.Height());
665
0
  aCompositor->DrawDiagnostics(DiagnosticFlags::CONTENT | componentAlphaDiagnostic,
666
0
                               rect, aClipRect, aTransform, mFlashCounter);
667
0
}
668
669
void
670
TiledContentHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
671
0
{
672
0
  aStream << aPrefix;
673
0
  aStream << nsPrintfCString("TiledContentHost (0x%p)", this).get();
674
0
675
#if defined(MOZ_DUMP_PAINTING)
676
  if (gfxPrefs::LayersDumpTexture()) {
677
    nsAutoCString pfx(aPrefix);
678
    pfx += "  ";
679
680
    Dump(aStream, pfx.get(), false);
681
  }
682
#endif
683
}
684
685
void
686
TiledContentHost::Dump(std::stringstream& aStream,
687
                       const char* aPrefix,
688
                       bool aDumpHtml)
689
0
{
690
0
  mTiledBuffer.Dump(aStream, aPrefix, aDumpHtml,
691
0
      TextureDumpMode::DoNotCompress /* compression not supported on host side */);
692
0
}
693
694
void
695
TiledContentHost::AddAnimationInvalidation(nsIntRegion& aRegion)
696
0
{
697
0
  return mTiledBuffer.AddAnimationInvalidation(aRegion);
698
0
}
699
700
701
} // namespace layers
702
} // namespace mozilla