Index: cc/surfaces/surface_aggregator.cc |
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc |
index 4c4408484e254c3009c05fe15ed33ba4e9b43210..7cb45a7b1fbae8cd79102a51ce74526fff2ae744 100644 |
--- a/cc/surfaces/surface_aggregator.cc |
+++ b/cc/surfaces/surface_aggregator.cc |
@@ -48,6 +48,31 @@ SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager, |
SurfaceAggregator::~SurfaceAggregator() {} |
+// Create a clip rect for an aggregated quad from the original clip rect and |
+// the clip rect from the surface it's on. |
+SurfaceAggregator::ClipData SurfaceAggregator::CalculateClipRect( |
+ const ClipData& surface_clip, |
+ const ClipData& quad_clip, |
+ const gfx::Transform& content_to_target_transform) { |
+ ClipData out_clip; |
+ if (surface_clip.is_clipped) |
+ out_clip = surface_clip; |
+ |
+ if (quad_clip.is_clipped) { |
+ // TODO(jamesr): This only works if content_to_target_transform maps integer |
+ // rects to integer rects. |
+ gfx::Rect final_clip = MathUtil::MapEnclosingClippedRect( |
+ content_to_target_transform, quad_clip.rect); |
+ if (out_clip.is_clipped) |
+ out_clip.rect.Intersect(final_clip); |
+ else |
+ out_clip.rect = final_clip; |
+ out_clip.is_clipped = true; |
+ } |
+ |
+ return out_clip; |
+} |
+ |
class SurfaceAggregator::RenderPassIdAllocator { |
public: |
explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {} |
@@ -163,9 +188,11 @@ gfx::Rect SurfaceAggregator::DamageRectForSurface(const Surface* surface, |
return full_rect; |
} |
-void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, |
- float opacity, |
- RenderPass* dest_pass) { |
+void SurfaceAggregator::HandleSurfaceQuad( |
+ const SurfaceDrawQuad* surface_quad, |
+ const gfx::Transform& content_to_target_transform, |
+ const ClipData& clip_rect, |
+ RenderPass* dest_pass) { |
SurfaceId surface_id = surface_quad->surface_id; |
// If this surface's id is already in our referenced set then it creates |
// a cycle in the graph and should be dropped. |
@@ -199,7 +226,7 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, |
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first; |
- bool merge_pass = copy_requests.empty(); |
+ bool merge_pass = surface_quad->opacity() == 1.f && copy_requests.empty(); |
const RenderPassList& referenced_passes = render_pass_list; |
size_t passes_to_copy = |
@@ -228,9 +255,11 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, |
// levels deep and add tests. |
copy_pass->transform_to_root_target.ConcatTransform( |
surface_quad->quadTransform()); |
+ copy_pass->transform_to_root_target.ConcatTransform( |
+ content_to_target_transform); |
CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, |
- gfx::Transform(), 1.f, copy_pass.get(), surface_id); |
+ gfx::Transform(), ClipData(), copy_pass.get(), surface_id); |
dest_pass_list_->push_back(copy_pass.Pass()); |
} |
@@ -240,17 +269,30 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, |
// TODO(jamesr): Clean up last pass special casing. |
const QuadList& quads = last_pass.quad_list; |
- // TODO(jamesr): Make sure clipping is enforced. |
- CopyQuadsToPass(quads, last_pass.shared_quad_state_list, |
- surface_quad->quadTransform(), |
- surface_quad->opacity() * opacity, dest_pass, surface_id); |
+ gfx::Transform surface_transform = surface_quad->quadTransform(); |
+ surface_transform.ConcatTransform(content_to_target_transform); |
+ |
+ // Intersect the transformed visible rect and the clip rect to create a |
+ // smaller cliprect for the quad. |
+ ClipData surface_quad_clip_rect( |
+ true, MathUtil::MapEnclosingClippedRect(surface_quad->quadTransform(), |
+ surface_quad->visible_rect)); |
+ if (surface_quad->isClipped()) |
+ surface_quad_clip_rect.rect.Intersect(surface_quad->clipRect()); |
+ |
+ ClipData quads_clip = CalculateClipRect(clip_rect, surface_quad_clip_rect, |
+ content_to_target_transform); |
+ |
+ CopyQuadsToPass(quads, last_pass.shared_quad_state_list, surface_transform, |
+ quads_clip, dest_pass, surface_id); |
} else { |
RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id); |
+ CopySharedQuadState(surface_quad->shared_quad_state, |
+ content_to_target_transform, clip_rect, dest_pass); |
+ |
SharedQuadState* shared_quad_state = |
- dest_pass->CreateAndAppendSharedQuadState(); |
- shared_quad_state->CopyFrom(surface_quad->shared_quad_state); |
- shared_quad_state->opacity *= opacity; |
+ dest_pass->shared_quad_state_list.back(); |
RenderPassDrawQuad* quad = |
dest_pass->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); |
quad->SetNew(shared_quad_state, |
@@ -277,6 +319,7 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, |
void SurfaceAggregator::CopySharedQuadState( |
const SharedQuadState* source_sqs, |
const gfx::Transform& content_to_target_transform, |
+ const ClipData& clip_rect, |
RenderPass* dest_render_pass) { |
SharedQuadState* copy_shared_quad_state = |
dest_render_pass->CreateAndAppendSharedQuadState(); |
@@ -289,17 +332,19 @@ void SurfaceAggregator::CopySharedQuadState( |
// transform is not identity. |
copy_shared_quad_state->content_to_target_transform.ConcatTransform( |
content_to_target_transform); |
- if (copy_shared_quad_state->is_clipped) { |
- copy_shared_quad_state->clip_rect = MathUtil::MapEnclosingClippedRect( |
- content_to_target_transform, copy_shared_quad_state->clip_rect); |
- } |
+ |
+ ClipData new_clip_rect = CalculateClipRect( |
+ clip_rect, ClipData(source_sqs->is_clipped, source_sqs->clip_rect), |
+ content_to_target_transform); |
+ copy_shared_quad_state->is_clipped = new_clip_rect.is_clipped; |
+ copy_shared_quad_state->clip_rect = new_clip_rect.rect; |
} |
void SurfaceAggregator::CopyQuadsToPass( |
const QuadList& source_quad_list, |
const SharedQuadStateList& source_shared_quad_state_list, |
const gfx::Transform& content_to_target_transform, |
- float opacity, |
+ const ClipData& clip_rect, |
RenderPass* dest_pass, |
SurfaceId surface_id) { |
const SharedQuadState* last_copied_source_shared_quad_state = NULL; |
@@ -315,12 +360,12 @@ void SurfaceAggregator::CopyQuadsToPass( |
if (quad->material == DrawQuad::SURFACE_CONTENT) { |
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); |
- HandleSurfaceQuad(surface_quad, opacity, dest_pass); |
+ HandleSurfaceQuad(surface_quad, content_to_target_transform, clip_rect, |
+ dest_pass); |
} else { |
if (quad->shared_quad_state != last_copied_source_shared_quad_state) { |
- CopySharedQuadState( |
- quad->shared_quad_state, content_to_target_transform, dest_pass); |
- dest_pass->shared_quad_state_list.back()->opacity *= opacity; |
+ CopySharedQuadState(quad->shared_quad_state, |
+ content_to_target_transform, clip_rect, dest_pass); |
last_copied_source_shared_quad_state = quad->shared_quad_state; |
} |
if (quad->material == DrawQuad::RENDER_PASS) { |
@@ -372,7 +417,7 @@ void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data, |
source.has_transparent_background); |
CopyQuadsToPass(source.quad_list, source.shared_quad_state_list, |
- gfx::Transform(), 1.f, copy_pass.get(), |
+ gfx::Transform(), ClipData(), copy_pass.get(), |
surface->surface_id()); |
dest_pass_list_->push_back(copy_pass.Pass()); |