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