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 "PaintedLayerComposite.h"
8 #include "CompositableHost.h"            // for TiledLayerProperties, etc
9 #include "FrameMetrics.h"                // for FrameMetrics
10 #include "Units.h"                       // for CSSRect, LayerPixel, etc
11 #include "gfxEnv.h"                      // for gfxEnv
12 #include "mozilla/Assertions.h"          // for MOZ_ASSERT, etc
13 #include "mozilla/gfx/Matrix.h"          // for Matrix4x4
14 #include "mozilla/gfx/Point.h"           // for Point
15 #include "mozilla/gfx/Polygon.h"         // for Polygon
16 #include "mozilla/gfx/Rect.h"            // for RoundedToInt, Rect
17 #include "mozilla/gfx/Types.h"           // for SamplingFilter::LINEAR
18 #include "mozilla/layers/Compositor.h"   // for Compositor
19 #include "mozilla/layers/ContentHost.h"  // for ContentHost
20 #include "mozilla/layers/Effects.h"      // for EffectChain
21 #include "mozilla/mozalloc.h"            // for operator delete
22 #include "nsAString.h"
23 #include "mozilla/RefPtr.h"   // for nsRefPtr
24 #include "nsISupportsImpl.h"  // for MOZ_COUNT_CTOR, etc
25 #include "nsMathUtils.h"      // for NS_lround
26 #include "nsString.h"         // for nsAutoCString
27 #include "TextRenderer.h"
28 #include "GeckoProfiler.h"
29 
30 namespace mozilla {
31 namespace layers {
32 
PaintedLayerComposite(LayerManagerComposite * aManager)33 PaintedLayerComposite::PaintedLayerComposite(LayerManagerComposite* aManager)
34     : PaintedLayer(aManager, nullptr),
35       LayerComposite(aManager),
36       mBuffer(nullptr) {
37   MOZ_COUNT_CTOR(PaintedLayerComposite);
38   mImplData = static_cast<LayerComposite*>(this);
39 }
40 
~PaintedLayerComposite()41 PaintedLayerComposite::~PaintedLayerComposite() {
42   MOZ_COUNT_DTOR(PaintedLayerComposite);
43   CleanupResources();
44 }
45 
SetCompositableHost(CompositableHost * aHost)46 bool PaintedLayerComposite::SetCompositableHost(CompositableHost* aHost) {
47   switch (aHost->GetType()) {
48     case CompositableType::CONTENT_TILED:
49     case CompositableType::CONTENT_SINGLE:
50     case CompositableType::CONTENT_DOUBLE: {
51       ContentHost* newBuffer = static_cast<ContentHost*>(aHost);
52       if (mBuffer && newBuffer != mBuffer) {
53         mBuffer->Detach(this);
54       }
55       mBuffer = newBuffer;
56       return true;
57     }
58     default:
59       return false;
60   }
61 }
62 
Disconnect()63 void PaintedLayerComposite::Disconnect() { Destroy(); }
64 
Destroy()65 void PaintedLayerComposite::Destroy() {
66   if (!mDestroyed) {
67     CleanupResources();
68     mDestroyed = true;
69   }
70 }
71 
GetLayer()72 Layer* PaintedLayerComposite::GetLayer() { return this; }
73 
SetLayerManager(HostLayerManager * aManager)74 void PaintedLayerComposite::SetLayerManager(HostLayerManager* aManager) {
75   LayerComposite::SetLayerManager(aManager);
76   mManager = aManager;
77   if (mBuffer && mCompositor) {
78     mBuffer->SetTextureSourceProvider(mCompositor);
79   }
80 }
81 
RenderLayer(const gfx::IntRect & aClipRect,const Maybe<gfx::Polygon> & aGeometry)82 void PaintedLayerComposite::RenderLayer(const gfx::IntRect& aClipRect,
83                                         const Maybe<gfx::Polygon>& aGeometry) {
84   if (!mBuffer || !mBuffer->IsAttached()) {
85     return;
86   }
87   AUTO_PROFILER_LABEL("PaintedLayerComposite::RenderLayer", GRAPHICS);
88 
89   Compositor* compositor = mCompositeManager->GetCompositor();
90 
91   MOZ_ASSERT(mBuffer->GetTextureSourceProvider() == compositor &&
92                  mBuffer->GetLayer() == this,
93              "buffer is corrupted");
94 
95   const nsIntRegion visibleRegion = GetLocalVisibleRegion().ToUnknownRegion();
96 
97 #ifdef MOZ_DUMP_PAINTING
98   if (gfxEnv::DumpCompositorTextures()) {
99     RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface();
100     if (surf) {
101       WriteSnapshotToDumpFile(this, surf);
102     }
103   }
104 #endif
105 
106   RenderWithAllMasks(
107       this, compositor, aClipRect,
108       [&](EffectChain& effectChain, const gfx::IntRect& clipRect) {
109         mBuffer->SetPaintWillResample(MayResample());
110 
111         mBuffer->Composite(compositor, this, effectChain, GetEffectiveOpacity(),
112                            GetEffectiveTransform(), GetSamplingFilter(),
113                            clipRect, &visibleRegion, aGeometry);
114       });
115 
116   mBuffer->BumpFlashCounter();
117 
118   compositor->MakeCurrent();
119 }
120 
GetCompositableHost()121 CompositableHost* PaintedLayerComposite::GetCompositableHost() {
122   if (mBuffer && mBuffer->IsAttached()) {
123     return mBuffer.get();
124   }
125 
126   return nullptr;
127 }
128 
CleanupResources()129 void PaintedLayerComposite::CleanupResources() {
130   if (mBuffer) {
131     mBuffer->Detach(this);
132   }
133   mBuffer = nullptr;
134 }
135 
IsOpaque()136 bool PaintedLayerComposite::IsOpaque() {
137   if (!mBuffer || !mBuffer->IsAttached()) {
138     return false;
139   }
140   return PaintedLayer::IsOpaque();
141 }
142 
GenEffectChain(EffectChain & aEffect)143 void PaintedLayerComposite::GenEffectChain(EffectChain& aEffect) {
144   aEffect.mLayerRef = this;
145   aEffect.mPrimaryEffect = mBuffer->GenEffect(GetSamplingFilter());
146 }
147 
PrintInfo(std::stringstream & aStream,const char * aPrefix)148 void PaintedLayerComposite::PrintInfo(std::stringstream& aStream,
149                                       const char* aPrefix) {
150   PaintedLayer::PrintInfo(aStream, aPrefix);
151   if (mBuffer && mBuffer->IsAttached()) {
152     aStream << "\n";
153     nsAutoCString pfx(aPrefix);
154     pfx += "  ";
155     mBuffer->PrintInfo(aStream, pfx.get());
156   }
157 }
158 
GetInvalidRegion()159 const gfx::TiledIntRegion& PaintedLayerComposite::GetInvalidRegion() {
160   if (mBuffer) {
161     nsIntRegion region = mInvalidRegion.GetRegion();
162     mBuffer->AddAnimationInvalidation(region);
163   }
164   return mInvalidRegion;
165 }
166 
167 }  // namespace layers
168 }  // namespace mozilla
169