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.
5 #include "cc/layers/tiled_layer_impl.h"
7 #include "base/basictypes.h"
8 #include "base/debug/trace_event_argument.h"
9 #include "base/strings/stringprintf.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_tracker.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "third_party/skia/include/core/SkColor.h"
22 #include "ui/gfx/quad_f.h"
26 class DrawableTile : public LayerTilingData::Tile {
28 static scoped_ptr<DrawableTile> Create() {
29 return make_scoped_ptr(new DrawableTile());
32 ResourceProvider::ResourceId resource_id() const { return resource_id_; }
33 void set_resource_id(ResourceProvider::ResourceId resource_id) {
34 resource_id_ = resource_id;
36 bool contents_swizzled() { return contents_swizzled_; }
37 void set_contents_swizzled(bool contents_swizzled) {
38 contents_swizzled_ = contents_swizzled;
42 DrawableTile() : resource_id_(0), contents_swizzled_(false) {}
44 ResourceProvider::ResourceId resource_id_;
45 bool contents_swizzled_;
47 DISALLOW_COPY_AND_ASSIGN(DrawableTile);
50 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id)
51 : LayerImpl(tree_impl, id), skips_draw_(true) {}
53 TiledLayerImpl::~TiledLayerImpl() {
56 ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const {
57 // This function is only valid for single texture layers, e.g. masks.
59 // It's possible the mask layer is created but has no size or otherwise
61 if (tiler_->num_tiles_x() == 0 || tiler_->num_tiles_y() == 0)
64 // Any other number of tiles other than 0 or 1 is incorrect for masks.
65 DCHECK_EQ(tiler_->num_tiles_x(), 1);
66 DCHECK_EQ(tiler_->num_tiles_y(), 1);
68 DrawableTile* tile = TileAt(0, 0);
69 ResourceProvider::ResourceId resource_id = tile ? tile->resource_id() : 0;
73 bool TiledLayerImpl::HasTileAt(int i, int j) const {
74 return !!tiler_->TileAt(i, j);
77 bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const {
78 return HasTileAt(i, j) && TileAt(i, j)->resource_id();
81 DrawableTile* TiledLayerImpl::TileAt(int i, int j) const {
82 return static_cast<DrawableTile*>(tiler_->TileAt(i, j));
85 DrawableTile* TiledLayerImpl::CreateTile(int i, int j) {
86 scoped_ptr<DrawableTile> tile(DrawableTile::Create());
87 DrawableTile* added_tile = tile.get();
88 tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
93 void TiledLayerImpl::GetDebugBorderProperties(SkColor* color,
95 *color = DebugColors::TiledContentLayerBorderColor();
96 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
99 scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl(
100 LayerTreeImpl* tree_impl) {
101 return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
104 void TiledLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
105 LayerImpl::AsValueInto(state);
106 state->BeginArray("invalidation");
107 MathUtil::AddToTracedValue(update_rect(), state);
111 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
113 const size_t kMemoryUsagePerTileInBytes =
114 4 * tiler_->tile_size().width() * tiler_->tile_size().height();
115 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
116 iter != tiler_->tiles().end();
118 const DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
120 if (!tile->resource_id())
122 amount += kMemoryUsagePerTileInBytes;
127 void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) {
128 LayerImpl::PushPropertiesTo(layer);
130 TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);
132 tiled_layer->set_skips_draw(skips_draw_);
133 tiled_layer->SetTilingData(*tiler_);
135 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
136 iter != tiler_->tiles().end();
138 int i = iter->first.first;
139 int j = iter->first.second;
140 DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
142 tiled_layer->PushTileProperties(i,
145 tile->contents_swizzled());
149 bool TiledLayerImpl::WillDraw(DrawMode draw_mode,
150 ResourceProvider* resource_provider) {
151 if (!tiler_ || tiler_->has_empty_bounds() ||
152 visible_content_rect().IsEmpty() ||
153 draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
155 return LayerImpl::WillDraw(draw_mode, resource_provider);
158 void TiledLayerImpl::AppendQuads(
159 RenderPass* render_pass,
160 const OcclusionTracker<LayerImpl>& occlusion_tracker,
161 AppendQuadsData* append_quads_data) {
163 DCHECK(!tiler_->has_empty_bounds());
164 DCHECK(!visible_content_rect().IsEmpty());
166 gfx::Rect content_rect = visible_content_rect();
167 SharedQuadState* shared_quad_state =
168 render_pass->CreateAndAppendSharedQuadState();
169 PopulateSharedQuadState(shared_quad_state);
171 AppendDebugBorderQuad(
172 render_pass, content_bounds(), shared_quad_state, append_quads_data);
174 int left, top, right, bottom;
175 tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom);
177 if (ShowDebugBorders()) {
178 for (int j = top; j <= bottom; ++j) {
179 for (int i = left; i <= right; ++i) {
180 DrawableTile* tile = TileAt(i, j);
181 gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
182 gfx::Rect visible_tile_rect = tile_rect;
183 SkColor border_color;
186 if (skips_draw_ || !tile || !tile->resource_id()) {
187 border_color = DebugColors::MissingTileBorderColor();
188 border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
190 border_color = DebugColors::HighResTileBorderColor();
191 border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
193 DebugBorderDrawQuad* debug_border_quad =
194 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
195 debug_border_quad->SetNew(shared_quad_state,
207 Occlusion occlusion =
208 occlusion_tracker.GetCurrentOcclusionForLayer(draw_transform());
209 for (int j = top; j <= bottom; ++j) {
210 for (int i = left; i <= right; ++i) {
211 DrawableTile* tile = TileAt(i, j);
212 gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
213 gfx::Rect display_rect = tile_rect;
214 tile_rect.Intersect(content_rect);
217 if (tile_rect.IsEmpty())
220 gfx::Rect visible_tile_rect =
221 occlusion.GetUnoccludedContentRect(tile_rect);
222 if (visible_tile_rect.IsEmpty())
225 if (!tile || !tile->resource_id()) {
226 SkColor checker_color;
227 if (ShowDebugBorders()) {
229 tile ? DebugColors::InvalidatedTileCheckerboardColor()
230 : DebugColors::EvictedTileCheckerboardColor();
232 checker_color = DebugColors::DefaultCheckerboardColor();
235 CheckerboardDrawQuad* checkerboard_quad =
236 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
237 checkerboard_quad->SetNew(
238 shared_quad_state, tile_rect, visible_tile_rect, checker_color);
239 append_quads_data->num_missing_tiles++;
243 gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : gfx::Rect();
245 // Keep track of how the top left has moved, so the texture can be
246 // offset the same amount.
247 gfx::Vector2d display_offset = tile_rect.origin() - display_rect.origin();
248 gfx::Vector2d texture_offset =
249 tiler_->texture_offset(i, j) + display_offset;
250 gfx::RectF tex_coord_rect = gfx::RectF(tile_rect.size()) + texture_offset;
252 float tile_width = static_cast<float>(tiler_->tile_size().width());
253 float tile_height = static_cast<float>(tiler_->tile_size().height());
254 gfx::Size texture_size(tile_width, tile_height);
256 TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
257 quad->SetNew(shared_quad_state,
264 tile->contents_swizzled());
269 void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) {
273 tiler_ = LayerTilingData::Create(tiler.tile_size(),
274 tiler.has_border_texels()
275 ? LayerTilingData::HAS_BORDER_TEXELS
276 : LayerTilingData::NO_BORDER_TEXELS);
281 void TiledLayerImpl::PushTileProperties(
284 ResourceProvider::ResourceId resource_id,
285 bool contents_swizzled) {
286 DrawableTile* tile = TileAt(i, j);
288 tile = CreateTile(i, j);
289 tile->set_resource_id(resource_id);
290 tile->set_contents_swizzled(contents_swizzled);
293 void TiledLayerImpl::PushInvalidTile(int i, int j) {
294 DrawableTile* tile = TileAt(i, j);
296 tile = CreateTile(i, j);
297 tile->set_resource_id(0);
298 tile->set_contents_swizzled(false);
301 SimpleEnclosedRegion TiledLayerImpl::VisibleContentOpaqueRegion() const {
303 return SimpleEnclosedRegion();
304 return LayerImpl::VisibleContentOpaqueRegion();
307 void TiledLayerImpl::ReleaseResources() {
311 const char* TiledLayerImpl::LayerTypeAsString() const {
312 return "cc::TiledLayerImpl";