OLD | NEW |
| (Empty) |
1 // Copyright 2011 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/tiled_layer_impl.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/strings/stringprintf.h" | |
9 #include "base/trace_event/trace_event_argument.h" | |
10 #include "cc/base/math_util.h" | |
11 #include "cc/base/simple_enclosed_region.h" | |
12 #include "cc/debug/debug_colors.h" | |
13 #include "cc/layers/append_quads_data.h" | |
14 #include "cc/quads/checkerboard_draw_quad.h" | |
15 #include "cc/quads/debug_border_draw_quad.h" | |
16 #include "cc/quads/solid_color_draw_quad.h" | |
17 #include "cc/quads/tile_draw_quad.h" | |
18 #include "cc/resources/layer_tiling_data.h" | |
19 #include "cc/trees/occlusion.h" | |
20 #include "third_party/skia/include/core/SkColor.h" | |
21 #include "ui/gfx/geometry/quad_f.h" | |
22 | |
23 namespace cc { | |
24 | |
25 class DrawableTile : public LayerTilingData::Tile { | |
26 public: | |
27 static scoped_ptr<DrawableTile> Create() { | |
28 return make_scoped_ptr(new DrawableTile()); | |
29 } | |
30 | |
31 ResourceProvider::ResourceId resource_id() const { return resource_id_; } | |
32 void set_resource_id(ResourceProvider::ResourceId resource_id) { | |
33 resource_id_ = resource_id; | |
34 } | |
35 bool contents_swizzled() { return contents_swizzled_; } | |
36 void set_contents_swizzled(bool contents_swizzled) { | |
37 contents_swizzled_ = contents_swizzled; | |
38 } | |
39 | |
40 private: | |
41 DrawableTile() : resource_id_(0), contents_swizzled_(false) {} | |
42 | |
43 ResourceProvider::ResourceId resource_id_; | |
44 bool contents_swizzled_; | |
45 | |
46 DISALLOW_COPY_AND_ASSIGN(DrawableTile); | |
47 }; | |
48 | |
49 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id) | |
50 : TiledLayerImpl(tree_impl, id, new LayerImpl::SyncedScrollOffset) { | |
51 } | |
52 | |
53 TiledLayerImpl::TiledLayerImpl( | |
54 LayerTreeImpl* tree_impl, | |
55 int id, | |
56 scoped_refptr<LayerImpl::SyncedScrollOffset> synced_scroll_offset) | |
57 : LayerImpl(tree_impl, id, synced_scroll_offset), skips_draw_(true) { | |
58 } | |
59 | |
60 TiledLayerImpl::~TiledLayerImpl() { | |
61 } | |
62 | |
63 void TiledLayerImpl::GetContentsResourceId( | |
64 ResourceProvider::ResourceId* resource_id, | |
65 gfx::Size* resource_size) const { | |
66 // This function is only valid for single texture layers, e.g. masks. | |
67 DCHECK(tiler_); | |
68 // It's possible the mask layer is created but has no size or otherwise | |
69 // can't draw. | |
70 if (tiler_->num_tiles_x() == 0 || tiler_->num_tiles_y() == 0) { | |
71 *resource_id = 0; | |
72 return; | |
73 } | |
74 | |
75 // Any other number of tiles other than 0 or 1 is incorrect for masks. | |
76 DCHECK_EQ(tiler_->num_tiles_x(), 1); | |
77 DCHECK_EQ(tiler_->num_tiles_y(), 1); | |
78 | |
79 DrawableTile* tile = TileAt(0, 0); | |
80 *resource_id = tile ? tile->resource_id() : 0; | |
81 *resource_size = tiler_->tile_size(); | |
82 } | |
83 | |
84 bool TiledLayerImpl::HasTileAt(int i, int j) const { | |
85 return !!tiler_->TileAt(i, j); | |
86 } | |
87 | |
88 bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const { | |
89 return HasTileAt(i, j) && TileAt(i, j)->resource_id(); | |
90 } | |
91 | |
92 DrawableTile* TiledLayerImpl::TileAt(int i, int j) const { | |
93 return static_cast<DrawableTile*>(tiler_->TileAt(i, j)); | |
94 } | |
95 | |
96 DrawableTile* TiledLayerImpl::CreateTile(int i, int j) { | |
97 scoped_ptr<DrawableTile> tile(DrawableTile::Create()); | |
98 DrawableTile* added_tile = tile.get(); | |
99 tiler_->AddTile(tile.Pass(), i, j); | |
100 | |
101 return added_tile; | |
102 } | |
103 | |
104 void TiledLayerImpl::GetDebugBorderProperties(SkColor* color, | |
105 float* width) const { | |
106 *color = DebugColors::TiledContentLayerBorderColor(); | |
107 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); | |
108 } | |
109 | |
110 scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl( | |
111 LayerTreeImpl* tree_impl) { | |
112 return TiledLayerImpl::Create(tree_impl, id(), synced_scroll_offset()); | |
113 } | |
114 | |
115 void TiledLayerImpl::AsValueInto(base::trace_event::TracedValue* state) const { | |
116 LayerImpl::AsValueInto(state); | |
117 MathUtil::AddToTracedValue("invalidation", update_rect(), state); | |
118 } | |
119 | |
120 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const { | |
121 size_t amount = 0; | |
122 const size_t kMemoryUsagePerTileInBytes = | |
123 4 * tiler_->tile_size().width() * tiler_->tile_size().height(); | |
124 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); | |
125 iter != tiler_->tiles().end(); | |
126 ++iter) { | |
127 const DrawableTile* tile = static_cast<DrawableTile*>(iter->second); | |
128 DCHECK(tile); | |
129 if (!tile->resource_id()) | |
130 continue; | |
131 amount += kMemoryUsagePerTileInBytes; | |
132 } | |
133 return amount; | |
134 } | |
135 | |
136 void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) { | |
137 LayerImpl::PushPropertiesTo(layer); | |
138 | |
139 TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); | |
140 | |
141 tiled_layer->set_skips_draw(skips_draw_); | |
142 tiled_layer->SetTilingData(*tiler_); | |
143 | |
144 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); | |
145 iter != tiler_->tiles().end(); | |
146 ++iter) { | |
147 int i = iter->first.first; | |
148 int j = iter->first.second; | |
149 DrawableTile* tile = static_cast<DrawableTile*>(iter->second); | |
150 DCHECK(tile); | |
151 tiled_layer->PushTileProperties(i, | |
152 j, | |
153 tile->resource_id(), | |
154 tile->contents_swizzled()); | |
155 } | |
156 } | |
157 | |
158 bool TiledLayerImpl::WillDraw(DrawMode draw_mode, | |
159 ResourceProvider* resource_provider) { | |
160 if (!tiler_ || tiler_->has_empty_bounds() || | |
161 visible_content_rect().IsEmpty() || | |
162 draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE) | |
163 return false; | |
164 return LayerImpl::WillDraw(draw_mode, resource_provider); | |
165 } | |
166 | |
167 void TiledLayerImpl::AppendQuads(RenderPass* render_pass, | |
168 AppendQuadsData* append_quads_data) { | |
169 DCHECK(tiler_); | |
170 DCHECK(!tiler_->has_empty_bounds()); | |
171 DCHECK(!visible_content_rect().IsEmpty()); | |
172 | |
173 gfx::Rect content_rect = visible_content_rect(); | |
174 SharedQuadState* shared_quad_state = | |
175 render_pass->CreateAndAppendSharedQuadState(); | |
176 PopulateSharedQuadState(shared_quad_state); | |
177 | |
178 AppendDebugBorderQuad( | |
179 render_pass, content_bounds(), shared_quad_state, append_quads_data); | |
180 | |
181 int left, top, right, bottom; | |
182 tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom); | |
183 | |
184 if (ShowDebugBorders()) { | |
185 for (int j = top; j <= bottom; ++j) { | |
186 for (int i = left; i <= right; ++i) { | |
187 DrawableTile* tile = TileAt(i, j); | |
188 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); | |
189 gfx::Rect visible_tile_rect = tile_rect; | |
190 SkColor border_color; | |
191 float border_width; | |
192 | |
193 if (skips_draw_ || !tile || !tile->resource_id()) { | |
194 border_color = DebugColors::MissingTileBorderColor(); | |
195 border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); | |
196 } else { | |
197 border_color = DebugColors::HighResTileBorderColor(); | |
198 border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); | |
199 } | |
200 DebugBorderDrawQuad* debug_border_quad = | |
201 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); | |
202 debug_border_quad->SetNew(shared_quad_state, | |
203 tile_rect, | |
204 visible_tile_rect, | |
205 border_color, | |
206 border_width); | |
207 } | |
208 } | |
209 } | |
210 | |
211 if (skips_draw_) | |
212 return; | |
213 | |
214 for (int j = top; j <= bottom; ++j) { | |
215 for (int i = left; i <= right; ++i) { | |
216 DrawableTile* tile = TileAt(i, j); | |
217 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); | |
218 gfx::Rect display_rect = tile_rect; | |
219 tile_rect.Intersect(content_rect); | |
220 | |
221 // Skip empty tiles. | |
222 if (tile_rect.IsEmpty()) | |
223 continue; | |
224 | |
225 gfx::Rect visible_tile_rect = | |
226 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
227 tile_rect); | |
228 if (visible_tile_rect.IsEmpty()) | |
229 continue; | |
230 | |
231 if (!tile || !tile->resource_id()) { | |
232 SkColor checker_color; | |
233 if (ShowDebugBorders()) { | |
234 checker_color = | |
235 tile ? DebugColors::InvalidatedTileCheckerboardColor() | |
236 : DebugColors::EvictedTileCheckerboardColor(); | |
237 } else { | |
238 checker_color = DebugColors::DefaultCheckerboardColor(); | |
239 } | |
240 | |
241 CheckerboardDrawQuad* checkerboard_quad = | |
242 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); | |
243 checkerboard_quad->SetNew(shared_quad_state, tile_rect, | |
244 visible_tile_rect, checker_color, 1.f); | |
245 append_quads_data->num_missing_tiles++; | |
246 continue; | |
247 } | |
248 | |
249 gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : gfx::Rect(); | |
250 | |
251 // Keep track of how the top left has moved, so the texture can be | |
252 // offset the same amount. | |
253 gfx::Vector2d display_offset = tile_rect.origin() - display_rect.origin(); | |
254 gfx::Vector2d texture_offset = | |
255 tiler_->texture_offset(i, j) + display_offset; | |
256 gfx::RectF tex_coord_rect = gfx::RectF(tile_rect.size()) + texture_offset; | |
257 | |
258 float tile_width = static_cast<float>(tiler_->tile_size().width()); | |
259 float tile_height = static_cast<float>(tiler_->tile_size().height()); | |
260 gfx::Size texture_size(tile_width, tile_height); | |
261 | |
262 TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); | |
263 quad->SetNew(shared_quad_state, | |
264 tile_rect, | |
265 tile_opaque_rect, | |
266 visible_tile_rect, | |
267 tile->resource_id(), | |
268 tex_coord_rect, | |
269 texture_size, | |
270 tile->contents_swizzled(), | |
271 false); | |
272 } | |
273 } | |
274 } | |
275 | |
276 void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) { | |
277 if (tiler_) { | |
278 tiler_->reset(); | |
279 } else { | |
280 tiler_ = LayerTilingData::Create(tiler.tile_size(), | |
281 tiler.has_border_texels() | |
282 ? LayerTilingData::HAS_BORDER_TEXELS | |
283 : LayerTilingData::NO_BORDER_TEXELS); | |
284 } | |
285 *tiler_ = tiler; | |
286 } | |
287 | |
288 void TiledLayerImpl::PushTileProperties( | |
289 int i, | |
290 int j, | |
291 ResourceProvider::ResourceId resource_id, | |
292 bool contents_swizzled) { | |
293 DrawableTile* tile = TileAt(i, j); | |
294 if (!tile) | |
295 tile = CreateTile(i, j); | |
296 tile->set_resource_id(resource_id); | |
297 tile->set_contents_swizzled(contents_swizzled); | |
298 } | |
299 | |
300 void TiledLayerImpl::PushInvalidTile(int i, int j) { | |
301 DrawableTile* tile = TileAt(i, j); | |
302 if (!tile) | |
303 tile = CreateTile(i, j); | |
304 tile->set_resource_id(0); | |
305 tile->set_contents_swizzled(false); | |
306 } | |
307 | |
308 SimpleEnclosedRegion TiledLayerImpl::VisibleContentOpaqueRegion() const { | |
309 if (skips_draw_) | |
310 return SimpleEnclosedRegion(); | |
311 return LayerImpl::VisibleContentOpaqueRegion(); | |
312 } | |
313 | |
314 void TiledLayerImpl::ReleaseResources() { | |
315 tiler_->reset(); | |
316 } | |
317 | |
318 const char* TiledLayerImpl::LayerTypeAsString() const { | |
319 return "cc::TiledLayerImpl"; | |
320 } | |
321 | |
322 } // namespace cc | |
OLD | NEW |