#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "build/build_config.h"
-#include "cc/debug/overdraw_metrics.h"
+#include "cc/base/simple_enclosed_region.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/tiled_layer_impl.h"
#include "cc/resources/layer_updater.h"
#include "cc/resources/prioritized_resource.h"
#include "cc/resources/priority_calculator.h"
#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/occlusion_tracker.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/rect_conversions.h"
}
void TiledLayer::UpdateBounds() {
- gfx::Size old_bounds = tiler_->bounds();
- gfx::Size new_bounds = content_bounds();
- if (old_bounds == new_bounds)
+ gfx::Size old_tiling_size = tiler_->tiling_size();
+ gfx::Size new_tiling_size = content_bounds();
+ if (old_tiling_size == new_tiling_size)
return;
- tiler_->SetBounds(new_bounds);
+ tiler_->SetTilingSize(new_tiling_size);
// Invalidate any areas that the new bounds exposes.
- Region old_region = gfx::Rect(old_bounds);
- Region new_region = gfx::Rect(new_bounds);
- new_region.Subtract(old_region);
- for (Region::Iterator new_rects(new_region);
- new_rects.has_rect();
+ Region new_region =
+ SubtractRegions(gfx::Rect(new_tiling_size), gfx::Rect(old_tiling_size));
+ for (Region::Iterator new_rects(new_region); new_rects.has_rect();
new_rects.next())
InvalidateContentRect(new_rects.rect());
+ UpdateDrawsContent(HasDrawableContent());
}
-void TiledLayer::SetTileSize(gfx::Size size) { tiler_->SetTileSize(size); }
+void TiledLayer::SetTileSize(const gfx::Size& size) {
+ tiler_->SetTileSize(size);
+ UpdateDrawsContent(HasDrawableContent());
+}
void TiledLayer::SetBorderTexelOption(
LayerTilingData::BorderTexelOption border_texel_option) {
tiler_->SetBorderTexelOption(border_texel_option);
+ UpdateDrawsContent(HasDrawableContent());
}
-bool TiledLayer::DrawsContent() const {
- if (!ContentsScalingLayer::DrawsContent())
- return false;
-
+bool TiledLayer::HasDrawableContent() const {
bool has_more_than_one_tile =
- tiler_->num_tiles_x() > 1 || tiler_->num_tiles_y() > 1;
- if (tiling_option_ == NEVER_TILE && has_more_than_one_tile)
- return false;
+ (tiler_->num_tiles_x() > 1) || (tiler_->num_tiles_y() > 1);
- return true;
+ return !(tiling_option_ == NEVER_TILE && has_more_than_one_tile) &&
+ ContentsScalingLayer::HasDrawableContent();
}
void TiledLayer::ReduceMemoryUsage() {
i,
j,
tile->managed_resource()->resource_id(),
- tile->opaque_rect(),
tile->managed_resource()->contents_swizzled());
}
for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin();
ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect);
}
-void TiledLayer::InvalidateContentRect(gfx::Rect content_rect) {
+void TiledLayer::InvalidateContentRect(const gfx::Rect& content_rect) {
UpdateBounds();
if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_)
return;
int right,
int bottom,
ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion,
+ const OcclusionTracker<Layer>* occlusion,
bool* updated) {
CreateUpdaterIfNeeded();
return false;
}
- gfx::Rect paint_rect =
- MarkTilesForUpdate(left, top, right, bottom, ignore_occlusions);
-
- if (occlusion)
- occlusion->overdraw_metrics()->DidPaint(paint_rect);
+ gfx::Rect update_rect;
+ gfx::Rect paint_rect;
+ MarkTilesForUpdate(
+ &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions);
if (paint_rect.IsEmpty())
return true;
*updated = true;
UpdateTileTextures(
- paint_rect, left, top, right, bottom, queue, occlusion);
+ update_rect, paint_rect, left, top, right, bottom, queue, occlusion);
return true;
}
int top,
int right,
int bottom,
- const OcclusionTracker* occlusion) {
- // There is some difficult dependancies between occlusions, recording
- // occlusion metrics and requesting memory so those are encapsulated in this
- // function: - We only want to call RequestLate on unoccluded textures (to
- // preserve memory for other layers when near OOM). - We only want to record
- // occlusion metrics if all memory requests succeed.
-
+ const OcclusionTracker<Layer>* occlusion) {
int occluded_tile_count = 0;
bool succeeded = true;
for (int j = top; j <= bottom; ++j) {
DCHECK(!tile->occluded);
gfx::Rect visible_tile_rect = gfx::IntersectRects(
tiler_->tile_bounds(i, j), visible_content_rect());
- if (occlusion && occlusion->Occluded(render_target(),
- visible_tile_rect,
- draw_transform(),
- draw_transform_is_animating())) {
+ if (!draw_transform_is_animating() && occlusion &&
+ occlusion->GetCurrentOcclusionForLayer(draw_transform())
+ .IsOccluded(visible_tile_rect)) {
tile->occluded = true;
occluded_tile_count++;
} else {
}
}
}
-
- if (!succeeded)
- return;
- if (occlusion)
- occlusion->overdraw_metrics()->DidCullTilesForUpload(occluded_tile_count);
}
bool TiledLayer::HaveTexturesForTiles(int left,
return true;
}
-gfx::Rect TiledLayer::MarkTilesForUpdate(int left,
- int top,
- int right,
- int bottom,
- bool ignore_occlusions) {
- gfx::Rect paint_rect;
+void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect,
+ gfx::Rect* paint_rect,
+ int left,
+ int top,
+ int right,
+ int bottom,
+ bool ignore_occlusions) {
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
UpdatableTile* tile = TileAt(i, j);
continue;
if (tile->occluded && !ignore_occlusions)
continue;
+
+ // Prepare update rect from original dirty rects.
+ update_rect->Union(tile->dirty_rect);
+
// TODO(reveman): Decide if partial update should be allowed based on cost
// of update. https://bugs.webkit.org/show_bug.cgi?id=77376
if (tile->is_dirty() &&
}
}
- paint_rect.Union(tile->dirty_rect);
+ paint_rect->Union(tile->dirty_rect);
tile->MarkForUpdate();
}
}
- return paint_rect;
}
-void TiledLayer::UpdateTileTextures(gfx::Rect paint_rect,
+void TiledLayer::UpdateTileTextures(const gfx::Rect& update_rect,
+ const gfx::Rect& paint_rect,
int left,
int top,
int right,
int bottom,
ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion) {
+ const OcclusionTracker<Layer>* occlusion) {
// The update_rect should be in layer space. So we have to convert the
// paint_rect from content space to layer space.
- float width_scale =
- paint_properties().bounds.width() /
- static_cast<float>(content_bounds().width());
- float height_scale =
- paint_properties().bounds.height() /
- static_cast<float>(content_bounds().height());
- update_rect_ = gfx::ScaleRect(paint_rect, width_scale, height_scale);
+ float width_scale = 1 / draw_properties().contents_scale_x;
+ float height_scale = 1 / draw_properties().contents_scale_y;
+ update_rect_ = gfx::ScaleRect(update_rect, width_scale, height_scale);
// Calling PrepareToUpdate() calls into WebKit to paint, which may have the
// side effect of disabling compositing, which causes our reference to the
// the SkCanvas until the paint finishes, so we grab a local reference here to
// hold the updater alive until the paint completes.
scoped_refptr<LayerUpdater> protector(Updater());
- gfx::Rect painted_opaque_rect;
- Updater()->PrepareToUpdate(paint_rect,
+ Updater()->PrepareToUpdate(content_bounds(),
+ paint_rect,
tiler_->tile_size(),
1.f / width_scale,
- 1.f / height_scale,
- &painted_opaque_rect);
+ 1.f / height_scale);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
if (dirty_rect.IsEmpty())
continue;
- // Save what was painted opaque in the tile. Keep the old area if the
- // paint didn't touch it, and didn't paint some other part of the tile
- // opaque.
- gfx::Rect tile_painted_rect = gfx::IntersectRects(tile_rect, paint_rect);
- gfx::Rect tile_painted_opaque_rect =
- gfx::IntersectRects(tile_rect, painted_opaque_rect);
- if (!tile_painted_rect.IsEmpty()) {
- gfx::Rect paint_inside_tile_opaque_rect =
- gfx::IntersectRects(tile->opaque_rect(), tile_painted_rect);
- bool paint_inside_tile_opaque_rect_is_non_opaque =
- !paint_inside_tile_opaque_rect.IsEmpty() &&
- !tile_painted_opaque_rect.Contains(paint_inside_tile_opaque_rect);
- bool opaque_paint_not_inside_tile_opaque_rect =
- !tile_painted_opaque_rect.IsEmpty() &&
- !tile->opaque_rect().Contains(tile_painted_opaque_rect);
-
- if (paint_inside_tile_opaque_rect_is_non_opaque ||
- opaque_paint_not_inside_tile_opaque_rect)
- tile->set_opaque_rect(tile_painted_opaque_rect);
- }
-
// source_rect starts as a full-sized tile with border texels included.
gfx::Rect source_rect = tiler_->TileRect(tile);
source_rect.Intersect(dirty_rect);
tile->updater_resource()->Update(
queue, source_rect, dest_offset, tile->partial_update);
- if (occlusion) {
- occlusion->overdraw_metrics()->
- DidUpload(gfx::Transform(), source_rect, tile->opaque_rect());
- }
}
}
}
// TODO(epenner): Remove this and make this based on distance once distance can
// be calculated for offscreen layers. For now, prioritize all small animated
// layers after 512 pixels of pre-painting.
-void SetPriorityForTexture(gfx::Rect visible_rect,
- gfx::Rect tile_rect,
+void SetPriorityForTexture(const gfx::Rect& visible_rect,
+ const gfx::Rect& tile_rect,
bool draws_to_root,
bool is_small_animated_layer,
PrioritizedResource* texture) {
}
}
-Region TiledLayer::VisibleContentOpaqueRegion() const {
+SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const {
if (skips_draw_)
- return Region();
- if (contents_opaque())
- return visible_content_rect();
- return tiler_->OpaqueRegionInContentRect(visible_content_rect());
+ return SimpleEnclosedRegion();
+ return Layer::VisibleContentOpaqueRegion();
}
void TiledLayer::ResetUpdateState() {
}
namespace {
-gfx::Rect ExpandRectByDelta(gfx::Rect rect, gfx::Vector2d delta) {
+gfx::Rect ExpandRectByDelta(const gfx::Rect& rect, const gfx::Vector2d& delta) {
int width = rect.width() + std::abs(delta.x());
int height = rect.height() + std::abs(delta.y());
int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0);
}
bool TiledLayer::Update(ResourceUpdateQueue* queue,
- const OcclusionTracker* occlusion) {
+ const OcclusionTracker<Layer>* occlusion) {
DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped?
// Tiled layer always causes commits to wait for activation, as it does