普通文本  |  263行  |  9.85 KB

// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/debug/debug_rect_history.h"

#include "cc/base/math_util.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/trees/damage_tracker.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_common.h"

namespace cc {

// static
scoped_ptr<DebugRectHistory> DebugRectHistory::Create() {
  return make_scoped_ptr(new DebugRectHistory());
}

DebugRectHistory::DebugRectHistory() {}

DebugRectHistory::~DebugRectHistory() {}

void DebugRectHistory::SaveDebugRectsForCurrentFrame(
    LayerImpl* root_layer,
    const LayerImplList& render_surface_layer_list,
    const std::vector<gfx::Rect>& occluding_screen_space_rects,
    const std::vector<gfx::Rect>& non_occluding_screen_space_rects,
    const LayerTreeDebugState& debug_state) {
  // For now, clear all rects from previous frames. In the future we may want to
  // store all debug rects for a history of many frames.
  debug_rects_.clear();

  if (debug_state.show_touch_event_handler_rects)
    SaveTouchEventHandlerRects(root_layer);

  if (debug_state.show_wheel_event_handler_rects)
    SaveWheelEventHandlerRects(root_layer);

  if (debug_state.show_non_fast_scrollable_rects)
    SaveNonFastScrollableRects(root_layer);

  if (debug_state.show_paint_rects)
    SavePaintRects(root_layer);

  if (debug_state.show_property_changed_rects)
    SavePropertyChangedRects(render_surface_layer_list);

  if (debug_state.show_surface_damage_rects)
    SaveSurfaceDamageRects(render_surface_layer_list);

  if (debug_state.show_screen_space_rects)
    SaveScreenSpaceRects(render_surface_layer_list);

  if (debug_state.show_occluding_rects)
    SaveOccludingRects(occluding_screen_space_rects);

  if (debug_state.show_non_occluding_rects)
    SaveNonOccludingRects(non_occluding_screen_space_rects);

  if (debug_state.show_layer_animation_bounds_rects)
    SaveLayerAnimationBoundsRects(render_surface_layer_list);
}

void DebugRectHistory::SavePaintRects(LayerImpl* layer) {
  // We would like to visualize where any layer's paint rect (update rect) has
  // changed, regardless of whether this layer is skipped for actual drawing or
  // not. Therefore we traverse recursively over all layers, not just the render
  // surface list.

  if (!layer->update_rect().IsEmpty() && layer->DrawsContent()) {
    float width_scale = layer->content_bounds().width() /
                        static_cast<float>(layer->bounds().width());
    float height_scale = layer->content_bounds().height() /
                         static_cast<float>(layer->bounds().height());
    gfx::RectF update_content_rect =
        gfx::ScaleRect(layer->update_rect(), width_scale, height_scale);
    debug_rects_.push_back(
        DebugRect(PAINT_RECT_TYPE,
                  MathUtil::MapClippedRect(layer->screen_space_transform(),
                                           update_content_rect)));
  }

  for (unsigned i = 0; i < layer->children().size(); ++i)
    SavePaintRects(layer->children()[i]);
}

void DebugRectHistory::SavePropertyChangedRects(
    const LayerImplList& render_surface_layer_list) {
  for (int surface_index = render_surface_layer_list.size() - 1;
       surface_index >= 0;
       --surface_index) {
    LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
    RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
    DCHECK(render_surface);

    const LayerImplList& layer_list = render_surface->layer_list();
    for (unsigned layer_index = 0;
         layer_index < layer_list.size();
         ++layer_index) {
      LayerImpl* layer = layer_list[layer_index];

      if (LayerTreeHostCommon::RenderSurfaceContributesToTarget<LayerImpl>(
              layer, render_surface_layer->id()))
        continue;

      if (layer->LayerIsAlwaysDamaged())
        continue;

      if (layer->LayerPropertyChanged()) {
        debug_rects_.push_back(
            DebugRect(PROPERTY_CHANGED_RECT_TYPE,
                      MathUtil::MapClippedRect(
                          layer->screen_space_transform(),
                          gfx::RectF(gfx::PointF(), layer->content_bounds()))));
      }
    }
  }
}

void DebugRectHistory::SaveSurfaceDamageRects(
    const LayerImplList& render_surface_layer_list) {
  for (int surface_index = render_surface_layer_list.size() - 1;
       surface_index >= 0;
       --surface_index) {
    LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
    RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
    DCHECK(render_surface);

    debug_rects_.push_back(DebugRect(
        SURFACE_DAMAGE_RECT_TYPE,
        MathUtil::MapClippedRect(
            render_surface->screen_space_transform(),
            render_surface->damage_tracker()->current_damage_rect())));
  }
}

void DebugRectHistory::SaveScreenSpaceRects(
    const LayerImplList& render_surface_layer_list) {
  for (int surface_index = render_surface_layer_list.size() - 1;
       surface_index >= 0;
       --surface_index) {
    LayerImpl* render_surface_layer = render_surface_layer_list[surface_index];
    RenderSurfaceImpl* render_surface = render_surface_layer->render_surface();
    DCHECK(render_surface);

    debug_rects_.push_back(DebugRect(
        SCREEN_SPACE_RECT_TYPE,
        MathUtil::MapClippedRect(render_surface->screen_space_transform(),
                                 render_surface->content_rect())));

    if (render_surface_layer->replica_layer()) {
      debug_rects_.push_back(
          DebugRect(REPLICA_SCREEN_SPACE_RECT_TYPE,
                    MathUtil::MapClippedRect(
                        render_surface->replica_screen_space_transform(),
                        render_surface->content_rect())));
    }
  }
}

void DebugRectHistory::SaveOccludingRects(
    const std::vector<gfx::Rect>& occluding_rects) {
  for (size_t i = 0; i < occluding_rects.size(); ++i)
    debug_rects_.push_back(DebugRect(OCCLUDING_RECT_TYPE, occluding_rects[i]));
}

void DebugRectHistory::SaveNonOccludingRects(
    const std::vector<gfx::Rect>& non_occluding_rects) {
  for (size_t i = 0; i < non_occluding_rects.size(); ++i) {
    debug_rects_.push_back(
        DebugRect(NONOCCLUDING_RECT_TYPE, non_occluding_rects[i]));
  }
}

void DebugRectHistory::SaveTouchEventHandlerRects(LayerImpl* layer) {
  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
      layer,
      base::Bind(&DebugRectHistory::SaveTouchEventHandlerRectsCallback,
                 base::Unretained(this)));
}

void DebugRectHistory::SaveTouchEventHandlerRectsCallback(LayerImpl* layer) {
  for (Region::Iterator iter(layer->touch_event_handler_region());
       iter.has_rect();
       iter.next()) {
    gfx::RectF touch_rect = gfx::ScaleRect(iter.rect(),
                                           layer->contents_scale_x(),
                                           layer->contents_scale_y());
    debug_rects_.push_back(DebugRect(TOUCH_EVENT_HANDLER_RECT_TYPE,
                                     MathUtil::MapClippedRect(
                                         layer->screen_space_transform(),
                                         touch_rect)));
  }
}

void DebugRectHistory::SaveWheelEventHandlerRects(LayerImpl* layer) {
  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
      layer,
      base::Bind(&DebugRectHistory::SaveWheelEventHandlerRectsCallback,
                 base::Unretained(this)));
}

void DebugRectHistory::SaveWheelEventHandlerRectsCallback(LayerImpl* layer) {
  if (!layer->have_wheel_event_handlers())
    return;

  gfx::RectF wheel_rect = gfx::RectF(layer->content_bounds());
  wheel_rect.Scale(layer->contents_scale_x(), layer->contents_scale_y());
  debug_rects_.push_back(DebugRect(WHEEL_EVENT_HANDLER_RECT_TYPE,
                                   MathUtil::MapClippedRect(
                                       layer->screen_space_transform(),
                                       wheel_rect)));
}

void DebugRectHistory::SaveNonFastScrollableRects(LayerImpl* layer) {
  LayerTreeHostCommon::CallFunctionForSubtree<LayerImpl>(
      layer,
      base::Bind(&DebugRectHistory::SaveNonFastScrollableRectsCallback,
                 base::Unretained(this)));
}

void DebugRectHistory::SaveNonFastScrollableRectsCallback(LayerImpl* layer) {
  for (Region::Iterator iter(layer->non_fast_scrollable_region());
       iter.has_rect();
       iter.next()) {
    gfx::RectF scroll_rect = gfx::ScaleRect(iter.rect(),
                                            layer->contents_scale_x(),
                                            layer->contents_scale_y());
    debug_rects_.push_back(DebugRect(NON_FAST_SCROLLABLE_RECT_TYPE,
                                     MathUtil::MapClippedRect(
                                         layer->screen_space_transform(),
                                         scroll_rect)));
  }
}

void DebugRectHistory::SaveLayerAnimationBoundsRects(
    const LayerImplList& render_surface_layer_list) {
  typedef LayerIterator<LayerImpl,
                        LayerImplList,
                        RenderSurfaceImpl,
                        LayerIteratorActions::FrontToBack> LayerIteratorType;
  LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
  for (LayerIteratorType it =
           LayerIteratorType::Begin(&render_surface_layer_list);
       it != end; ++it) {
    if (!it.represents_itself())
      continue;
    gfx::BoxF inflated_bounds;
    if (!(*it)->GetAnimationBounds(&inflated_bounds))
      continue;

    debug_rects_.push_back(DebugRect(ANIMATION_BOUNDS_RECT_TYPE,
                                     gfx::RectF(inflated_bounds.x(),
                                                inflated_bounds.y(),
                                                inflated_bounds.width(),
                                                inflated_bounds.height())));
  }
}

}  // namespace cc