- add sources.
[platform/framework/web/crosswalk.git] / src / cc / layers / tiled_layer_impl.cc
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/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"
21
22 namespace cc {
23
24 class DrawableTile : public LayerTilingData::Tile {
25  public:
26   static scoped_ptr<DrawableTile> Create() {
27     return make_scoped_ptr(new DrawableTile());
28   }
29
30   ResourceProvider::ResourceId resource_id() const { return resource_id_; }
31   void set_resource_id(ResourceProvider::ResourceId resource_id) {
32     resource_id_ = resource_id;
33   }
34   bool contents_swizzled() { return contents_swizzled_; }
35   void set_contents_swizzled(bool contents_swizzled) {
36     contents_swizzled_ = contents_swizzled;
37   }
38
39  private:
40   DrawableTile() : resource_id_(0), contents_swizzled_(false) {}
41
42   ResourceProvider::ResourceId resource_id_;
43   bool contents_swizzled_;
44
45   DISALLOW_COPY_AND_ASSIGN(DrawableTile);
46 };
47
48 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id)
49     : LayerImpl(tree_impl, id), skips_draw_(true) {}
50
51 TiledLayerImpl::~TiledLayerImpl() {
52 }
53
54 ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const {
55   // This function is only valid for single texture layers, e.g. masks.
56   DCHECK(tiler_);
57   DCHECK_EQ(tiler_->num_tiles_x(), 1);
58   DCHECK_EQ(tiler_->num_tiles_y(), 1);
59
60   DrawableTile* tile = TileAt(0, 0);
61   ResourceProvider::ResourceId resource_id = tile ? tile->resource_id() : 0;
62   return resource_id;
63 }
64
65 bool TiledLayerImpl::HasTileAt(int i, int j) const {
66   return !!tiler_->TileAt(i, j);
67 }
68
69 bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const {
70   return HasTileAt(i, j) && TileAt(i, j)->resource_id();
71 }
72
73 DrawableTile* TiledLayerImpl::TileAt(int i, int j) const {
74   return static_cast<DrawableTile*>(tiler_->TileAt(i, j));
75 }
76
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);
81
82   return added_tile;
83 }
84
85 void TiledLayerImpl::GetDebugBorderProperties(SkColor* color,
86                                               float* width) const {
87   *color = DebugColors::TiledContentLayerBorderColor();
88   *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
89 }
90
91 scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl(
92     LayerTreeImpl* tree_impl) {
93   return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
94 }
95
96 void TiledLayerImpl::AsValueInto(base::DictionaryValue* state) const {
97   LayerImpl::AsValueInto(state);
98   state->Set("invalidation", MathUtil::AsValue(update_rect()).release());
99 }
100
101 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
102   size_t amount = 0;
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();
107        ++iter) {
108     const DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
109     if (!tile || !tile->resource_id())
110       continue;
111     amount += kMemoryUsagePerTileInBytes;
112   }
113   return amount;
114 }
115
116 void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) {
117   LayerImpl::PushPropertiesTo(layer);
118
119   TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);
120
121   tiled_layer->set_skips_draw(skips_draw_);
122   tiled_layer->SetTilingData(*tiler_);
123
124   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
125        iter != tiler_->tiles().end();
126        ++iter) {
127     int i = iter->first.first;
128     int j = iter->first.second;
129     DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
130
131     tiled_layer->PushTileProperties(i,
132                                     j,
133                                     tile->resource_id(),
134                                     tile->opaque_rect(),
135                                     tile->contents_swizzled());
136   }
137 }
138
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)
144     return false;
145   return LayerImpl::WillDraw(draw_mode, resource_provider);
146 }
147
148 void TiledLayerImpl::AppendQuads(QuadSink* quad_sink,
149                                  AppendQuadsData* append_quads_data) {
150   DCHECK(tiler_);
151   DCHECK(!tiler_->has_empty_bounds());
152   DCHECK(!visible_content_rect().IsEmpty());
153
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);
158
159   int left, top, right, bottom;
160   tiler_->ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom);
161
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;
168         float border_width;
169
170         if (skips_draw_ || !tile || !tile->resource_id()) {
171           border_color = DebugColors::MissingTileBorderColor();
172           border_width = DebugColors::MissingTileBorderWidth(layer_tree_impl());
173         } else {
174           border_color = DebugColors::HighResTileBorderColor();
175           border_width = DebugColors::HighResTileBorderWidth(layer_tree_impl());
176         }
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>(),
182                           append_quads_data);
183       }
184     }
185   }
186
187   if (skips_draw_)
188     return;
189
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);
196
197       // Skip empty tiles.
198       if (tile_rect.IsEmpty())
199         continue;
200
201       if (!tile || !tile->resource_id()) {
202         SkColor checker_color;
203         if (ShowDebugBorders()) {
204           checker_color =
205               tile ? DebugColors::InvalidatedTileCheckerboardColor()
206                    : DebugColors::EvictedTileCheckerboardColor();
207         } else {
208           checker_color = DebugColors::DefaultCheckerboardColor();
209         }
210
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>(),
216                               append_quads_data))
217           append_quads_data->num_missing_tiles++;
218
219         continue;
220       }
221
222       gfx::Rect tile_opaque_rect =
223           contents_opaque() ? tile_rect : gfx::IntersectRects(
224                                               tile->opaque_rect(), tile_rect);
225
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;
232
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);
236
237       scoped_ptr<TileDrawQuad> quad = TileDrawQuad::Create();
238       quad->SetNew(shared_quad_state,
239                    tile_rect,
240                    tile_opaque_rect,
241                    tile->resource_id(),
242                    tex_coord_rect,
243                    texture_size,
244                    tile->contents_swizzled());
245       quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
246     }
247   }
248 }
249
250 void TiledLayerImpl::SetTilingData(const LayerTilingData& tiler) {
251   if (tiler_) {
252     tiler_->reset();
253   } else {
254     tiler_ = LayerTilingData::Create(tiler.tile_size(),
255                                      tiler.has_border_texels()
256                                          ? LayerTilingData::HAS_BORDER_TEXELS
257                                          : LayerTilingData::NO_BORDER_TEXELS);
258   }
259   *tiler_ = tiler;
260 }
261
262 void TiledLayerImpl::PushTileProperties(
263     int i,
264     int j,
265     ResourceProvider::ResourceId resource_id,
266     gfx::Rect opaque_rect,
267     bool contents_swizzled) {
268   DrawableTile* tile = TileAt(i, j);
269   if (!tile)
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);
274 }
275
276 void TiledLayerImpl::PushInvalidTile(int i, int j) {
277   DrawableTile* tile = TileAt(i, j);
278   if (!tile)
279     tile = CreateTile(i, j);
280   tile->set_resource_id(0);
281   tile->set_opaque_rect(gfx::Rect());
282   tile->set_contents_swizzled(false);
283 }
284
285 Region TiledLayerImpl::VisibleContentOpaqueRegion() const {
286   if (skips_draw_)
287     return Region();
288   if (contents_opaque())
289     return visible_content_rect();
290   return tiler_->OpaqueRegionInContentRect(visible_content_rect());
291 }
292
293 void TiledLayerImpl::DidLoseOutputSurface() {
294   tiler_->reset();
295 }
296
297 const char* TiledLayerImpl::LayerTypeAsString() const {
298   return "cc::TiledLayerImpl";
299 }
300
301 }  // namespace cc