tiled_layer_impl.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/stringprintf.h" 9#include "cc/base/math_util.h" 10#include "cc/debug/debug_colors.h" 11#include "cc/layers/append_quads_data.h" 12#include "cc/layers/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 22namespace cc { 23 24// Temporary diagnostic. 25static bool s_safe_to_delete_drawable_tile = false; 26 27class 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 53TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id) 54 : LayerImpl(tree_impl, id), skips_draw_(true) {} 55 56TiledLayerImpl::~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 63ResourceProvider::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 74void 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 80bool TiledLayerImpl::HasTileAt(int i, int j) const { 81 return !!tiler_->TileAt(i, j); 82} 83 84bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const { 85 return HasTileAt(i, j) && TileAt(i, j)->resource_id(); 86} 87 88DrawableTile* TiledLayerImpl::TileAt(int i, int j) const { 89 return static_cast<DrawableTile*>(tiler_->TileAt(i, j)); 90} 91 92DrawableTile* 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 104void TiledLayerImpl::GetDebugBorderProperties(SkColor* color, 105 float* width) const { 106 *color = DebugColors::TiledContentLayerBorderColor(); 107 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); 108} 109 110scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl( 111 LayerTreeImpl* tree_impl) { 112 return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 113} 114 115void TiledLayerImpl::AsValueInto(base::DictionaryValue* state) const { 116 LayerImpl::AsValueInto(state); 117 state->Set("invalidation", MathUtil::AsValue(update_rect()).release()); 118} 119 120size_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 if (!tile || !tile->resource_id()) 129 continue; 130 amount += kMemoryUsagePerTileInBytes; 131 } 132 return amount; 133} 134 135void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) { 136 LayerImpl::PushPropertiesTo(layer); 137 138 TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); 139 140 tiled_layer->set_skips_draw(skips_draw_); 141 tiled_layer->SetTilingData(*tiler_); 142 143 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 144 iter != tiler_->tiles().end(); 145 ++iter) { 146 int i = iter->first.first; 147 int j = iter->first.second; 148 DrawableTile* tile = static_cast<DrawableTile*>(iter->second); 149 150 tiled_layer->PushTileProperties(i, 151 j, 152 tile->resource_id(), 153 tile->opaque_rect(), 154 tile->contents_swizzled()); 155 } 156} 157 158void TiledLayerImpl::AppendQuads(QuadSink* quad_sink, 159 AppendQuadsData* append_quads_data) { 160 gfx::Rect content_rect = visible_content_rect(); 161 162 if (!tiler_ || tiler_->has_empty_bounds() || content_rect.IsEmpty()) 163 return; 164 165 SharedQuadState* shared_quad_state = 166 quad_sink->UseSharedQuadState(CreateSharedQuadState()); 167 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); 168 169 int left, top, right, bottom; 170 tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom); 171 172 if (ShowDebugBorders()) { 173 for (int j = top; j <= bottom; ++j) { 174 for (int i = left; i <= right; ++i) { 175 DrawableTile* tile = TileAt(i, j); 176 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); 177 SkColor border_color; 178 float border_width; 179 180 if (skips_draw_ || !tile || !tile->resource_id()) { 181 border_color = DebugColors::MissingTileBorderColor(); 182 border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); 183 } else { 184 border_color = DebugColors::HighResTileBorderColor(); 185 border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); 186 } 187 scoped_ptr<DebugBorderDrawQuad> debug_border_quad = 188 DebugBorderDrawQuad::Create(); 189 debug_border_quad->SetNew( 190 shared_quad_state, tile_rect, border_color, border_width); 191 quad_sink->Append(debug_border_quad.PassAs<DrawQuad>(), 192 append_quads_data); 193 } 194 } 195 } 196 197 if (skips_draw_) 198 return; 199 200 for (int j = top; j <= bottom; ++j) { 201 for (int i = left; i <= right; ++i) { 202 DrawableTile* tile = TileAt(i, j); 203 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); 204 gfx::Rect display_rect = tile_rect; 205 tile_rect.Intersect(content_rect); 206 207 // Skip empty tiles. 208 if (tile_rect.IsEmpty()) 209 continue; 210 211 if (!tile || !tile->resource_id()) { 212 SkColor checker_color; 213 if (ShowDebugBorders()) { 214 checker_color = 215 tile ? DebugColors::InvalidatedTileCheckerboardColor() 216 : DebugColors::EvictedTileCheckerboardColor(); 217 } else { 218 checker_color = DebugColors::DefaultCheckerboardColor(); 219 } 220 221 scoped_ptr<CheckerboardDrawQuad> checkerboard_quad = 222 CheckerboardDrawQuad::Create(); 223 checkerboard_quad->SetNew( 224 shared_quad_state, tile_rect, checker_color); 225 if (quad_sink->Append(checkerboard_quad.PassAs<DrawQuad>(), 226 append_quads_data)) 227 append_quads_data->num_missing_tiles++; 228 229 continue; 230 } 231 232 gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : 233 gfx::IntersectRects(tile->opaque_rect(), content_rect); 234 235 // Keep track of how the top left has moved, so the texture can be 236 // offset the same amount. 237 gfx::Vector2d display_offset = tile_rect.origin() - display_rect.origin(); 238 gfx::Vector2d texture_offset = 239 tiler_->texture_offset(i, j) + display_offset; 240 gfx::RectF tex_coord_rect = gfx::RectF(tile_rect.size()) + texture_offset; 241 242 float tile_width = static_cast<float>(tiler_->tile_size().width()); 243 float tile_height = static_cast<float>(tiler_->tile_size().height()); 244 gfx::Size texture_size(tile_width, tile_height); 245 246 scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create(); 247 quad->SetNew(shared_quad_state, 248 tile_rect, 249 tile_opaque_rect, 250 tile->resource_id(), 251 tex_coord_rect, 252 texture_size, 253 tile->contents_swizzled()); 254 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); 255 } 256 } 257} 258 259void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) { 260 s_safe_to_delete_drawable_tile = true; 261 262 if (tiler_) { 263 tiler_->reset(); 264 } else { 265 tiler_ = LayerTilingData::Create(tiler.tile_size(), 266 tiler.has_border_texels() 267 ? LayerTilingData::HAS_BORDER_TEXELS 268 : LayerTilingData::NO_BORDER_TEXELS); 269 } 270 *tiler_ = tiler; 271 272 s_safe_to_delete_drawable_tile = false; 273} 274 275void TiledLayerImpl::PushTileProperties( 276 int i, 277 int j, 278 ResourceProvider::ResourceId resource_id, 279 gfx::Rect opaque_rect, 280 bool contents_swizzled) { 281 DrawableTile* tile = TileAt(i, j); 282 if (!tile) 283 tile = CreateTile(i, j); 284 tile->set_resource_id(resource_id); 285 tile->set_opaque_rect(opaque_rect); 286 tile->set_contents_swizzled(contents_swizzled); 287} 288 289void TiledLayerImpl::PushInvalidTile(int i, int j) { 290 DrawableTile* tile = TileAt(i, j); 291 if (!tile) 292 tile = CreateTile(i, j); 293 tile->set_resource_id(0); 294 tile->set_opaque_rect(gfx::Rect()); 295 tile->set_contents_swizzled(false); 296} 297 298Region TiledLayerImpl::VisibleContentOpaqueRegion() const { 299 if (skips_draw_) 300 return Region(); 301 if (contents_opaque()) 302 return visible_content_rect(); 303 return tiler_->OpaqueRegionInContentRect(visible_content_rect()); 304} 305 306void TiledLayerImpl::DidLoseOutputSurface() { 307 s_safe_to_delete_drawable_tile = true; 308 // Temporary diagnostic check. 309 CHECK(tiler_); 310 tiler_->reset(); 311 s_safe_to_delete_drawable_tile = false; 312} 313 314const char* TiledLayerImpl::LayerTypeAsString() const { 315 return "cc::TiledLayerImpl"; 316} 317 318} // namespace cc 319