Home | History | Annotate | Download | only in layers
      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
    316