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/tiled_layer_impl.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/stringprintf.h" | |
9 #include "cc/append_quads_data.h" | |
10 #include "cc/base/math_util.h" | |
11 #include "cc/debug/debug_colors.h" | |
12 #include "cc/quad_sink.h" | |
13 #include "cc/quads/checkerboard_draw_quad.h" | |
14 #include "cc/quads/debug_border_draw_quad.h" | |
15 #include "cc/quads/solid_color_draw_quad.h" | |
16 #include "cc/quads/tile_draw_quad.h" | |
17 #include "cc/resources/layer_tiling_data.h" | |
18 #include "third_party/khronos/GLES2/gl2.h" | |
19 #include "third_party/skia/include/core/SkColor.h" | |
20 #include "ui/gfx/quad_f.h" | |
21 | |
22 namespace cc { | |
23 | |
24 // Temporary diagnostic. | |
25 static bool s_safe_to_delete_drawable_tile = false; | |
26 | |
27 class DrawableTile : public LayerTilingData::Tile { | |
28 public: | |
29 static scoped_ptr<DrawableTile> Create() { | |
30 return make_scoped_ptr(new DrawableTile()); | |
31 } | |
32 | |
33 virtual ~DrawableTile() { CHECK(s_safe_to_delete_drawable_tile); } | |
34 | |
35 ResourceProvider::ResourceId resource_id() const { return resource_id_; } | |
36 void set_resource_id(ResourceProvider::ResourceId resource_id) { | |
37 resource_id_ = resource_id; | |
38 } | |
39 bool contents_swizzled() { return contents_swizzled_; } | |
40 void set_contents_swizzled(bool contents_swizzled) { | |
41 contents_swizzled_ = contents_swizzled; | |
42 } | |
43 | |
44 private: | |
45 DrawableTile() : resource_id_(0), contents_swizzled_(false) {} | |
46 | |
47 ResourceProvider::ResourceId resource_id_; | |
48 bool contents_swizzled_; | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(DrawableTile); | |
51 }; | |
52 | |
53 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id) | |
54 : LayerImpl(tree_impl, id), skips_draw_(true) {} | |
55 | |
56 TiledLayerImpl::~TiledLayerImpl() { | |
57 s_safe_to_delete_drawable_tile = true; | |
58 if (tiler_) | |
59 tiler_->reset(); | |
60 s_safe_to_delete_drawable_tile = false; | |
61 } | |
62 | |
63 ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const { | |
64 // This function is only valid for single texture layers, e.g. masks. | |
65 DCHECK(tiler_); | |
66 DCHECK_EQ(tiler_->num_tiles_x(), 1); | |
67 DCHECK_EQ(tiler_->num_tiles_y(), 1); | |
68 | |
69 DrawableTile* tile = TileAt(0, 0); | |
70 ResourceProvider::ResourceId resource_id = tile ? tile->resource_id() : 0; | |
71 return resource_id; | |
72 } | |
73 | |
74 void TiledLayerImpl::DumpLayerProperties(std::string* str, int indent) const { | |
75 str->append(IndentString(indent)); | |
76 base::StringAppendF(str, "skipsDraw: %d\n", (!tiler_ || skips_draw_)); | |
77 LayerImpl::DumpLayerProperties(str, indent); | |
78 } | |
79 | |
80 bool TiledLayerImpl::HasTileAt(int i, int j) const { | |
81 return tiler_->TileAt(i, j); | |
82 } | |
83 | |
84 bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const { | |
85 return HasTileAt(i, j) && TileAt(i, j)->resource_id(); | |
86 } | |
87 | |
88 DrawableTile* TiledLayerImpl::TileAt(int i, int j) const { | |
89 return static_cast<DrawableTile*>(tiler_->TileAt(i, j)); | |
90 } | |
91 | |
92 DrawableTile* TiledLayerImpl::CreateTile(int i, int j) { | |
93 scoped_ptr<DrawableTile> tile(DrawableTile::Create()); | |
94 DrawableTile* added_tile = tile.get(); | |
95 tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j); | |
96 | |
97 // Temporary diagnostic checks. | |
98 CHECK(added_tile); | |
99 CHECK(TileAt(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()).PassAs<LayerImpl>(); | |
113 } | |
114 | |
115 void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) { | |
116 LayerImpl::PushPropertiesTo(layer); | |
117 | |
118 TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); | |
119 | |
120 tiled_layer->set_skips_draw(skips_draw_); | |
121 tiled_layer->SetTilingData(*tiler_); | |
122 | |
123 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); | |
124 iter != tiler_->tiles().end(); | |
125 ++iter) { | |
126 int i = iter->first.first; | |
127 int j = iter->first.second; | |
128 DrawableTile* tile = static_cast<DrawableTile*>(iter->second); | |
129 | |
130 tiled_layer->PushTileProperties(i, | |
131 j, | |
132 tile->resource_id(), | |
133 tile->opaque_rect(), | |
134 tile->contents_swizzled()); | |
135 } | |
136 } | |
137 | |
138 void TiledLayerImpl::AppendQuads(QuadSink* quad_sink, | |
139 AppendQuadsData* append_quads_data) { | |
140 gfx::Rect content_rect = visible_content_rect(); | |
141 | |
142 if (!tiler_ || tiler_->has_empty_bounds() || content_rect.IsEmpty()) | |
143 return; | |
144 | |
145 SharedQuadState* shared_quad_state = | |
146 quad_sink->UseSharedQuadState(CreateSharedQuadState()); | |
147 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); | |
148 | |
149 int left, top, right, bottom; | |
150 tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom); | |
151 | |
152 if (ShowDebugBorders()) { | |
153 for (int j = top; j <= bottom; ++j) { | |
154 for (int i = left; i <= right; ++i) { | |
155 DrawableTile* tile = TileAt(i, j); | |
156 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); | |
157 SkColor border_color; | |
158 float border_width; | |
159 | |
160 if (skips_draw_ || !tile || !tile->resource_id()) { | |
161 border_color = DebugColors::MissingTileBorderColor(); | |
162 border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); | |
163 } else { | |
164 border_color = DebugColors::HighResTileBorderColor(); | |
165 border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); | |
166 } | |
167 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = | |
168 DebugBorderDrawQuad::Create(); | |
169 debug_border_quad->SetNew( | |
170 shared_quad_state, tile_rect, border_color, border_width); | |
171 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), | |
172 append_quads_data); | |
173 } | |
174 } | |
175 } | |
176 | |
177 if (skips_draw_) | |
178 return; | |
179 | |
180 for (int j = top; j <= bottom; ++j) { | |
181 for (int i = left; i <= right; ++i) { | |
182 DrawableTile* tile = TileAt(i, j); | |
183 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); | |
184 gfx::Rect display_rect = tile_rect; | |
185 tile_rect.Intersect(content_rect); | |
186 | |
187 // Skip empty tiles. | |
188 if (tile_rect.IsEmpty()) | |
189 continue; | |
190 | |
191 if (!tile || !tile->resource_id()) { | |
192 if (DrawCheckerboardForMissingTiles()) { | |
193 SkColor checker_color; | |
194 if (ShowDebugBorders()) { | |
195 checker_color = | |
196 tile ? DebugColors::InvalidatedTileCheckerboardColor() | |
197 : DebugColors::EvictedTileCheckerboardColor(); | |
198 } else { | |
199 checker_color = DebugColors::DefaultCheckerboardColor(); | |
200 } | |
201 | |
202 scoped_ptr<CheckerboardDrawQuad> checkerboard_quad = | |
203 CheckerboardDrawQuad::Create(); | |
204 checkerboard_quad->SetNew( | |
205 shared_quad_state, tile_rect, checker_color); | |
206 if (quad_sink->Append(checkerboard_quad.PassAs<DrawQuad>(), | |
207 append_quads_data)) | |
208 append_quads_data->numMissingTiles++; | |
209 } else { | |
210 scoped_ptr<SolidColorDrawQuad> solid_color_quad = | |
211 SolidColorDrawQuad::Create(); | |
212 solid_color_quad->SetNew( | |
213 shared_quad_state, tile_rect, background_color()); | |
214 if (quad_sink->Append(solid_color_quad.PassAs<DrawQuad>(), | |
215 append_quads_data)) | |
216 append_quads_data->numMissingTiles++; | |
217 } | |
218 continue; | |
219 } | |
220 | |
221 gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : | |
222 gfx::IntersectRects(tile->opaque_rect(), content_rect); | |
223 | |
224 // Keep track of how the top left has moved, so the texture can be | |
225 // offset the same amount. | |
226 gfx::Vector2d display_offset = tile_rect.origin() - display_rect.origin(); | |
227 gfx::Vector2d texture_offset = | |
228 tiler_->texture_offset(i, j) + display_offset; | |
229 gfx::RectF tex_coord_rect = gfx::RectF(tile_rect.size()) + texture_offset; | |
230 | |
231 float tile_width = static_cast<float>(tiler_->tile_size().width()); | |
232 float tile_height = static_cast<float>(tiler_->tile_size().height()); | |
233 gfx::Size texture_size(tile_width, tile_height); | |
234 | |
235 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); | |
236 quad->SetNew(shared_quad_state, | |
237 tile_rect, | |
238 tile_opaque_rect, | |
239 tile->resource_id(), | |
240 tex_coord_rect, | |
241 texture_size, | |
242 tile->contents_swizzled()); | |
243 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
244 } | |
245 } | |
246 } | |
247 | |
248 void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) { | |
249 s_safe_to_delete_drawable_tile = true; | |
250 | |
251 if (tiler_) { | |
252 tiler_->reset(); | |
253 } else { | |
254 tiler_ = LayerTilingData::Create(tiler.tile_size(), | |
255 tiler.has_border_texels() | |
256 ? LayerTilingData::HAS_BORDER_TEXELS | |
257 : LayerTilingData::NO_BORDER_TEXELS); | |
258 } | |
259 *tiler_ = tiler; | |
260 | |
261 s_safe_to_delete_drawable_tile = false; | |
262 } | |
263 | |
264 void TiledLayerImpl::PushTileProperties( | |
265 int i, | |
266 int j, | |
267 ResourceProvider::ResourceId resource_id, | |
268 gfx::Rect opaque_rect, | |
269 bool contents_swizzled) { | |
270 DrawableTile* tile = TileAt(i, j); | |
271 if (!tile) | |
272 tile = CreateTile(i, j); | |
273 tile->set_resource_id(resource_id); | |
274 tile->set_opaque_rect(opaque_rect); | |
275 tile->set_contents_swizzled(contents_swizzled); | |
276 } | |
277 | |
278 void TiledLayerImpl::PushInvalidTile(int i, int j) { | |
279 DrawableTile* tile = TileAt(i, j); | |
280 if (!tile) | |
281 tile = CreateTile(i, j); | |
282 tile->set_resource_id(0); | |
283 tile->set_opaque_rect(gfx::Rect()); | |
284 tile->set_contents_swizzled(false); | |
285 } | |
286 | |
287 Region TiledLayerImpl::VisibleContentOpaqueRegion() const { | |
288 if (skips_draw_) | |
289 return Region(); | |
290 if (contents_opaque()) | |
291 return visible_content_rect(); | |
292 return tiler_->OpaqueRegionInContentRect(visible_content_rect()); | |
293 } | |
294 | |
295 void TiledLayerImpl::DidLoseOutputSurface() { | |
296 s_safe_to_delete_drawable_tile = true; | |
297 // Temporary diagnostic check. | |
298 CHECK(tiler_); | |
299 tiler_->reset(); | |
300 s_safe_to_delete_drawable_tile = false; | |
301 } | |
302 | |
303 const char* TiledLayerImpl::LayerTypeAsString() const { | |
304 return "ContentLayer"; | |
305 } | |
306 | |
307 } // namespace cc | |
OLD | NEW |