#include <algorithm>
#include "cc/base/math_util.h"
-#include "cc/debug/overdraw_metrics.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface.h"
namespace cc {
-template <typename LayerType, typename RenderSurfaceType>
-OcclusionTrackerBase<LayerType, RenderSurfaceType>::OcclusionTrackerBase(
- const gfx::Rect& screen_space_clip_rect, bool record_metrics_for_frame)
+template <typename LayerType>
+OcclusionTracker<LayerType>::OcclusionTracker(
+ const gfx::Rect& screen_space_clip_rect)
: screen_space_clip_rect_(screen_space_clip_rect),
- overdraw_metrics_(OverdrawMetrics::Create(record_metrics_for_frame)),
occluding_screen_space_rects_(NULL),
non_occluding_screen_space_rects_(NULL) {}
-template <typename LayerType, typename RenderSurfaceType>
-OcclusionTrackerBase<LayerType, RenderSurfaceType>::~OcclusionTrackerBase() {}
+template <typename LayerType>
+OcclusionTracker<LayerType>::~OcclusionTracker() {}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::EnterLayer(
const LayerIteratorPosition<LayerType>& layer_iterator) {
LayerType* render_target = layer_iterator.target_render_surface_layer;
FinishedRenderTarget(render_target);
}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveLayer(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::LeaveLayer(
const LayerIteratorPosition<LayerType>& layer_iterator) {
LayerType* render_target = layer_iterator.target_render_surface_layer;
}
static inline bool LayerIsInUnsorted3dRenderingContext(const Layer* layer) {
- return layer->is_3d_sorted();
+ return layer->Is3dSorted();
}
static inline bool LayerIsInUnsorted3dRenderingContext(const LayerImpl* layer) {
return false;
(layer->parent() && LayerIsHidden(layer->parent()));
}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::EnterRenderTarget(
const LayerType* new_target) {
if (!stack_.empty() && stack_.back().target == new_target)
return;
const LayerType* old_target = NULL;
- const RenderSurfaceType* old_occlusion_immune_ancestor = NULL;
+ const typename LayerType::RenderSurfaceType* old_occlusion_immune_ancestor =
+ NULL;
if (!stack_.empty()) {
old_target = stack_.back().target;
old_occlusion_immune_ancestor =
old_target->render_surface()->nearest_occlusion_immune_ancestor();
}
- const RenderSurfaceType* new_occlusion_immune_ancestor =
+ const typename LayerType::RenderSurfaceType* new_occlusion_immune_ancestor =
new_target->render_surface()->nearest_occlusion_immune_ancestor();
stack_.push_back(StackObject(new_target));
inverse_new_target_screen_space_transform,
old_target->render_surface()->screen_space_transform());
stack_[last_index].occlusion_from_outside_target =
- TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+ TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
stack_[last_index - 1].occlusion_from_outside_target,
false,
gfx::Rect(),
old_target_to_new_target_transform);
stack_[last_index].occlusion_from_outside_target.Union(
- TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+ TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
stack_[last_index - 1].occlusion_from_inside_target,
false,
gfx::Rect(),
old_target_to_new_target_transform));
}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::FinishedRenderTarget(
const LayerType* finished_target) {
// Make sure we know about the target surface.
EnterRenderTarget(finished_target);
- RenderSurfaceType* surface = finished_target->render_surface();
+ typename LayerType::RenderSurfaceType* surface =
+ finished_target->render_surface();
// Readbacks always happen on render targets so we only need to check
// for readbacks here.
}
}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::LeaveToRenderTarget(
const LayerType* new_target) {
int last_index = stack_.size() - 1;
bool surface_will_be_at_top_after_pop =
// merged out as well but needs to be transformed to the new target.
const LayerType* old_target = stack_[last_index].target;
- const RenderSurfaceType* old_surface = old_target->render_surface();
+ const typename LayerType::RenderSurfaceType* old_surface =
+ old_target->render_surface();
Region old_occlusion_from_inside_target_in_new_target =
- TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+ TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
stack_[last_index].occlusion_from_inside_target,
old_surface->is_clipped(),
old_surface->clip_rect(),
old_surface->draw_transform());
if (old_target->has_replica() && !old_target->replica_has_mask()) {
old_occlusion_from_inside_target_in_new_target.Union(
- TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+ TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
stack_[last_index].occlusion_from_inside_target,
old_surface->is_clipped(),
old_surface->clip_rect(),
}
Region old_occlusion_from_outside_target_in_new_target =
- TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+ TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
stack_[last_index].occlusion_from_outside_target,
false,
gfx::Rect(),
gfx::Rect unoccluded_replica_rect;
if (old_target->background_filters().HasFilterThatMovesPixels()) {
unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect(
- old_target, false, old_surface->content_rect());
+ old_surface->content_rect(), old_surface->draw_transform());
if (old_target->has_replica()) {
unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect(
- old_target, true, old_surface->content_rect());
+ old_surface->content_rect(),
+ old_surface->replica_draw_transform());
}
}
&stack_.back().occlusion_from_outside_target);
}
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
- MarkOccludedBehindLayer(const LayerType* layer) {
+template <typename LayerType>
+void OcclusionTracker<LayerType>::MarkOccludedBehindLayer(
+ const LayerType* layer) {
DCHECK(!stack_.empty());
DCHECK_EQ(layer->render_target(), stack_.back().target);
if (stack_.empty())
return;
- if (!layer->DrawsContent())
- return;
-
if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1)
return;
}
}
-template <typename LayerType, typename RenderSurfaceType>
-bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
+template <typename LayerType>
+bool OcclusionTracker<LayerType>::Occluded(
const LayerType* render_target,
const gfx::Rect& content_rect,
- const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown) const {
+ const gfx::Transform& draw_transform) const {
DCHECK(!stack_.empty());
if (stack_.empty())
return false;
if (content_rect.IsEmpty())
return true;
- if (impl_draw_transform_is_unknown)
- return false;
// For tests with no render target.
if (!render_target)
return unoccluded_rect_in_target_surface.IsEmpty();
}
-template <typename LayerType, typename RenderSurfaceType>
-gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
- UnoccludedContentRect(
- const LayerType* render_target,
- const gfx::Rect& content_rect,
- const gfx::Transform& draw_transform,
- bool impl_draw_transform_is_unknown) const {
- DCHECK(!stack_.empty());
+template <typename LayerType>
+gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect(
+ const gfx::Rect& content_rect,
+ const gfx::Transform& draw_transform) const {
if (stack_.empty())
return content_rect;
if (content_rect.IsEmpty())
return content_rect;
- if (impl_draw_transform_is_unknown)
- return content_rect;
-
- // For tests with no render target.
- if (!render_target)
- return content_rect;
-
- DCHECK_EQ(render_target->render_target(), render_target);
- DCHECK(render_target->render_surface());
- DCHECK_EQ(render_target, stack_.back().target);
if (stack_.back().occlusion_from_inside_target.IsEmpty() &&
stack_.back().occlusion_from_outside_target.IsEmpty()) {
unoccluded_region_in_target_surface.Subtract(
stack_.back().occlusion_from_outside_target);
+ if (unoccluded_region_in_target_surface.IsEmpty())
+ return gfx::Rect();
+
gfx::Rect unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect(
return unoccluded_rect;
}
-template <typename LayerType, typename RenderSurfaceType>
-gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
- UnoccludedContributingSurfaceContentRect(
- const LayerType* layer,
- bool for_replica,
- const gfx::Rect& content_rect) const {
- DCHECK(!stack_.empty());
- // The layer is a contributing render_target so it should have a surface.
- DCHECK(layer->render_surface());
- // The layer is a contributing render_target so its target should be itself.
- DCHECK_EQ(layer->render_target(), layer);
- // The layer should not be the root, else what is is contributing to?
- DCHECK(layer->parent());
- // This should be called while the layer is still considered the current
- // target in the occlusion tracker.
- DCHECK_EQ(layer, stack_.back().target);
-
+template <typename LayerType>
+gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect(
+ const gfx::Rect& content_rect,
+ const gfx::Transform& draw_transform) const {
if (content_rect.IsEmpty())
return content_rect;
- const RenderSurfaceType* surface = layer->render_surface();
- const LayerType* contributing_surface_render_target =
- layer->parent()->render_target();
+ // A contributing surface doesn't get occluded by things inside its own
+ // surface, so only things outside the surface can occlude it. That occlusion
+ // is found just below the top of the stack (if it exists).
+ bool has_occlusion = stack_.size() > 1;
+ if (!has_occlusion)
+ return content_rect;
+
+ const StackObject& second_last = stack_[stack_.size() - 2];
- if (!SurfaceTransformsToTargetKnown(surface))
+ if (second_last.occlusion_from_inside_target.IsEmpty() &&
+ second_last.occlusion_from_outside_target.IsEmpty())
return content_rect;
- gfx::Transform draw_transform =
- for_replica ? surface->replica_draw_transform()
- : surface->draw_transform();
gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
if (!draw_transform.GetInverse(&inverse_draw_transform))
return content_rect;
- // A contributing surface doesn't get occluded by things inside its own
- // surface, so only things outside the surface can occlude it. That occlusion
- // is found just below the top of the stack (if it exists).
- bool has_occlusion = stack_.size() > 1;
-
// 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 =
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());
- if (has_occlusion) {
- const StackObject& second_last = stack_[stack_.size() - 2];
- unoccluded_region_in_target_surface.Subtract(
- second_last.occlusion_from_inside_target);
- unoccluded_region_in_target_surface.Subtract(
- second_last.occlusion_from_outside_target);
- }
+ unoccluded_region_in_target_surface.Subtract(
+ second_last.occlusion_from_inside_target);
+ unoccluded_region_in_target_surface.Subtract(
+ second_last.occlusion_from_outside_target);
- // Treat other clipping as occlusion from outside the target surface.
- unoccluded_region_in_target_surface.Intersect(
- contributing_surface_render_target->render_surface()->content_rect());
- unoccluded_region_in_target_surface.Intersect(
- ScreenSpaceClipRectInTargetSurface(
- contributing_surface_render_target->render_surface(),
- screen_space_clip_rect_));
+ if (unoccluded_region_in_target_surface.IsEmpty())
+ return gfx::Rect();
gfx::Rect unoccluded_rect_in_target_surface =
unoccluded_region_in_target_surface.bounds();
}
// Instantiate (and export) templates here for the linker.
-template class OcclusionTrackerBase<Layer, RenderSurface>;
-template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>;
+template class OcclusionTracker<Layer>;
+template class OcclusionTracker<LayerImpl>;
} // namespace cc