1 // Copyright 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/layers/content_layer.h"
6
7 #include "base/auto_reset.h"
8 #include "base/metrics/histogram.h"
9 #include "base/time/time.h"
10 #include "cc/layers/content_layer_client.h"
11 #include "cc/resources/bitmap_content_layer_updater.h"
12 #include "cc/resources/bitmap_skpicture_content_layer_updater.h"
13 #include "cc/resources/layer_painter.h"
14 #include "cc/trees/layer_tree_host.h"
15
16 namespace cc {
17
ContentLayerPainter(ContentLayerClient * client)18 ContentLayerPainter::ContentLayerPainter(ContentLayerClient* client)
19 : client_(client) {}
20
Create(ContentLayerClient * client)21 scoped_ptr<ContentLayerPainter> ContentLayerPainter::Create(
22 ContentLayerClient* client) {
23 return make_scoped_ptr(new ContentLayerPainter(client));
24 }
25
Paint(SkCanvas * canvas,gfx::Rect content_rect,gfx::RectF * opaque)26 void ContentLayerPainter::Paint(SkCanvas* canvas,
27 gfx::Rect content_rect,
28 gfx::RectF* opaque) {
29 base::TimeTicks paint_start = base::TimeTicks::HighResNow();
30 client_->PaintContents(canvas, content_rect, opaque);
31 base::TimeTicks paint_end = base::TimeTicks::HighResNow();
32 // The start and end times might be the same if the paint was very fast or if
33 // our timer granularity is poor. Treat this as a very short time duration
34 // instead of none to avoid dividing by zero.
35 if (paint_end == paint_start)
36 paint_end += base::TimeDelta::FromMicroseconds(1);
37
38 double pixels_per_sec = (content_rect.width() * content_rect.height()) /
39 (paint_end - paint_start).InSecondsF();
40 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.AccelContentPaintDurationMS",
41 (paint_end - paint_start).InMilliseconds(),
42 0,
43 120,
44 30);
45 UMA_HISTOGRAM_CUSTOM_COUNTS("Renderer4.AccelContentPaintMegapixPerSecond",
46 pixels_per_sec / 1000000,
47 10,
48 210,
49 30);
50 }
51
Create(ContentLayerClient * client)52 scoped_refptr<ContentLayer> ContentLayer::Create(ContentLayerClient* client) {
53 return make_scoped_refptr(new ContentLayer(client));
54 }
55
ContentLayer(ContentLayerClient * client)56 ContentLayer::ContentLayer(ContentLayerClient* client)
57 : TiledLayer(),
58 client_(client),
59 can_use_lcd_text_last_frame_(can_use_lcd_text()) {
60 }
61
~ContentLayer()62 ContentLayer::~ContentLayer() {}
63
DrawsContent() const64 bool ContentLayer::DrawsContent() const {
65 return TiledLayer::DrawsContent() && client_;
66 }
67
SetLayerTreeHost(LayerTreeHost * host)68 void ContentLayer::SetLayerTreeHost(LayerTreeHost* host) {
69 TiledLayer::SetLayerTreeHost(host);
70
71 if (!updater_.get())
72 return;
73
74 if (host) {
75 updater_->set_rendering_stats_instrumentation(
76 host->rendering_stats_instrumentation());
77 } else {
78 updater_->set_rendering_stats_instrumentation(NULL);
79 }
80 }
81
SetTexturePriorities(const PriorityCalculator & priority_calc)82 void ContentLayer::SetTexturePriorities(
83 const PriorityCalculator& priority_calc) {
84 // Update the tile data before creating all the layer's tiles.
85 UpdateTileSizeAndTilingOption();
86
87 TiledLayer::SetTexturePriorities(priority_calc);
88 }
89
Update(ResourceUpdateQueue * queue,const OcclusionTracker * occlusion)90 bool ContentLayer::Update(ResourceUpdateQueue* queue,
91 const OcclusionTracker* occlusion) {
92 {
93 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
94 true);
95
96 CreateUpdaterIfNeeded();
97 UpdateCanUseLCDText();
98 }
99
100 bool updated = TiledLayer::Update(queue, occlusion);
101 return updated;
102 }
103
NeedMoreUpdates()104 bool ContentLayer::NeedMoreUpdates() {
105 return NeedsIdlePaint();
106 }
107
Updater() const108 LayerUpdater* ContentLayer::Updater() const {
109 return updater_.get();
110 }
111
CreateUpdaterIfNeeded()112 void ContentLayer::CreateUpdaterIfNeeded() {
113 if (updater_.get())
114 return;
115 scoped_ptr<LayerPainter> painter =
116 ContentLayerPainter::Create(client_).PassAs<LayerPainter>();
117 if (layer_tree_host()->settings().per_tile_painting_enabled) {
118 updater_ = BitmapSkPictureContentLayerUpdater::Create(
119 painter.Pass(),
120 rendering_stats_instrumentation(),
121 id());
122 } else {
123 updater_ = BitmapContentLayerUpdater::Create(
124 painter.Pass(),
125 rendering_stats_instrumentation(),
126 id());
127 }
128 updater_->SetOpaque(contents_opaque());
129
130 SetTextureFormat(
131 layer_tree_host()->GetRendererCapabilities().best_texture_format);
132 }
133
SetContentsOpaque(bool opaque)134 void ContentLayer::SetContentsOpaque(bool opaque) {
135 Layer::SetContentsOpaque(opaque);
136 if (updater_.get())
137 updater_->SetOpaque(opaque);
138 }
139
UpdateCanUseLCDText()140 void ContentLayer::UpdateCanUseLCDText() {
141 if (can_use_lcd_text_last_frame_ == can_use_lcd_text())
142 return;
143
144 can_use_lcd_text_last_frame_ = can_use_lcd_text();
145 if (client_)
146 client_->DidChangeLayerCanUseLCDText();
147 }
148
SupportsLCDText() const149 bool ContentLayer::SupportsLCDText() const {
150 return true;
151 }
152
GetPicture() const153 skia::RefPtr<SkPicture> ContentLayer::GetPicture() const {
154 if (!DrawsContent())
155 return skia::RefPtr<SkPicture>();
156
157 int width = bounds().width();
158 int height = bounds().height();
159 gfx::RectF opaque;
160
161 skia::RefPtr<SkPicture> picture = skia::AdoptRef(new SkPicture);
162 SkCanvas* canvas = picture->beginRecording(width, height);
163 client_->PaintContents(canvas, gfx::Rect(width, height), &opaque);
164 picture->endRecording();
165 return picture;
166 }
167
OnOutputSurfaceCreated()168 void ContentLayer::OnOutputSurfaceCreated() {
169 SetTextureFormat(
170 layer_tree_host()->GetRendererCapabilities().best_texture_format);
171 TiledLayer::OnOutputSurfaceCreated();
172 }
173
174 } // namespace cc
175