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/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/layer_tree_impl.h"
20 #include "cc/trees/occlusion.h"
21 #include "third_party/skia/include/core/SkColor.h"
22 #include "ui/gfx/geometry/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 : TiledLayerImpl(tree_impl
, id
, new LayerImpl::SyncedScrollOffset
) {
54 TiledLayerImpl::TiledLayerImpl(
55 LayerTreeImpl
* tree_impl
,
57 scoped_refptr
<LayerImpl::SyncedScrollOffset
> synced_scroll_offset
)
58 : LayerImpl(tree_impl
, id
, synced_scroll_offset
), skips_draw_(true) {
61 TiledLayerImpl::~TiledLayerImpl() {
64 void TiledLayerImpl::GetContentsResourceId(
65 ResourceProvider::ResourceId
* resource_id
,
66 gfx::Size
* resource_size
) const {
67 // This function is only valid for single texture layers, e.g. masks.
69 // It's possible the mask layer is created but has no size or otherwise
71 if (tiler_
->num_tiles_x() == 0 || tiler_
->num_tiles_y() == 0) {
76 // Any other number of tiles other than 0 or 1 is incorrect for masks.
77 DCHECK_EQ(tiler_
->num_tiles_x(), 1);
78 DCHECK_EQ(tiler_
->num_tiles_y(), 1);
80 DrawableTile
* tile
= TileAt(0, 0);
81 *resource_id
= tile
? tile
->resource_id() : 0;
82 *resource_size
= tiler_
->tile_size();
85 bool TiledLayerImpl::HasTileAt(int i
, int j
) const {
86 return !!tiler_
->TileAt(i
, j
);
89 bool TiledLayerImpl::HasResourceIdForTileAt(int i
, int j
) const {
90 return HasTileAt(i
, j
) && TileAt(i
, j
)->resource_id();
93 DrawableTile
* TiledLayerImpl::TileAt(int i
, int j
) const {
94 return static_cast<DrawableTile
*>(tiler_
->TileAt(i
, j
));
97 DrawableTile
* TiledLayerImpl::CreateTile(int i
, int j
) {
98 scoped_ptr
<DrawableTile
> tile(DrawableTile::Create());
99 DrawableTile
* added_tile
= tile
.get();
100 tiler_
->AddTile(tile
.Pass(), i
, j
);
105 void TiledLayerImpl::GetDebugBorderProperties(SkColor
* color
,
106 float* width
) const {
107 *color
= DebugColors::TiledContentLayerBorderColor();
108 *width
= DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
111 scoped_ptr
<LayerImpl
> TiledLayerImpl::CreateLayerImpl(
112 LayerTreeImpl
* tree_impl
) {
113 return TiledLayerImpl::Create(tree_impl
, id(), synced_scroll_offset());
116 void TiledLayerImpl::AsValueInto(base::trace_event::TracedValue
* state
) const {
117 LayerImpl::AsValueInto(state
);
118 MathUtil::AddToTracedValue("invalidation", update_rect(), state
);
121 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
123 const size_t kMemoryUsagePerTileInBytes
=
124 4 * tiler_
->tile_size().width() * tiler_
->tile_size().height();
125 for (LayerTilingData::TileMap::const_iterator iter
= tiler_
->tiles().begin();
126 iter
!= tiler_
->tiles().end();
128 const DrawableTile
* tile
= static_cast<DrawableTile
*>(iter
->second
);
130 if (!tile
->resource_id())
132 amount
+= kMemoryUsagePerTileInBytes
;
137 void TiledLayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
138 LayerImpl::PushPropertiesTo(layer
);
140 TiledLayerImpl
* tiled_layer
= static_cast<TiledLayerImpl
*>(layer
);
142 tiled_layer
->set_skips_draw(skips_draw_
);
143 tiled_layer
->SetTilingData(*tiler_
);
145 for (LayerTilingData::TileMap::const_iterator iter
= tiler_
->tiles().begin();
146 iter
!= tiler_
->tiles().end();
148 int i
= iter
->first
.first
;
149 int j
= iter
->first
.second
;
150 DrawableTile
* tile
= static_cast<DrawableTile
*>(iter
->second
);
152 tiled_layer
->PushTileProperties(i
,
155 tile
->contents_swizzled());
159 bool TiledLayerImpl::WillDraw(DrawMode draw_mode
,
160 ResourceProvider
* resource_provider
) {
161 if (!tiler_
|| tiler_
->has_empty_bounds() ||
162 visible_content_rect().IsEmpty() ||
163 draw_mode
== DRAW_MODE_RESOURCELESS_SOFTWARE
)
165 return LayerImpl::WillDraw(draw_mode
, resource_provider
);
168 void TiledLayerImpl::AppendQuads(RenderPass
* render_pass
,
169 AppendQuadsData
* append_quads_data
) {
171 DCHECK(!tiler_
->has_empty_bounds());
172 DCHECK(!visible_content_rect().IsEmpty());
174 gfx::Rect content_rect
= visible_content_rect();
175 SharedQuadState
* shared_quad_state
=
176 render_pass
->CreateAndAppendSharedQuadState();
177 PopulateSharedQuadState(shared_quad_state
);
179 AppendDebugBorderQuad(
180 render_pass
, content_bounds(), shared_quad_state
, append_quads_data
);
182 int left
, top
, right
, bottom
;
183 tiler_
->ContentRectToTileIndices(content_rect
, &left
, &top
, &right
, &bottom
);
185 if (ShowDebugBorders()) {
186 for (int j
= top
; j
<= bottom
; ++j
) {
187 for (int i
= left
; i
<= right
; ++i
) {
188 DrawableTile
* tile
= TileAt(i
, j
);
189 gfx::Rect tile_rect
= tiler_
->tile_bounds(i
, j
);
190 gfx::Rect visible_tile_rect
= tile_rect
;
191 SkColor border_color
;
194 if (skips_draw_
|| !tile
|| !tile
->resource_id()) {
195 border_color
= DebugColors::MissingTileBorderColor();
196 border_width
= DebugColors::MissingTileBorderWidth(layer_tree_impl());
198 border_color
= DebugColors::HighResTileBorderColor();
199 border_width
= DebugColors::HighResTileBorderWidth(layer_tree_impl());
201 DebugBorderDrawQuad
* debug_border_quad
=
202 render_pass
->CreateAndAppendDrawQuad
<DebugBorderDrawQuad
>();
203 debug_border_quad
->SetNew(shared_quad_state
,
215 for (int j
= top
; j
<= bottom
; ++j
) {
216 for (int i
= left
; i
<= right
; ++i
) {
217 DrawableTile
* tile
= TileAt(i
, j
);
218 gfx::Rect tile_rect
= tiler_
->tile_bounds(i
, j
);
219 gfx::Rect display_rect
= tile_rect
;
220 tile_rect
.Intersect(content_rect
);
223 if (tile_rect
.IsEmpty())
226 gfx::Rect visible_tile_rect
=
227 draw_properties().occlusion_in_content_space
.GetUnoccludedContentRect(
229 if (visible_tile_rect
.IsEmpty())
232 if (!tile
|| !tile
->resource_id()) {
233 SkColor checker_color
;
234 if (ShowDebugBorders()) {
236 tile
? DebugColors::InvalidatedTileCheckerboardColor()
237 : DebugColors::EvictedTileCheckerboardColor();
239 checker_color
= DebugColors::DefaultCheckerboardColor();
242 CheckerboardDrawQuad
* checkerboard_quad
=
243 render_pass
->CreateAndAppendDrawQuad
<CheckerboardDrawQuad
>();
244 checkerboard_quad
->SetNew(shared_quad_state
, tile_rect
,
245 visible_tile_rect
, checker_color
, 1.f
);
246 append_quads_data
->num_missing_tiles
++;
250 gfx::Rect tile_opaque_rect
= contents_opaque() ? tile_rect
: gfx::Rect();
252 // Keep track of how the top left has moved, so the texture can be
253 // offset the same amount.
254 gfx::Vector2d display_offset
= tile_rect
.origin() - display_rect
.origin();
255 gfx::Vector2d texture_offset
=
256 tiler_
->texture_offset(i
, j
) + display_offset
;
257 gfx::RectF tex_coord_rect
= gfx::RectF(tile_rect
.size()) + texture_offset
;
259 float tile_width
= static_cast<float>(tiler_
->tile_size().width());
260 float tile_height
= static_cast<float>(tiler_
->tile_size().height());
261 gfx::Size
texture_size(tile_width
, tile_height
);
263 // TODO(danakj): crbug.com/455931
264 layer_tree_impl()->resource_provider()->ValidateResource(
265 tile
->resource_id());
266 TileDrawQuad
* quad
= render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
267 quad
->SetNew(shared_quad_state
,
274 tile
->contents_swizzled(),
280 void TiledLayerImpl::SetTilingData(const LayerTilingData
& tiler
) {
284 tiler_
= LayerTilingData::Create(tiler
.tile_size(),
285 tiler
.has_border_texels()
286 ? LayerTilingData::HAS_BORDER_TEXELS
287 : LayerTilingData::NO_BORDER_TEXELS
);
292 void TiledLayerImpl::PushTileProperties(
295 ResourceProvider::ResourceId resource_id
,
296 bool contents_swizzled
) {
297 DrawableTile
* tile
= TileAt(i
, j
);
299 tile
= CreateTile(i
, j
);
300 tile
->set_resource_id(resource_id
);
301 tile
->set_contents_swizzled(contents_swizzled
);
304 void TiledLayerImpl::PushInvalidTile(int i
, int j
) {
305 DrawableTile
* tile
= TileAt(i
, j
);
307 tile
= CreateTile(i
, j
);
308 tile
->set_resource_id(0);
309 tile
->set_contents_swizzled(false);
312 SimpleEnclosedRegion
TiledLayerImpl::VisibleContentOpaqueRegion() const {
314 return SimpleEnclosedRegion();
315 return LayerImpl::VisibleContentOpaqueRegion();
318 void TiledLayerImpl::ReleaseResources() {
322 const char* TiledLayerImpl::LayerTypeAsString() const {
323 return "cc::TiledLayerImpl";