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