Skip to content

Commit

Permalink
Avoid int->float->int conversion in OcclusionTracker for int translates.
Browse files Browse the repository at this point in the history
If the transform on a layer is an integer translation, we can easily
avoid converting the query rectangle to floats just to convert them
back to integers again. This is super costly.

Added a perftest for this. On an N4 the results are

Before: 20.553817749023438 us
After: 13.440165519714355 us

For about 35% reduction in time in this scnario.

Also renames MapClippedRect(Rect) to MapEnclosingClippedRect(Rect) to
describe what it does better, and audit callsides of MapClippedRect
to change any others that then ToEnclosingRect to call the
MapEnclosingClippedRect instead. Similar for Project.

R=enne
BUG=342848

Review URL: https://codereview.chromium.org/143293005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250739 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
danakj@chromium.org committed Feb 12, 2014
1 parent f734b22 commit 8a82269
Show file tree
Hide file tree
Showing 14 changed files with 209 additions and 50 deletions.
24 changes: 22 additions & 2 deletions cc/base/math_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,15 @@ static inline void AddVertexToClippedQuad(const gfx::PointF& new_vertex,
(*num_vertices_in_clipped_quad)++;
}

gfx::Rect MathUtil::MapClippedRect(const gfx::Transform& transform,
const gfx::Rect& src_rect) {
gfx::Rect MathUtil::MapEnclosingClippedRect(const gfx::Transform& transform,
const gfx::Rect& src_rect) {
if (transform.IsIdentityOrIntegerTranslation()) {
return src_rect +
gfx::Vector2d(
static_cast<int>(SkMScalarToFloat(transform.matrix().get(0, 3))),
static_cast<int>(
SkMScalarToFloat(transform.matrix().get(1, 3))));
}
return gfx::ToEnclosingRect(MapClippedRect(transform, gfx::RectF(src_rect)));
}

Expand Down Expand Up @@ -136,6 +143,19 @@ gfx::RectF MathUtil::MapClippedRect(const gfx::Transform& transform,
return ComputeEnclosingClippedRect(hc0, hc1, hc2, hc3);
}

gfx::Rect MathUtil::ProjectEnclosingClippedRect(const gfx::Transform& transform,
const gfx::Rect& src_rect) {
if (transform.IsIdentityOrIntegerTranslation()) {
return src_rect +
gfx::Vector2d(
static_cast<int>(SkMScalarToFloat(transform.matrix().get(0, 3))),
static_cast<int>(
SkMScalarToFloat(transform.matrix().get(1, 3))));
}
return gfx::ToEnclosingRect(
ProjectClippedRect(transform, gfx::RectF(src_rect)));
}

gfx::RectF MathUtil::ProjectClippedRect(const gfx::Transform& transform,
const gfx::RectF& src_rect) {
if (transform.IsIdentityOrTranslation()) {
Expand Down
6 changes: 4 additions & 2 deletions cc/base/math_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ class CC_EXPORT MathUtil {
//
// These functions return the axis-aligned rect that encloses the correctly
// clipped, transformed polygon.
static gfx::Rect MapClippedRect(const gfx::Transform& transform,
const gfx::Rect& rect);
static gfx::Rect MapEnclosingClippedRect(const gfx::Transform& transform,
const gfx::Rect& rect);
static gfx::RectF MapClippedRect(const gfx::Transform& transform,
const gfx::RectF& rect);
static gfx::Rect ProjectEnclosingClippedRect(const gfx::Transform& transform,
const gfx::Rect& rect);
static gfx::RectF ProjectClippedRect(const gfx::Transform& transform,
const gfx::RectF& rect);

Expand Down
1 change: 1 addition & 0 deletions cc/cc_tests.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
'test/run_all_perftests.cc',
'trees/layer_tree_host_common_perftest.cc',
'trees/layer_tree_host_perftest.cc',
'trees/occlusion_tracker_perftest.cc',
],
'include_dirs': [
'test',
Expand Down
4 changes: 2 additions & 2 deletions cc/debug/debug_rect_history.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ void DebugRectHistory::SavePropertyChangedRects(
if (layer->LayerPropertyChanged()) {
debug_rects_.push_back(
DebugRect(PROPERTY_CHANGED_RECT_TYPE,
MathUtil::MapClippedRect(
MathUtil::MapEnclosingClippedRect(
layer->screen_space_transform(),
gfx::RectF(gfx::PointF(), layer->content_bounds()))));
gfx::Rect(layer->content_bounds()))));
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions cc/layers/delegated_renderer_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -423,13 +423,14 @@ void DelegatedRendererLayerImpl::AppendRenderPassQuads(
DCHECK(!is_clipped());
DCHECK(render_surface());
DCHECK_EQ(0, num_unclipped_descendants());
output_shared_quad_state->clip_rect = MathUtil::MapClippedRect(
delegated_frame_to_target_transform,
output_shared_quad_state->clip_rect);
output_shared_quad_state->clip_rect =
MathUtil::MapEnclosingClippedRect(
delegated_frame_to_target_transform,
output_shared_quad_state->clip_rect);
} else {
gfx::Rect clip_rect = drawable_content_rect();
if (output_shared_quad_state->is_clipped) {
clip_rect.Intersect(MathUtil::MapClippedRect(
clip_rect.Intersect(MathUtil::MapEnclosingClippedRect(
delegated_frame_to_target_transform,
output_shared_quad_state->clip_rect));
}
Expand Down
5 changes: 2 additions & 3 deletions cc/layers/layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,8 @@ void LayerImpl::TakeCopyRequestsAndTransformToTarget(
gfx::Rect request_in_layer_space = request->area();
gfx::Rect request_in_content_space =
LayerRectToContentRect(request_in_layer_space);
request->set_area(
MathUtil::MapClippedRect(draw_properties_.target_space_transform,
request_in_content_space));
request->set_area(MathUtil::MapEnclosingClippedRect(
draw_properties_.target_space_transform, request_in_content_space));
}

layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
Expand Down
5 changes: 2 additions & 3 deletions cc/layers/picture_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,8 @@ void PictureLayerImpl::UpdateTilePriorities() {
gfx::Rect viewport_in_content_space;
gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization);
if (screen_space_transform().GetInverse(&screen_to_layer)) {
viewport_in_content_space =
gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
screen_to_layer, gfx::Rect(viewport_size)));
viewport_in_content_space = MathUtil::ProjectEnclosingClippedRect(
screen_to_layer, gfx::Rect(viewport_size));
}

WhichTree tree =
Expand Down
11 changes: 5 additions & 6 deletions cc/trees/layer_tree_host_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ inline gfx::Rect CalculateVisibleRectWithCachedLayerRect(
return layer_bound_rect;
}

gfx::Rect layer_rect = gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
surface_to_layer, gfx::RectF(minimal_surface_rect)));
gfx::Rect layer_rect = MathUtil::ProjectEnclosingClippedRect(
surface_to_layer, minimal_surface_rect);
layer_rect.Intersect(layer_bound_rect);
return layer_rect;
}
Expand All @@ -108,7 +108,7 @@ gfx::Rect LayerTreeHostCommon::CalculateVisibleRect(
const gfx::Rect& layer_bound_rect,
const gfx::Transform& transform) {
gfx::Rect layer_in_surface_space =
MathUtil::MapClippedRect(transform, layer_bound_rect);
MathUtil::MapEnclosingClippedRect(transform, layer_bound_rect);
return CalculateVisibleRectWithCachedLayerRect(
target_surface_rect, layer_bound_rect, layer_in_surface_space, transform);
}
Expand Down Expand Up @@ -1739,9 +1739,8 @@ static void CalculateDrawPropertiesInternal(
// here, or DCHECK that the transform is invertible.
}

gfx::Rect projected_surface_rect = gfx::ToEnclosingRect(
MathUtil::ProjectClippedRect(inverse_surface_draw_transform,
ancestor_clip_rect_in_target_space));
gfx::Rect projected_surface_rect = MathUtil::ProjectEnclosingClippedRect(
inverse_surface_draw_transform, ancestor_clip_rect_in_target_space);

if (layer_draw_properties.num_unclipped_descendants > 0) {
// If we have unclipped descendants, we cannot count on the render
Expand Down
8 changes: 4 additions & 4 deletions cc/trees/layer_tree_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,8 @@ static void AppendQuadsToFillScreen(
fill_rects.next()) {
// The root layer transform is composed of translations and scales only,
// no perspective, so mapping is sufficient (as opposed to projecting).
gfx::Rect layer_rect =
MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
gfx::Rect layer_rect = MathUtil::MapEnclosingClippedRect(
transform_to_layer_space, fill_rects.rect());
// Skip the quad culler and just append the quads directly to avoid
// occlusion checks.
scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
Expand All @@ -678,8 +678,8 @@ static void AppendQuadsToFillScreen(
fill_rects.has_rect();
fill_rects.next()) {
DCHECK(overhang_resource_id);
gfx::Rect layer_rect =
MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect());
gfx::Rect layer_rect = MathUtil::MapEnclosingClippedRect(
transform_to_layer_space, fill_rects.rect());
scoped_ptr<TextureDrawQuad> tex_quad = TextureDrawQuad::Create();
const float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
tex_quad->SetNew(
Expand Down
5 changes: 2 additions & 3 deletions cc/trees/layer_tree_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,8 @@ gfx::Rect LayerTreeImpl::RootScrollLayerDeviceViewportBounds() const {
if (!root_scroll_layer || root_scroll_layer->children().empty())
return gfx::Rect();
LayerImpl* layer = root_scroll_layer->children()[0];
return MathUtil::MapClippedRect(
layer->screen_space_transform(),
gfx::Rect(layer->content_bounds()));
return MathUtil::MapEnclosingClippedRect(layer->screen_space_transform(),
gfx::Rect(layer->content_bounds()));
}

static void ApplySentScrollDeltasFromAbortedCommitTo(LayerImpl* layer) {
Expand Down
34 changes: 16 additions & 18 deletions cc/trees/occlusion_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ static gfx::Rect ScreenSpaceClipRectInTargetSurface(
&inverse_screen_space_transform))
return target_surface->content_rect();

return gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
inverse_screen_space_transform, screen_space_clip_rect));
return MathUtil::ProjectEnclosingClippedRect(inverse_screen_space_transform,
screen_space_clip_rect);
}

template <typename RenderSurfaceType>
Expand Down Expand Up @@ -248,8 +248,8 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer,
if (surface_rect.IsEmpty())
return;

gfx::Rect affected_area_in_target = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(surface_transform, gfx::RectF(surface_rect)));
gfx::Rect affected_area_in_target =
MathUtil::MapEnclosingClippedRect(surface_transform, surface_rect);
if (contributing_layer->render_surface()->is_clipped()) {
affected_area_in_target.Intersect(
contributing_layer->render_surface()->clip_rect());
Expand Down Expand Up @@ -529,8 +529,8 @@ bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(

// Take the ToEnclosingRect at each step, as we want to contain any unoccluded
// partial pixels in the resulting Rect.
Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
Region unoccluded_region_in_target_surface =
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_inside_target);
gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
Expand Down Expand Up @@ -578,18 +578,17 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::

// Take the ToEnclosingRect at each step, as we want to contain any unoccluded
// partial pixels in the resulting Rect.
Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
Region unoccluded_region_in_target_surface =
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_inside_target);
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_outside_target);

gfx::RectF unoccluded_rect_in_target_surface =
gfx::Rect unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
gfx::Rect unoccluded_rect = gfx::ToEnclosingRect(
MathUtil::ProjectClippedRect(inverse_draw_transform,
unoccluded_rect_in_target_surface));
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect(
inverse_draw_transform, unoccluded_rect_in_target_surface);
unoccluded_rect.Intersect(content_rect);

return unoccluded_rect;
Expand Down Expand Up @@ -636,8 +635,8 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::

// Take the ToEnclosingRect at each step, as we want to contain any unoccluded
// partial pixels in the resulting Rect.
Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
Region unoccluded_region_in_target_surface =
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
// Layers can't clip across surfaces, so count this as internal occlusion.
if (surface->is_clipped())
unoccluded_region_in_target_surface.Intersect(surface->clip_rect());
Expand All @@ -657,11 +656,10 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
contributing_surface_render_target->render_surface(),
screen_space_clip_rect_));

gfx::RectF unoccluded_rect_in_target_surface =
gfx::Rect unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
gfx::Rect unoccluded_rect = gfx::ToEnclosingRect(
MathUtil::ProjectClippedRect(inverse_draw_transform,
unoccluded_rect_in_target_surface));
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect(
inverse_draw_transform, unoccluded_rect_in_target_surface);
unoccluded_rect.Intersect(content_rect);

return unoccluded_rect;
Expand Down
Loading

0 comments on commit 8a82269

Please sign in to comment.