tiled_layer_impl.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/debug/trace_event_argument.h" 9#include "base/strings/stringprintf.h" 10#include "cc/base/math_util.h" 11#include "cc/debug/debug_colors.h" 12#include "cc/layers/append_quads_data.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 "cc/trees/occlusion_tracker.h" 19#include "third_party/khronos/GLES2/gl2.h" 20#include "third_party/skia/include/core/SkColor.h" 21#include "ui/gfx/quad_f.h" 22 23namespace cc { 24 25class 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 49TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id) 50 : LayerImpl(tree_impl, id), skips_draw_(true) {} 51 52TiledLayerImpl::~TiledLayerImpl() { 53} 54 55ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const { 56 // This function is only valid for single texture layers, e.g. masks. 57 DCHECK(tiler_); 58 // It's possible the mask layer is created but has no size or otherwise 59 // can't draw. 60 if (tiler_->num_tiles_x() == 0 || tiler_->num_tiles_y() == 0) 61 return 0; 62 63 // Any other number of tiles other than 0 or 1 is incorrect for masks. 64 DCHECK_EQ(tiler_->num_tiles_x(), 1); 65 DCHECK_EQ(tiler_->num_tiles_y(), 1); 66 67 DrawableTile* tile = TileAt(0, 0); 68 ResourceProvider::ResourceId resource_id = tile ? tile->resource_id() : 0; 69 return resource_id; 70} 71 72bool TiledLayerImpl::HasTileAt(int i, int j) const { 73 return !!tiler_->TileAt(i, j); 74} 75 76bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const { 77 return HasTileAt(i, j) && TileAt(i, j)->resource_id(); 78} 79 80DrawableTile* TiledLayerImpl::TileAt(int i, int j) const { 81 return static_cast<DrawableTile*>(tiler_->TileAt(i, j)); 82} 83 84DrawableTile* TiledLayerImpl::CreateTile(int i, int j) { 85 scoped_ptr<DrawableTile> tile(DrawableTile::Create()); 86 DrawableTile* added_tile = tile.get(); 87 tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j); 88 89 return added_tile; 90} 91 92void TiledLayerImpl::GetDebugBorderProperties(SkColor* color, 93 float* width) const { 94 *color = DebugColors::TiledContentLayerBorderColor(); 95 *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl()); 96} 97 98scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl( 99 LayerTreeImpl* tree_impl) { 100 return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 101} 102 103void TiledLayerImpl::AsValueInto(base::debug::TracedValue* state) const { 104 LayerImpl::AsValueInto(state); 105 state->BeginArray("invalidation"); 106 MathUtil::AddToTracedValue(update_rect(), state); 107 state->EndArray(); 108} 109 110size_t TiledLayerImpl::GPUMemoryUsageInBytes() const { 111 size_t amount = 0; 112 const size_t kMemoryUsagePerTileInBytes = 113 4 * tiler_->tile_size().width() * tiler_->tile_size().height(); 114 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 115 iter != tiler_->tiles().end(); 116 ++iter) { 117 const DrawableTile* tile = static_cast<DrawableTile*>(iter->second); 118 DCHECK(tile); 119 if (!tile->resource_id()) 120 continue; 121 amount += kMemoryUsagePerTileInBytes; 122 } 123 return amount; 124} 125 126void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) { 127 LayerImpl::PushPropertiesTo(layer); 128 129 TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); 130 131 tiled_layer->set_skips_draw(skips_draw_); 132 tiled_layer->SetTilingData(*tiler_); 133 134 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 135 iter != tiler_->tiles().end(); 136 ++iter) { 137 int i = iter->first.first; 138 int j = iter->first.second; 139 DrawableTile* tile = static_cast<DrawableTile*>(iter->second); 140 DCHECK(tile); 141 tiled_layer->PushTileProperties(i, 142 j, 143 tile->resource_id(), 144 tile->opaque_rect(), 145 tile->contents_swizzled()); 146 } 147} 148 149bool 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) 154 return false; 155 return LayerImpl::WillDraw(draw_mode, resource_provider); 156} 157 158void TiledLayerImpl::AppendQuads( 159 RenderPass* render_pass, 160 const OcclusionTracker<LayerImpl>& occlusion_tracker, 161 AppendQuadsData* append_quads_data) { 162 DCHECK(tiler_); 163 DCHECK(!tiler_->has_empty_bounds()); 164 DCHECK(!visible_content_rect().IsEmpty()); 165 166 gfx::Rect content_rect = visible_content_rect(); 167 SharedQuadState* shared_quad_state = 168 render_pass->CreateAndAppendSharedQuadState(); 169 PopulateSharedQuadState(shared_quad_state); 170 171 AppendDebugBorderQuad( 172 render_pass, content_bounds(), shared_quad_state, append_quads_data); 173 174 int left, top, right, bottom; 175 tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom); 176 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; 184 float border_width; 185 186 if (skips_draw_ || !tile || !tile->resource_id()) { 187 border_color = DebugColors::MissingTileBorderColor(); 188 border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl()); 189 } else { 190 border_color = DebugColors::HighResTileBorderColor(); 191 border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl()); 192 } 193 DebugBorderDrawQuad* debug_border_quad = 194 render_pass->CreateAndAppendDrawQuad<DebugBorderDrawQuad>(); 195 debug_border_quad->SetNew(shared_quad_state, 196 tile_rect, 197 visible_tile_rect, 198 border_color, 199 border_width); 200 } 201 } 202 } 203 204 if (skips_draw_) 205 return; 206 207 for (int j = top; j <= bottom; ++j) { 208 for (int i = left; i <= right; ++i) { 209 DrawableTile* tile = TileAt(i, j); 210 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); 211 gfx::Rect display_rect = tile_rect; 212 tile_rect.Intersect(content_rect); 213 214 // Skip empty tiles. 215 if (tile_rect.IsEmpty()) 216 continue; 217 218 gfx::Rect visible_tile_rect = 219 occlusion_tracker.UnoccludedContentRect(tile_rect, draw_transform()); 220 if (visible_tile_rect.IsEmpty()) 221 continue; 222 223 if (!tile || !tile->resource_id()) { 224 SkColor checker_color; 225 if (ShowDebugBorders()) { 226 checker_color = 227 tile ? DebugColors::InvalidatedTileCheckerboardColor() 228 : DebugColors::EvictedTileCheckerboardColor(); 229 } else { 230 checker_color = DebugColors::DefaultCheckerboardColor(); 231 } 232 233 CheckerboardDrawQuad* checkerboard_quad = 234 render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>(); 235 checkerboard_quad->SetNew( 236 shared_quad_state, tile_rect, visible_tile_rect, checker_color); 237 append_quads_data->num_missing_tiles++; 238 continue; 239 } 240 241 gfx::Rect tile_opaque_rect = 242 contents_opaque() ? tile_rect : gfx::IntersectRects( 243 tile->opaque_rect(), tile_rect); 244 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; 251 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); 255 256 TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); 257 quad->SetNew(shared_quad_state, 258 tile_rect, 259 tile_opaque_rect, 260 visible_tile_rect, 261 tile->resource_id(), 262 tex_coord_rect, 263 texture_size, 264 tile->contents_swizzled()); 265 } 266 } 267} 268 269void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) { 270 if (tiler_) { 271 tiler_->reset(); 272 } else { 273 tiler_ = LayerTilingData::Create(tiler.tile_size(), 274 tiler.has_border_texels() 275 ? LayerTilingData::HAS_BORDER_TEXELS 276 : LayerTilingData::NO_BORDER_TEXELS); 277 } 278 *tiler_ = tiler; 279} 280 281void TiledLayerImpl::PushTileProperties( 282 int i, 283 int j, 284 ResourceProvider::ResourceId resource_id, 285 const gfx::Rect& opaque_rect, 286 bool contents_swizzled) { 287 DrawableTile* tile = TileAt(i, j); 288 if (!tile) 289 tile = CreateTile(i, j); 290 tile->set_resource_id(resource_id); 291 tile->set_opaque_rect(opaque_rect); 292 tile->set_contents_swizzled(contents_swizzled); 293} 294 295void TiledLayerImpl::PushInvalidTile(int i, int j) { 296 DrawableTile* tile = TileAt(i, j); 297 if (!tile) 298 tile = CreateTile(i, j); 299 tile->set_resource_id(0); 300 tile->set_opaque_rect(gfx::Rect()); 301 tile->set_contents_swizzled(false); 302} 303 304Region TiledLayerImpl::VisibleContentOpaqueRegion() const { 305 if (skips_draw_) 306 return Region(); 307 if (contents_opaque()) 308 return visible_content_rect(); 309 return tiler_->OpaqueRegionInContentRect(visible_content_rect()); 310} 311 312void TiledLayerImpl::ReleaseResources() { 313 tiler_->reset(); 314} 315 316const char* TiledLayerImpl::LayerTypeAsString() const { 317 return "cc::TiledLayerImpl"; 318} 319 320} // namespace cc 321