exo: Apply full surface damage on non-buffer changes

Setting certain surface values such as the plane alpha should
effectively damage the entire surface. The complete set seemed to be the
scale, blending mode, plane alpha, viewport rectangle, and clip rectangle.

Bug: 754548
Change-Id: I4ee8a47bdfcdbb1be4ae10b43fbf140aae25311c
Reviewed-on: https://chromium-review.googlesource.com/611619
Commit-Queue: Lloyd Pique <[email protected]>
Reviewed-by: David Reveman <[email protected]>
Cr-Commit-Position: refs/heads/master@{#494595}
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 298905cb..7cf62869 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -411,9 +411,22 @@
     std::list<PresentationCallback>* presentation_callbacks) {
   bool needs_commit =
       frame_type == FRAME_TYPE_COMMIT && needs_commit_surface_hierarchy_;
+  bool needs_full_damage = frame_type == FRAME_TYPE_RECREATED_RESOURCES;
+
   if (needs_commit) {
     needs_commit_surface_hierarchy_ = false;
 
+    if (pending_state_.opaque_region != state_.opaque_region ||
+        pending_state_.buffer_scale != state_.buffer_scale ||
+        pending_state_.viewport != state_.viewport ||
+        pending_state_.crop != state_.crop ||
+        pending_state_.only_visible_on_secure_output !=
+            state_.only_visible_on_secure_output ||
+        pending_state_.blend_mode != state_.blend_mode ||
+        pending_state_.alpha != state_.alpha) {
+      needs_full_damage = true;
+    }
+
     state_ = pending_state_;
     pending_state_.only_visible_on_secure_output = false;
 
@@ -470,7 +483,7 @@
         frame_sink_holder, frame, frame_callbacks, presentation_callbacks);
   }
 
-  AppendContentsToFrame(origin, frame_type, frame);
+  AppendContentsToFrame(origin, frame, needs_full_damage);
 
   // Reset damage.
   if (needs_commit)
@@ -639,23 +652,20 @@
 }
 
 void Surface::AppendContentsToFrame(const gfx::Point& origin,
-                                    FrameType frame_type,
-                                    cc::CompositorFrame* frame) {
+                                    cc::CompositorFrame* frame,
+                                    bool needs_full_damage) {
   const std::unique_ptr<cc::RenderPass>& render_pass =
       frame->render_pass_list.back();
   gfx::Rect output_rect = gfx::Rect(origin, content_size_);
   gfx::Rect quad_rect = output_rect;
   gfx::Rect damage_rect;
-  switch (frame_type) {
-    case FRAME_TYPE_COMMIT:
-      // pending_damage_ is in Surface coordinates.
-      damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
-      damage_rect.set_origin(origin);
-      damage_rect.Intersect(output_rect);
-      break;
-    case FRAME_TYPE_RECREATED_RESOURCES:
-      damage_rect = output_rect;
-      break;
+  if (needs_full_damage) {
+    damage_rect = output_rect;
+  } else {
+    // pending_damage_ is in Surface coordinates.
+    damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
+    damage_rect.set_origin(origin);
+    damage_rect.Intersect(output_rect);
   }
 
   render_pass->damage_rect.Union(damage_rect);
diff --git a/components/exo/surface.h b/components/exo/surface.h
index 211d3ee..41cc351 100644
--- a/components/exo/surface.h
+++ b/components/exo/surface.h
@@ -261,8 +261,8 @@
   // Puts the current surface into a draw quad, and appends the draw quads into
   // the |frame|.
   void AppendContentsToFrame(const gfx::Point& origin,
-                             FrameType frame_type,
-                             cc::CompositorFrame* frame);
+                             cc::CompositorFrame* frame,
+                             bool needs_full_damage);
 
   void UpdateContentSize();
 
diff --git a/components/exo/surface_unittest.cc b/components/exo/surface_unittest.cc
index 4eba0f3..98bf020e 100644
--- a/components/exo/surface_unittest.cc
+++ b/components/exo/surface_unittest.cc
@@ -136,6 +136,8 @@
     EXPECT_FALSE(frame.render_pass_list.back()
                      ->quad_list.back()
                      ->ShouldDrawWithBlending());
+    EXPECT_EQ(gfx::Rect(0, 0, 1, 1),
+              frame.render_pass_list.back()->damage_rect);
   }
 
   // Setting an empty opaque region requires draw with blending.
@@ -150,6 +152,8 @@
     EXPECT_TRUE(frame.render_pass_list.back()
                     ->quad_list.back()
                     ->ShouldDrawWithBlending());
+    EXPECT_EQ(gfx::Rect(0, 0, 1, 1),
+              frame.render_pass_list.back()->damage_rect);
   }
 
   std::unique_ptr<Buffer> buffer_without_alpha(
@@ -169,6 +173,8 @@
     EXPECT_FALSE(frame.render_pass_list.back()
                      ->quad_list.back()
                      ->ShouldDrawWithBlending());
+    EXPECT_EQ(gfx::Rect(0, 0, 0, 0),
+              frame.render_pass_list.back()->damage_rect);
   }
 }
 
@@ -201,6 +207,13 @@
   EXPECT_EQ(
       gfx::ScaleToFlooredSize(buffer_size, 1.0f / kBufferScale).ToString(),
       surface->content_size().ToString());
+
+  RunAllPendingInMessageLoop();
+
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
+  ASSERT_EQ(1u, frame.render_pass_list.size());
+  EXPECT_EQ(gfx::Rect(0, 0, 256, 256),
+            frame.render_pass_list.back()->damage_rect);
 }
 
 TEST_F(SurfaceTest, MirrorLayers) {
@@ -247,6 +260,13 @@
   EXPECT_EQ(viewport2.ToString(),
             surface->window()->bounds().size().ToString());
   EXPECT_EQ(viewport2.ToString(), surface->content_size().ToString());
+
+  RunAllPendingInMessageLoop();
+
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
+  ASSERT_EQ(1u, frame.render_pass_list.size());
+  EXPECT_EQ(gfx::Rect(0, 0, 512, 512),
+            frame.render_pass_list.back()->damage_rect);
 }
 
 TEST_F(SurfaceTest, SetCrop) {
@@ -263,6 +283,13 @@
   EXPECT_EQ(crop_size.ToString(),
             surface->window()->bounds().size().ToString());
   EXPECT_EQ(crop_size.ToString(), surface->content_size().ToString());
+
+  RunAllPendingInMessageLoop();
+
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
+  ASSERT_EQ(1u, frame.render_pass_list.size());
+  EXPECT_EQ(gfx::Rect(0, 0, 12, 12),
+            frame.render_pass_list.back()->damage_rect);
 }
 
 TEST_F(SurfaceTest, SetBlendMode) {
@@ -319,6 +346,11 @@
   surface->Attach(buffer.get());
   surface->SetAlpha(0.5f);
   surface->Commit();
+  RunAllPendingInMessageLoop();
+
+  const cc::CompositorFrame& frame = GetFrameFromSurface(shell_surface.get());
+  ASSERT_EQ(1u, frame.render_pass_list.size());
+  EXPECT_EQ(gfx::Rect(0, 0, 1, 1), frame.render_pass_list.back()->damage_rect);
 }
 
 TEST_F(SurfaceTest, Commit) {