gfx/layers/composite/LayerManagerComposite.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:888244f7e941
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 "LayerManagerComposite.h"
7 #include <stddef.h> // for size_t
8 #include <stdint.h> // for uint16_t, uint32_t
9 #include "CanvasLayerComposite.h" // for CanvasLayerComposite
10 #include "ColorLayerComposite.h" // for ColorLayerComposite
11 #include "Composer2D.h" // for Composer2D
12 #include "CompositableHost.h" // for CompositableHost
13 #include "ContainerLayerComposite.h" // for ContainerLayerComposite, etc
14 #include "FPSCounter.h" // for FPSState, FPSCounter
15 #include "FrameMetrics.h" // for FrameMetrics
16 #include "GeckoProfiler.h" // for profiler_set_frame_number, etc
17 #include "ImageLayerComposite.h" // for ImageLayerComposite
18 #include "Layers.h" // for Layer, ContainerLayer, etc
19 #include "ThebesLayerComposite.h" // for ThebesLayerComposite
20 #include "TiledLayerBuffer.h" // for TiledLayerComposer
21 #include "Units.h" // for ScreenIntRect
22 #include "gfx2DGlue.h" // for ToMatrix4x4
23 #include "gfx3DMatrix.h" // for gfx3DMatrix
24 #include "gfxPrefs.h" // for gfxPrefs
25 #ifdef XP_MACOSX
26 #include "gfxPlatformMac.h"
27 #endif
28 #include "gfxRect.h" // for gfxRect
29 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
30 #include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef
31 #include "mozilla/gfx/2D.h" // for DrawTarget
32 #include "mozilla/gfx/Matrix.h" // for Matrix4x4
33 #include "mozilla/gfx/Point.h" // for IntSize, Point
34 #include "mozilla/gfx/Rect.h" // for Rect
35 #include "mozilla/gfx/Types.h" // for Color, SurfaceFormat
36 #include "mozilla/layers/Compositor.h" // for Compositor
37 #include "mozilla/layers/CompositorTypes.h"
38 #include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
39 #include "mozilla/layers/LayersTypes.h" // for etc
40 #include "ipc/ShadowLayerUtils.h"
41 #include "mozilla/mozalloc.h" // for operator new, etc
42 #include "nsAutoPtr.h" // for nsRefPtr
43 #include "nsCOMPtr.h" // for already_AddRefed
44 #include "nsDebug.h" // for NS_WARNING, NS_RUNTIMEABORT, etc
45 #include "nsISupportsImpl.h" // for Layer::AddRef, etc
46 #include "nsIWidget.h" // for nsIWidget
47 #include "nsPoint.h" // for nsIntPoint
48 #include "nsRect.h" // for nsIntRect
49 #include "nsRegion.h" // for nsIntRegion, etc
50 #ifdef MOZ_WIDGET_ANDROID
51 #include <android/log.h>
52 #endif
53 #include "GeckoProfiler.h"
54 #include "TextRenderer.h" // for TextRenderer
55
56 class gfxContext;
57 struct nsIntSize;
58
59
60 namespace mozilla {
61 namespace layers {
62
63 class ImageLayer;
64
65 using namespace mozilla::gfx;
66 using namespace mozilla::gl;
67
68 static LayerComposite*
69 ToLayerComposite(Layer* aLayer)
70 {
71 return static_cast<LayerComposite*>(aLayer->ImplData());
72 }
73
74 static void ClearSubtree(Layer* aLayer)
75 {
76 ToLayerComposite(aLayer)->CleanupResources();
77 for (Layer* child = aLayer->GetFirstChild(); child;
78 child = child->GetNextSibling()) {
79 ClearSubtree(child);
80 }
81 }
82
83 void
84 LayerManagerComposite::ClearCachedResources(Layer* aSubtree)
85 {
86 MOZ_ASSERT(!aSubtree || aSubtree->Manager() == this);
87 Layer* subtree = aSubtree ? aSubtree : mRoot.get();
88 if (!subtree) {
89 return;
90 }
91
92 ClearSubtree(subtree);
93 // FIXME [bjacob]
94 // XXX the old LayerManagerOGL code had a mMaybeInvalidTree that it set to true here.
95 // Do we need that?
96 }
97
98 /**
99 * LayerManagerComposite
100 */
101 LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
102 : mCompositor(aCompositor)
103 , mInTransaction(false)
104 , mIsCompositorReady(false)
105 , mDebugOverlayWantsNextFrame(false)
106 , mGeometryChanged(true)
107 {
108 mTextRenderer = new TextRenderer(aCompositor);
109 MOZ_ASSERT(aCompositor);
110 }
111
112 LayerManagerComposite::~LayerManagerComposite()
113 {
114 Destroy();
115 }
116
117
118 bool
119 LayerManagerComposite::Initialize()
120 {
121 bool result = mCompositor->Initialize();
122 return result;
123 }
124
125 void
126 LayerManagerComposite::Destroy()
127 {
128 if (!mDestroyed) {
129 mCompositor->GetWidget()->CleanupWindowEffects();
130 if (mRoot) {
131 RootLayer()->Destroy();
132 }
133 mRoot = nullptr;
134
135 mCompositor->Destroy();
136
137 mDestroyed = true;
138 }
139 }
140
141 void
142 LayerManagerComposite::UpdateRenderBounds(const nsIntRect& aRect)
143 {
144 mRenderBounds = aRect;
145 }
146
147 void
148 LayerManagerComposite::BeginTransaction()
149 {
150 mInTransaction = true;
151
152 if (!mCompositor->Ready()) {
153 return;
154 }
155
156 mIsCompositorReady = true;
157
158 if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL ||
159 Compositor::GetBackend() == LayersBackend::LAYERS_BASIC) {
160 mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot());
161 }
162 }
163
164 void
165 LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget)
166 {
167 mInTransaction = true;
168
169 if (!mCompositor->Ready()) {
170 return;
171 }
172
173 #ifdef MOZ_LAYERS_HAVE_LOG
174 MOZ_LAYERS_LOG(("[----- BeginTransaction"));
175 Log();
176 #endif
177
178 if (mDestroyed) {
179 NS_WARNING("Call on destroyed layer manager");
180 return;
181 }
182
183 mIsCompositorReady = true;
184 mCompositor->SetTargetContext(aTarget);
185 mTarget = aTarget;
186 }
187
188 bool
189 LayerManagerComposite::EndEmptyTransaction(EndTransactionFlags aFlags)
190 {
191 NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
192 if (!mRoot) {
193 mInTransaction = false;
194 mIsCompositorReady = false;
195 return false;
196 }
197
198 EndTransaction(nullptr, nullptr);
199 return true;
200 }
201
202 void
203 LayerManagerComposite::EndTransaction(DrawThebesLayerCallback aCallback,
204 void* aCallbackData,
205 EndTransactionFlags aFlags)
206 {
207 NS_ASSERTION(mInTransaction, "Didn't call BeginTransaction?");
208 NS_ASSERTION(!aCallback && !aCallbackData, "Not expecting callbacks here");
209 mInTransaction = false;
210
211 if (!mIsCompositorReady) {
212 return;
213 }
214 mIsCompositorReady = false;
215
216 #ifdef MOZ_LAYERS_HAVE_LOG
217 MOZ_LAYERS_LOG((" ----- (beginning paint)"));
218 Log();
219 #endif
220
221 if (mDestroyed) {
222 NS_WARNING("Call on destroyed layer manager");
223 return;
224 }
225
226 if (mRoot && mClonedLayerTreeProperties) {
227 nsIntRegion invalid =
228 mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr, &mGeometryChanged);
229 mClonedLayerTreeProperties = nullptr;
230
231 mInvalidRegion.Or(mInvalidRegion, invalid);
232 } else {
233 mInvalidRegion.Or(mInvalidRegion, mRenderBounds);
234 }
235
236 if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
237 if (aFlags & END_NO_COMPOSITE) {
238 // Apply pending tree updates before recomputing effective
239 // properties.
240 mRoot->ApplyPendingUpdatesToSubtree();
241 }
242
243 // The results of our drawing always go directly into a pixel buffer,
244 // so we don't need to pass any global transform here.
245 mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
246
247 Render();
248 mGeometryChanged = false;
249 }
250
251 mCompositor->SetTargetContext(nullptr);
252 mTarget = nullptr;
253
254 #ifdef MOZ_LAYERS_HAVE_LOG
255 Log();
256 MOZ_LAYERS_LOG(("]----- EndTransaction"));
257 #endif
258 }
259
260 TemporaryRef<DrawTarget>
261 LayerManagerComposite::CreateOptimalMaskDrawTarget(const IntSize &aSize)
262 {
263 NS_RUNTIMEABORT("Should only be called on the drawing side");
264 return nullptr;
265 }
266
267 already_AddRefed<ThebesLayer>
268 LayerManagerComposite::CreateThebesLayer()
269 {
270 NS_RUNTIMEABORT("Should only be called on the drawing side");
271 return nullptr;
272 }
273
274 already_AddRefed<ContainerLayer>
275 LayerManagerComposite::CreateContainerLayer()
276 {
277 NS_RUNTIMEABORT("Should only be called on the drawing side");
278 return nullptr;
279 }
280
281 already_AddRefed<ImageLayer>
282 LayerManagerComposite::CreateImageLayer()
283 {
284 NS_RUNTIMEABORT("Should only be called on the drawing side");
285 return nullptr;
286 }
287
288 already_AddRefed<ColorLayer>
289 LayerManagerComposite::CreateColorLayer()
290 {
291 NS_RUNTIMEABORT("Should only be called on the drawing side");
292 return nullptr;
293 }
294
295 already_AddRefed<CanvasLayer>
296 LayerManagerComposite::CreateCanvasLayer()
297 {
298 NS_RUNTIMEABORT("Should only be called on the drawing side");
299 return nullptr;
300 }
301
302 LayerComposite*
303 LayerManagerComposite::RootLayer() const
304 {
305 if (mDestroyed) {
306 NS_WARNING("Call on destroyed layer manager");
307 return nullptr;
308 }
309
310 return ToLayerComposite(mRoot);
311 }
312
313 // Size of the builtin font.
314 static const float FontHeight = 7.f;
315 static const float FontWidth = 4.f;
316 static const float FontStride = 4.f;
317
318 // Scale the font when drawing it to the viewport for better readability.
319 static const float FontScaleX = 2.f;
320 static const float FontScaleY = 3.f;
321
322 static void DrawDigits(unsigned int aValue,
323 int aOffsetX, int aOffsetY,
324 Compositor* aCompositor,
325 EffectChain& aEffectChain)
326 {
327 if (aValue > 999) {
328 aValue = 999;
329 }
330
331 unsigned int divisor = 100;
332 float textureWidth = FontWidth * 10;
333 gfx::Float opacity = 1;
334 gfx::Matrix4x4 transform;
335 transform.Scale(FontScaleX, FontScaleY, 1);
336
337 for (size_t n = 0; n < 3; ++n) {
338 unsigned int digit = aValue % (divisor * 10) / divisor;
339 divisor /= 10;
340
341 RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
342 texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
343
344 Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
345 Rect clipRect = Rect(0, 0, 300, 100);
346 aCompositor->DrawQuad(drawRect, clipRect,
347 aEffectChain, opacity, transform);
348 }
349 }
350
351 void FPSState::DrawFPS(TimeStamp aNow,
352 unsigned int aFillRatio,
353 Compositor* aCompositor)
354 {
355 if (!mFPSTextureSource) {
356 const char *text =
357 " "
358 " XXX XX XXX XXX X X XXX XXX XXX XXX XXX"
359 " X X X X X X X X X X X X X X"
360 " X X X XXX XXX XXX XXX XXX X XXX XXX"
361 " X X X X X X X X X X X X X"
362 " XXX XXX XXX XXX X XXX XXX X XXX X"
363 " ";
364
365 // Convert the text encoding above to RGBA.
366 int w = FontWidth * 10;
367 int h = FontHeight;
368 uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
369 for (int i = 0; i < h; i++) {
370 for (int j = 0; j < w; j++) {
371 uint32_t purple = 0xfff000ff;
372 uint32_t white = 0xffffffff;
373 buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
374 }
375 }
376
377 int bytesPerPixel = 4;
378 RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
379 reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
380 mFPSTextureSource = aCompositor->CreateDataTextureSource();
381 mFPSTextureSource->Update(fpsSurface);
382 }
383
384 EffectChain effectChain;
385 effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
386
387 unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
388 unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
389
390 DrawDigits(fps, 0, 0, aCompositor, effectChain);
391 DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain);
392 DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain);
393 }
394
395 static uint16_t sFrameCount = 0;
396 void
397 LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
398 {
399 if (gfxPrefs::LayersDrawFPS()) {
400 if (!mFPS) {
401 mFPS = new FPSState();
402 }
403
404 float fillRatio = mCompositor->GetFillRatio();
405 mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor);
406 } else {
407 mFPS = nullptr;
408 }
409
410 if (gfxPrefs::DrawFrameCounter()) {
411 profiler_set_frame_number(sFrameCount);
412
413 uint16_t frameNumber = sFrameCount;
414 const uint16_t bitWidth = 3;
415 float opacity = 1.0;
416 gfx::Rect clip(0,0, bitWidth*16, bitWidth);
417 for (size_t i = 0; i < 16; i++) {
418
419 gfx::Color bitColor;
420 if ((frameNumber >> i) & 0x1) {
421 bitColor = gfx::Color(0, 0, 0, 1.0);
422 } else {
423 bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
424 }
425 EffectChain effects;
426 effects.mPrimaryEffect = new EffectSolidColor(bitColor);
427 mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
428 clip,
429 effects,
430 opacity,
431 gfx::Matrix4x4());
432 }
433 // We intentionally overflow at 2^16.
434 sFrameCount++;
435 }
436 }
437
438 void
439 LayerManagerComposite::Render()
440 {
441 PROFILER_LABEL("LayerManagerComposite", "Render");
442 if (mDestroyed) {
443 NS_WARNING("Call on destroyed layer manager");
444 return;
445 }
446
447 if (gfxPrefs::LayersDump()) {
448 this->Dump();
449 }
450
451 /** Our more efficient but less powerful alter ego, if one is available. */
452 nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
453
454 if (!mTarget && composer2D && composer2D->TryRender(mRoot, mWorldMatrix, mGeometryChanged)) {
455 if (mFPS) {
456 double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
457 if (gfxPrefs::LayersDrawFPS()) {
458 printf_stderr("HWComposer: FPS is %g\n", fps);
459 }
460 }
461 mCompositor->EndFrameForExternalComposition(mWorldMatrix);
462 return;
463 }
464
465 {
466 PROFILER_LABEL("LayerManagerComposite", "PreRender");
467 if (!mCompositor->GetWidget()->PreRender(this)) {
468 return;
469 }
470 }
471
472 nsIntRect clipRect;
473 Rect bounds(mRenderBounds.x, mRenderBounds.y, mRenderBounds.width, mRenderBounds.height);
474 Rect actualBounds;
475 if (mRoot->GetClipRect()) {
476 clipRect = *mRoot->GetClipRect();
477 WorldTransformRect(clipRect);
478 Rect rect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
479 mCompositor->BeginFrame(mInvalidRegion, &rect, mWorldMatrix, bounds, nullptr, &actualBounds);
480 } else {
481 gfx::Rect rect;
482 mCompositor->BeginFrame(mInvalidRegion, nullptr, mWorldMatrix, bounds, &rect, &actualBounds);
483 clipRect = nsIntRect(rect.x, rect.y, rect.width, rect.height);
484 }
485
486 // Reset the invalid region now that we've begun compositing.
487 mInvalidRegion.SetEmpty();
488
489 if (actualBounds.IsEmpty()) {
490 mCompositor->GetWidget()->PostRender(this);
491 return;
492 }
493
494 // Allow widget to render a custom background.
495 mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
496 actualBounds.y,
497 actualBounds.width,
498 actualBounds.height));
499
500 // Render our layers.
501 RootLayer()->RenderLayer(clipRect);
502
503 if (!mRegionToClear.IsEmpty()) {
504 nsIntRegionRectIterator iter(mRegionToClear);
505 const nsIntRect *r;
506 while ((r = iter.Next())) {
507 mCompositor->ClearRect(Rect(r->x, r->y, r->width, r->height));
508 }
509 }
510
511 // Allow widget to render a custom foreground.
512 mCompositor->GetWidget()->DrawWindowOverlay(this, nsIntRect(actualBounds.x,
513 actualBounds.y,
514 actualBounds.width,
515 actualBounds.height));
516
517 // Debugging
518 RenderDebugOverlay(actualBounds);
519
520 {
521 PROFILER_LABEL("LayerManagerComposite", "EndFrame");
522 mCompositor->EndFrame();
523 mCompositor->SetFBAcquireFence(mRoot);
524 }
525
526 mCompositor->GetWidget()->PostRender(this);
527
528 RecordFrame();
529 }
530
531 void
532 LayerManagerComposite::SetWorldTransform(const gfx::Matrix& aMatrix)
533 {
534 NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
535 "SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
536 NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
537 "SetWorldTransform only accepts matrices with integer scale");
538
539 mWorldMatrix = aMatrix;
540 }
541
542 gfx::Matrix&
543 LayerManagerComposite::GetWorldTransform(void)
544 {
545 return mWorldMatrix;
546 }
547
548 void
549 LayerManagerComposite::WorldTransformRect(nsIntRect& aRect)
550 {
551 gfx::Rect grect(aRect.x, aRect.y, aRect.width, aRect.height);
552 grect = mWorldMatrix.TransformBounds(grect);
553 aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height());
554 }
555
556 static void
557 SubtractTransformedRegion(nsIntRegion& aRegion,
558 const nsIntRegion& aRegionToSubtract,
559 const gfx3DMatrix& aTransform)
560 {
561 if (aRegionToSubtract.IsEmpty()) {
562 return;
563 }
564
565 // For each rect in the region, find out its bounds in screen space and
566 // subtract it from the screen region.
567 nsIntRegionRectIterator it(aRegionToSubtract);
568 while (const nsIntRect* rect = it.Next()) {
569 gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect));
570 aRegion.Sub(aRegion, nsIntRect(incompleteRect.x,
571 incompleteRect.y,
572 incompleteRect.width,
573 incompleteRect.height));
574 }
575 }
576
577 /* static */ void
578 LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer,
579 nsIntRegion& aScreenRegion,
580 nsIntRegion& aLowPrecisionScreenRegion,
581 const gfx3DMatrix& aTransform)
582 {
583 if (aLayer->GetOpacity() <= 0.f ||
584 (aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) {
585 return;
586 }
587
588 // If the layer's a container, recurse into all of its children
589 ContainerLayer* container = aLayer->AsContainerLayer();
590 if (container) {
591 // Accumulate the transform of intermediate surfaces
592 gfx3DMatrix transform = aTransform;
593 if (container->UseIntermediateSurface()) {
594 gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform);
595 transform.PreMultiply(aTransform);
596 }
597 for (Layer* child = aLayer->GetFirstChild(); child;
598 child = child->GetNextSibling()) {
599 ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform);
600 }
601 return;
602 }
603
604 // Only thebes layers can be incomplete
605 ThebesLayer* thebesLayer = aLayer->AsThebesLayer();
606 if (!thebesLayer) {
607 return;
608 }
609
610 // See if there's any incomplete rendering
611 nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion();
612 incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion());
613
614 if (!incompleteRegion.IsEmpty()) {
615 // Calculate the transform to get between screen and layer space
616 gfx3DMatrix transformToScreen;
617 To3DMatrix(aLayer->GetEffectiveTransform(), transformToScreen);
618 transformToScreen.PreMultiply(aTransform);
619
620 SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen);
621
622 // See if there's any incomplete low-precision rendering
623 TiledLayerComposer* composer = nullptr;
624 LayerComposite* shadow = aLayer->AsLayerComposite();
625 if (shadow) {
626 composer = shadow->GetTiledLayerComposer();
627 if (composer) {
628 incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion());
629 if (!incompleteRegion.IsEmpty()) {
630 SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
631 }
632 }
633 }
634
635 // If we can't get a valid low precision region, assume it's the same as
636 // the high precision region.
637 if (!composer) {
638 SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
639 }
640 }
641 }
642
643 #ifdef MOZ_ANDROID_OMTC
644 static float
645 GetDisplayportCoverage(const CSSRect& aDisplayPort,
646 const gfx3DMatrix& aTransformToScreen,
647 const nsIntRect& aScreenRect)
648 {
649 gfxRect transformedDisplayport =
650 aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
651 aDisplayPort.y,
652 aDisplayPort.width,
653 aDisplayPort.height));
654 transformedDisplayport.RoundOut();
655 nsIntRect displayport = nsIntRect(transformedDisplayport.x,
656 transformedDisplayport.y,
657 transformedDisplayport.width,
658 transformedDisplayport.height);
659 if (!displayport.Contains(aScreenRect)) {
660 nsIntRegion coveredRegion;
661 coveredRegion.And(aScreenRect, displayport);
662 return coveredRegion.Area() / (float)(aScreenRect.width * aScreenRect.height);
663 }
664
665 return 1.0f;
666 }
667 #endif // MOZ_ANDROID_OMTC
668
669 float
670 LayerManagerComposite::ComputeRenderIntegrity()
671 {
672 // We only ever have incomplete rendering when progressive tiles are enabled.
673 Layer* root = GetRoot();
674 if (!gfxPrefs::UseProgressiveTilePainting() || !root) {
675 return 1.f;
676 }
677
678 const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
679 nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
680 rootMetrics.mCompositionBounds.y,
681 rootMetrics.mCompositionBounds.width,
682 rootMetrics.mCompositionBounds.height);
683
684 float lowPrecisionMultiplier = 1.0f;
685 float highPrecisionMultiplier = 1.0f;
686
687 #ifdef MOZ_ANDROID_OMTC
688 // Use the transform on the primary scrollable layer and its FrameMetrics
689 // to find out how much of the viewport the current displayport covers
690 Layer* primaryScrollable = GetPrimaryScrollableLayer();
691 if (primaryScrollable) {
692 // This is derived from the code in
693 // AsyncCompositionManager::TransformScrollableLayer
694 const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
695 gfx3DMatrix transform;
696 gfx::To3DMatrix(primaryScrollable->GetEffectiveTransform(), transform);
697 transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1);
698
699 // Clip the screen rect to the document bounds
700 gfxRect documentBounds =
701 transform.TransformBounds(gfxRect(metrics.mScrollableRect.x - metrics.GetScrollOffset().x,
702 metrics.mScrollableRect.y - metrics.GetScrollOffset().y,
703 metrics.mScrollableRect.width,
704 metrics.mScrollableRect.height));
705 documentBounds.RoundOut();
706 screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y,
707 documentBounds.width, documentBounds.height));
708
709 // If the screen rect is empty, the user has scrolled entirely into
710 // over-scroll and so we can be considered to have full integrity.
711 if (screenRect.IsEmpty()) {
712 return 1.0f;
713 }
714
715 // Work out how much of the critical display-port covers the screen
716 bool hasLowPrecision = false;
717 if (!metrics.mCriticalDisplayPort.IsEmpty()) {
718 hasLowPrecision = true;
719 highPrecisionMultiplier =
720 GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
721 }
722
723 // Work out how much of the display-port covers the screen
724 if (!metrics.mDisplayPort.IsEmpty()) {
725 if (hasLowPrecision) {
726 lowPrecisionMultiplier =
727 GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
728 } else {
729 lowPrecisionMultiplier = highPrecisionMultiplier =
730 GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
731 }
732 }
733 }
734
735 // If none of the screen is covered, we have zero integrity.
736 if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) {
737 return 0.0f;
738 }
739 #endif // MOZ_ANDROID_OMTC
740
741 nsIntRegion screenRegion(screenRect);
742 nsIntRegion lowPrecisionScreenRegion(screenRect);
743 gfx3DMatrix transform;
744 ComputeRenderIntegrityInternal(root, screenRegion,
745 lowPrecisionScreenRegion, transform);
746
747 if (!screenRegion.IsEqual(screenRect)) {
748 // Calculate the area of the region. All rects in an nsRegion are
749 // non-overlapping.
750 float screenArea = screenRect.width * screenRect.height;
751 float highPrecisionIntegrity = screenRegion.Area() / screenArea;
752 float lowPrecisionIntegrity = 1.f;
753 if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
754 lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea;
755 }
756
757 return ((highPrecisionIntegrity * highPrecisionMultiplier) +
758 (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2;
759 }
760
761 return 1.f;
762 }
763
764 already_AddRefed<ThebesLayerComposite>
765 LayerManagerComposite::CreateThebesLayerComposite()
766 {
767 if (mDestroyed) {
768 NS_WARNING("Call on destroyed layer manager");
769 return nullptr;
770 }
771 return nsRefPtr<ThebesLayerComposite>(new ThebesLayerComposite(this)).forget();
772 }
773
774 already_AddRefed<ContainerLayerComposite>
775 LayerManagerComposite::CreateContainerLayerComposite()
776 {
777 if (mDestroyed) {
778 NS_WARNING("Call on destroyed layer manager");
779 return nullptr;
780 }
781 return nsRefPtr<ContainerLayerComposite>(new ContainerLayerComposite(this)).forget();
782 }
783
784 already_AddRefed<ImageLayerComposite>
785 LayerManagerComposite::CreateImageLayerComposite()
786 {
787 if (mDestroyed) {
788 NS_WARNING("Call on destroyed layer manager");
789 return nullptr;
790 }
791 return nsRefPtr<ImageLayerComposite>(new ImageLayerComposite(this)).forget();
792 }
793
794 already_AddRefed<ColorLayerComposite>
795 LayerManagerComposite::CreateColorLayerComposite()
796 {
797 if (LayerManagerComposite::mDestroyed) {
798 NS_WARNING("Call on destroyed layer manager");
799 return nullptr;
800 }
801 return nsRefPtr<ColorLayerComposite>(new ColorLayerComposite(this)).forget();
802 }
803
804 already_AddRefed<CanvasLayerComposite>
805 LayerManagerComposite::CreateCanvasLayerComposite()
806 {
807 if (LayerManagerComposite::mDestroyed) {
808 NS_WARNING("Call on destroyed layer manager");
809 return nullptr;
810 }
811 return nsRefPtr<CanvasLayerComposite>(new CanvasLayerComposite(this)).forget();
812 }
813
814 already_AddRefed<RefLayerComposite>
815 LayerManagerComposite::CreateRefLayerComposite()
816 {
817 if (LayerManagerComposite::mDestroyed) {
818 NS_WARNING("Call on destroyed layer manager");
819 return nullptr;
820 }
821 return nsRefPtr<RefLayerComposite>(new RefLayerComposite(this)).forget();
822 }
823
824 LayerManagerComposite::AutoAddMaskEffect::AutoAddMaskEffect(Layer* aMaskLayer,
825 EffectChain& aEffects,
826 bool aIs3D)
827 : mCompositable(nullptr)
828 {
829 if (!aMaskLayer) {
830 return;
831 }
832
833 mCompositable = ToLayerComposite(aMaskLayer)->GetCompositableHost();
834 if (!mCompositable) {
835 NS_WARNING("Mask layer with no compositable host");
836 return;
837 }
838
839 if (!mCompositable->AddMaskEffect(aEffects, aMaskLayer->GetEffectiveTransform(), aIs3D)) {
840 mCompositable = nullptr;
841 }
842 }
843
844 LayerManagerComposite::AutoAddMaskEffect::~AutoAddMaskEffect()
845 {
846 if (!mCompositable) {
847 return;
848 }
849
850 mCompositable->RemoveMaskEffect();
851 }
852
853 TemporaryRef<DrawTarget>
854 LayerManagerComposite::CreateDrawTarget(const IntSize &aSize,
855 SurfaceFormat aFormat)
856 {
857 #ifdef XP_MACOSX
858 // We don't want to accelerate if the surface is too small which indicates
859 // that it's likely used for an icon/static image. We also don't want to
860 // accelerate anything that is above the maximum texture size of weakest gpu.
861 // Safari uses 5000 area as the minimum for acceleration, we decided 64^2 is more logical.
862 bool useAcceleration = aSize.width <= 4096 && aSize.height <= 4096 &&
863 aSize.width > 64 && aSize.height > 64 &&
864 gfxPlatformMac::GetPlatform()->UseAcceleratedCanvas();
865 if (useAcceleration) {
866 return Factory::CreateDrawTarget(BackendType::COREGRAPHICS_ACCELERATED,
867 aSize, aFormat);
868 }
869 #endif
870 return LayerManager::CreateDrawTarget(aSize, aFormat);
871 }
872
873 LayerComposite::LayerComposite(LayerManagerComposite *aManager)
874 : mCompositeManager(aManager)
875 , mCompositor(aManager->GetCompositor())
876 , mShadowOpacity(1.0)
877 , mUseShadowClipRect(false)
878 , mShadowTransformSetByAnimation(false)
879 , mDestroyed(false)
880 , mLayerComposited(false)
881 { }
882
883 LayerComposite::~LayerComposite()
884 {
885 }
886
887 void
888 LayerComposite::Destroy()
889 {
890 if (!mDestroyed) {
891 mDestroyed = true;
892 CleanupResources();
893 }
894 }
895
896 bool
897 LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize &aSize)
898 {
899 return mCompositor->CanUseCanvasLayerForSize(gfx::IntSize(aSize.width,
900 aSize.height));
901 }
902
903 void
904 LayerManagerComposite::NotifyShadowTreeTransaction()
905 {
906 if (mFPS) {
907 mFPS->NotifyShadowTreeTransaction();
908 }
909 }
910
911 #ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
912
913 /*static*/ bool
914 LayerManagerComposite::SupportsDirectTexturing()
915 {
916 return false;
917 }
918
919 /*static*/ void
920 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
921 {
922 }
923
924 #endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
925
926 } /* layers */
927 } /* mozilla */

mercurial