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 "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"
24 class DrawableTile
: public LayerTilingData::Tile
{
26 static scoped_ptr
<DrawableTile
> Create() {
27 return make_scoped_ptr(new DrawableTile());
30 ResourceProvider::ResourceId
resource_id() const { return resource_id_
; }
31 void set_resource_id(ResourceProvider::ResourceId resource_id
) {
32 resource_id_
= resource_id
;
34 bool contents_swizzled() { return contents_swizzled_
; }
35 void set_contents_swizzled(bool contents_swizzled
) {
36 contents_swizzled_
= contents_swizzled
;
40 DrawableTile() : resource_id_(0), contents_swizzled_(false) {}
42 ResourceProvider::ResourceId resource_id_
;
43 bool contents_swizzled_
;
45 DISALLOW_COPY_AND_ASSIGN(DrawableTile
);
48 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
49 : LayerImpl(tree_impl
, id
), skips_draw_(true) {}
51 TiledLayerImpl::~TiledLayerImpl() {
54 ResourceProvider::ResourceId
TiledLayerImpl::ContentsResourceId() const {
55 // This function is only valid for single texture layers, e.g. masks.
57 DCHECK_EQ(tiler_
->num_tiles_x(), 1);
58 DCHECK_EQ(tiler_
->num_tiles_y(), 1);
60 DrawableTile
* tile
= TileAt(0, 0);
61 ResourceProvider::ResourceId resource_id
= tile
? tile
->resource_id() : 0;
65 bool TiledLayerImpl::HasTileAt(int i
, int j
) const {
66 return !!tiler_
->TileAt(i
, j
);
69 bool TiledLayerImpl::HasResourceIdForTileAt(int i
, int j
) const {
70 return HasTileAt(i
, j
) && TileAt(i
, j
)->resource_id();
73 DrawableTile
* TiledLayerImpl::TileAt(int i
, int j
) const {
74 return static_cast<DrawableTile
*>(tiler_
->TileAt(i
, j
));
77 DrawableTile
* TiledLayerImpl::CreateTile(int i
, int j
) {
78 scoped_ptr
<DrawableTile
> tile(DrawableTile::Create());
79 DrawableTile
* added_tile
= tile
.get();
80 tiler_
->AddTile(tile
.PassAs
<LayerTilingData::Tile
>(), i
, j
);
85 void TiledLayerImpl::GetDebugBorderProperties(SkColor
* color
,
87 *color
= DebugColors::TiledContentLayerBorderColor();
88 *width
= DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
91 scoped_ptr
<LayerImpl
> TiledLayerImpl::CreateLayerImpl(
92 LayerTreeImpl
* tree_impl
) {
93 return TiledLayerImpl::Create(tree_impl
, id()).PassAs
<LayerImpl
>();
96 void TiledLayerImpl::AsValueInto(base::DictionaryValue
* state
) const {
97 LayerImpl::AsValueInto(state
);
98 state
->Set("invalidation", MathUtil::AsValue(update_rect()).release());
101 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
103 const size_t kMemoryUsagePerTileInBytes
=
104 4 * tiler_
->tile_size().width() * tiler_
->tile_size().height();
105 for (LayerTilingData::TileMap::const_iterator iter
= tiler_
->tiles().begin();
106 iter
!= tiler_
->tiles().end();
108 const DrawableTile
* tile
= static_cast<DrawableTile
*>(iter
->second
);
109 if (!tile
|| !tile
->resource_id())
111 amount
+= kMemoryUsagePerTileInBytes
;
116 void TiledLayerImpl::PushPropertiesTo(LayerImpl
* layer
) {
117 LayerImpl::PushPropertiesTo(layer
);
119 TiledLayerImpl
* tiled_layer
= static_cast<TiledLayerImpl
*>(layer
);
121 tiled_layer
->set_skips_draw(skips_draw_
);
122 tiled_layer
->SetTilingData(*tiler_
);
124 for (LayerTilingData::TileMap::const_iterator iter
= tiler_
->tiles().begin();
125 iter
!= tiler_
->tiles().end();
127 int i
= iter
->first
.first
;
128 int j
= iter
->first
.second
;
129 DrawableTile
* tile
= static_cast<DrawableTile
*>(iter
->second
);
131 tiled_layer
->PushTileProperties(i
,
135 tile
->contents_swizzled());
139 bool TiledLayerImpl::WillDraw(DrawMode draw_mode
,
140 ResourceProvider
* resource_provider
) {
141 if (!tiler_
|| tiler_
->has_empty_bounds() ||
142 visible_content_rect().IsEmpty() ||
143 draw_mode
== DRAW_MODE_RESOURCELESS_SOFTWARE
)
145 return LayerImpl::WillDraw(draw_mode
, resource_provider
);
148 void TiledLayerImpl::AppendQuads(QuadSink
* quad_sink
,
149 AppendQuadsData
* append_quads_data
) {
151 DCHECK(!tiler_
->has_empty_bounds());
152 DCHECK(!visible_content_rect().IsEmpty());
154 gfx::Rect content_rect
= visible_content_rect();
155 SharedQuadState
* shared_quad_state
=
156 quad_sink
->UseSharedQuadState(CreateSharedQuadState());
157 AppendDebugBorderQuad(quad_sink
, shared_quad_state
, append_quads_data
);
159 int left
, top
, right
, bottom
;
160 tiler_
->ContentRectToTileIndices(content_rect
, &left
, &top
, &right
, &bottom
);
162 if (ShowDebugBorders()) {
163 for (int j
= top
; j
<= bottom
; ++j
) {
164 for (int i
= left
; i
<= right
; ++i
) {
165 DrawableTile
* tile
= TileAt(i
, j
);
166 gfx::Rect tile_rect
= tiler_
->tile_bounds(i
, j
);
167 SkColor border_color
;
170 if (skips_draw_
|| !tile
|| !tile
->resource_id()) {
171 border_color
= DebugColors::MissingTileBorderColor();
172 border_width
= DebugColors::MissingTileBorderWidth(layer_tree_impl());
174 border_color
= DebugColors::HighResTileBorderColor();
175 border_width
= DebugColors::HighResTileBorderWidth(layer_tree_impl());
177 scoped_ptr
<DebugBorderDrawQuad
> debug_border_quad
=
178 DebugBorderDrawQuad::Create();
179 debug_border_quad
->SetNew(
180 shared_quad_state
, tile_rect
, border_color
, border_width
);
181 quad_sink
->Append(debug_border_quad
.PassAs
<DrawQuad
>(),
190 for (int j
= top
; j
<= bottom
; ++j
) {
191 for (int i
= left
; i
<= right
; ++i
) {
192 DrawableTile
* tile
= TileAt(i
, j
);
193 gfx::Rect tile_rect
= tiler_
->tile_bounds(i
, j
);
194 gfx::Rect display_rect
= tile_rect
;
195 tile_rect
.Intersect(content_rect
);
198 if (tile_rect
.IsEmpty())
201 if (!tile
|| !tile
->resource_id()) {
202 SkColor checker_color
;
203 if (ShowDebugBorders()) {
205 tile
? DebugColors::InvalidatedTileCheckerboardColor()
206 : DebugColors::EvictedTileCheckerboardColor();
208 checker_color
= DebugColors::DefaultCheckerboardColor();
211 scoped_ptr
<CheckerboardDrawQuad
> checkerboard_quad
=
212 CheckerboardDrawQuad::Create();
213 checkerboard_quad
->SetNew(
214 shared_quad_state
, tile_rect
, checker_color
);
215 if (quad_sink
->Append(checkerboard_quad
.PassAs
<DrawQuad
>(),
217 append_quads_data
->num_missing_tiles
++;
222 gfx::Rect tile_opaque_rect
=
223 contents_opaque() ? tile_rect
: gfx::IntersectRects(
224 tile
->opaque_rect(), tile_rect
);
226 // Keep track of how the top left has moved, so the texture can be
227 // offset the same amount.
228 gfx::Vector2d display_offset
= tile_rect
.origin() - display_rect
.origin();
229 gfx::Vector2d texture_offset
=
230 tiler_
->texture_offset(i
, j
) + display_offset
;
231 gfx::RectF tex_coord_rect
= gfx::RectF(tile_rect
.size()) + texture_offset
;
233 float tile_width
= static_cast<float>(tiler_
->tile_size().width());
234 float tile_height
= static_cast<float>(tiler_
->tile_size().height());
235 gfx::Size
texture_size(tile_width
, tile_height
);
237 scoped_ptr
<TileDrawQuad
> quad
= TileDrawQuad::Create();
238 quad
->SetNew(shared_quad_state
,
244 tile
->contents_swizzled());
245 quad_sink
->Append(quad
.PassAs
<DrawQuad
>(), append_quads_data
);
250 void TiledLayerImpl::SetTilingData(const LayerTilingData
& tiler
) {
254 tiler_
= LayerTilingData::Create(tiler
.tile_size(),
255 tiler
.has_border_texels()
256 ? LayerTilingData::HAS_BORDER_TEXELS
257 : LayerTilingData::NO_BORDER_TEXELS
);
262 void TiledLayerImpl::PushTileProperties(
265 ResourceProvider::ResourceId resource_id
,
266 gfx::Rect opaque_rect
,
267 bool contents_swizzled
) {
268 DrawableTile
* tile
= TileAt(i
, j
);
270 tile
= CreateTile(i
, j
);
271 tile
->set_resource_id(resource_id
);
272 tile
->set_opaque_rect(opaque_rect
);
273 tile
->set_contents_swizzled(contents_swizzled
);
276 void TiledLayerImpl::PushInvalidTile(int i
, int j
) {
277 DrawableTile
* tile
= TileAt(i
, j
);
279 tile
= CreateTile(i
, j
);
280 tile
->set_resource_id(0);
281 tile
->set_opaque_rect(gfx::Rect());
282 tile
->set_contents_swizzled(false);
285 Region
TiledLayerImpl::VisibleContentOpaqueRegion() const {
288 if (contents_opaque())
289 return visible_content_rect();
290 return tiler_
->OpaqueRegionInContentRect(visible_content_rect());
293 void TiledLayerImpl::DidLoseOutputSurface() {
297 const char* TiledLayerImpl::LayerTypeAsString() const {
298 return "cc::TiledLayerImpl";