Upstream version 10.39.225.0
[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/debug/trace_event_argument.h"
9 #include "base/strings/stringprintf.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/occlusion_tracker.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "third_party/skia/include/core/SkColor.h"
22 #include "ui/gfx/quad_f.h"
23
24 namespace cc {
25
26 class DrawableTile : public LayerTilingData::Tile {
27  public:
28   static scoped_ptr<DrawableTile> Create() {
29     return make_scoped_ptr(new DrawableTile());
30   }
31
32   ResourceProvider::ResourceId resource_id() const { return resource_id_; }
33   void set_resource_id(ResourceProvider::ResourceId resource_id) {
34     resource_id_ = resource_id;
35   }
36   bool contents_swizzled() { return contents_swizzled_; }
37   void set_contents_swizzled(bool contents_swizzled) {
38     contents_swizzled_ = contents_swizzled;
39   }
40
41  private:
42   DrawableTile() : resource_id_(0), contents_swizzled_(false) {}
43
44   ResourceProvider::ResourceId resource_id_;
45   bool contents_swizzled_;
46
47   DISALLOW_COPY_AND_ASSIGN(DrawableTile);
48 };
49
50 TiledLayerImpl::TiledLayerImpl(LayerTreeImpl* tree_impl, int id)
51     : LayerImpl(tree_impl, id), skips_draw_(true) {}
52
53 TiledLayerImpl::~TiledLayerImpl() {
54 }
55
56 ResourceProvider::ResourceId TiledLayerImpl::ContentsResourceId() const {
57   // This function is only valid for single texture layers, e.g. masks.
58   DCHECK(tiler_);
59   // It's possible the mask layer is created but has no size or otherwise
60   // can't draw.
61   if (tiler_->num_tiles_x() == 0 || tiler_->num_tiles_y() == 0)
62     return 0;
63
64   // Any other number of tiles other than 0 or 1 is incorrect for masks.
65   DCHECK_EQ(tiler_->num_tiles_x(), 1);
66   DCHECK_EQ(tiler_->num_tiles_y(), 1);
67
68   DrawableTile* tile = TileAt(0, 0);
69   ResourceProvider::ResourceId resource_id = tile ? tile->resource_id() : 0;
70   return resource_id;
71 }
72
73 bool TiledLayerImpl::HasTileAt(int i, int j) const {
74   return !!tiler_->TileAt(i, j);
75 }
76
77 bool TiledLayerImpl::HasResourceIdForTileAt(int i, int j) const {
78   return HasTileAt(i, j) && TileAt(i, j)->resource_id();
79 }
80
81 DrawableTile* TiledLayerImpl::TileAt(int i, int j) const {
82   return static_cast<DrawableTile*>(tiler_->TileAt(i, j));
83 }
84
85 DrawableTile* TiledLayerImpl::CreateTile(int i, int j) {
86   scoped_ptr<DrawableTile> tile(DrawableTile::Create());
87   DrawableTile* added_tile = tile.get();
88   tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j);
89
90   return added_tile;
91 }
92
93 void TiledLayerImpl::GetDebugBorderProperties(SkColor* color,
94                                               float* width) const {
95   *color = DebugColors::TiledContentLayerBorderColor();
96   *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
97 }
98
99 scoped_ptr<LayerImpl> TiledLayerImpl::CreateLayerImpl(
100     LayerTreeImpl* tree_impl) {
101   return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
102 }
103
104 void TiledLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
105   LayerImpl::AsValueInto(state);
106   state->BeginArray("invalidation");
107   MathUtil::AddToTracedValue(update_rect(), state);
108   state->EndArray();
109 }
110
111 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
112   size_t amount = 0;
113   const size_t kMemoryUsagePerTileInBytes =
114       4 * tiler_->tile_size().width() * tiler_->tile_size().height();
115   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
116        iter != tiler_->tiles().end();
117        ++iter) {
118     const DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
119     DCHECK(tile);
120     if (!tile->resource_id())
121       continue;
122     amount += kMemoryUsagePerTileInBytes;
123   }
124   return amount;
125 }
126
127 void TiledLayerImpl::PushPropertiesTo(LayerImpl* layer) {
128   LayerImpl::PushPropertiesTo(layer);
129
130   TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer);
131
132   tiled_layer->set_skips_draw(skips_draw_);
133   tiled_layer->SetTilingData(*tiler_);
134
135   for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin();
136        iter != tiler_->tiles().end();
137        ++iter) {
138     int i = iter->first.first;
139     int j = iter->first.second;
140     DrawableTile* tile = static_cast<DrawableTile*>(iter->second);
141     DCHECK(tile);
142     tiled_layer->PushTileProperties(i,
143                                     j,
144                                     tile->resource_id(),
145                                     tile->contents_swizzled());
146   }
147 }
148
149 bool 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
158 void 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   Occlusion occlusion =
208       occlusion_tracker.GetCurrentOcclusionForLayer(draw_transform());
209   for (int j = top; j <= bottom; ++j) {
210     for (int i = left; i <= right; ++i) {
211       DrawableTile* tile = TileAt(i, j);
212       gfx::Rect tile_rect = tiler_->tile_bounds(i, j);
213       gfx::Rect display_rect = tile_rect;
214       tile_rect.Intersect(content_rect);
215
216       // Skip empty tiles.
217       if (tile_rect.IsEmpty())
218         continue;
219
220       gfx::Rect visible_tile_rect =
221           occlusion.GetUnoccludedContentRect(tile_rect);
222       if (visible_tile_rect.IsEmpty())
223         continue;
224
225       if (!tile || !tile->resource_id()) {
226         SkColor checker_color;
227         if (ShowDebugBorders()) {
228           checker_color =
229               tile ? DebugColors::InvalidatedTileCheckerboardColor()
230                    : DebugColors::EvictedTileCheckerboardColor();
231         } else {
232           checker_color = DebugColors::DefaultCheckerboardColor();
233         }
234
235         CheckerboardDrawQuad* checkerboard_quad =
236             render_pass->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
237         checkerboard_quad->SetNew(
238             shared_quad_state, tile_rect, visible_tile_rect, checker_color);
239         append_quads_data->num_missing_tiles++;
240         continue;
241       }
242
243       gfx::Rect tile_opaque_rect = contents_opaque() ? tile_rect : gfx::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
269 void 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
281 void TiledLayerImpl::PushTileProperties(
282     int i,
283     int j,
284     ResourceProvider::ResourceId resource_id,
285     bool contents_swizzled) {
286   DrawableTile* tile = TileAt(i, j);
287   if (!tile)
288     tile = CreateTile(i, j);
289   tile->set_resource_id(resource_id);
290   tile->set_contents_swizzled(contents_swizzled);
291 }
292
293 void TiledLayerImpl::PushInvalidTile(int i, int j) {
294   DrawableTile* tile = TileAt(i, j);
295   if (!tile)
296     tile = CreateTile(i, j);
297   tile->set_resource_id(0);
298   tile->set_contents_swizzled(false);
299 }
300
301 SimpleEnclosedRegion TiledLayerImpl::VisibleContentOpaqueRegion() const {
302   if (skips_draw_)
303     return SimpleEnclosedRegion();
304   return LayerImpl::VisibleContentOpaqueRegion();
305 }
306
307 void TiledLayerImpl::ReleaseResources() {
308   tiler_->reset();
309 }
310
311 const char* TiledLayerImpl::LayerTypeAsString() const {
312   return "cc::TiledLayerImpl";
313 }
314
315 }  // namespace cc