Avoid sending empty OnRepaint msgs and propagate window damage correctly

This fixes two issues related to OnRepaint (window damage) messages:

1.) In the case of a renderer-resized widget, the browser's information about
the size of the widget could be out of date. If the browser widget was asked to
paint in compositing mode before it received the proper size it could send a
ViewMsg_OnRepaint with 0x0 size and then set repaint_ack_pending_, expecting the
renderer to reply. The renderer wasn't actually replying with a frame since
damaging a 0x0 rect doesn't actually require painting anything. This suppresses
sending the OnRepaint message if the browser's size is 0x0. Either the size will
at some point become 0x0, triggering a repaint, or the user will never see it.

2.) In compositing mode on the renderer side we weren't plumbing the OnRepaint
window damage rect properly in to the compositor. Thus the compositor could end
up not producing a frame after receiving an OnRepaint message, confusing the
browser rate limiting logic greatly.

BUG=230766

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194510 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index fa74f6f6..d84036b 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -274,6 +274,10 @@
 
 void RenderWidgetHostImpl::ResetSizeAndRepaintPendingFlags() {
   resize_ack_pending_ = false;
+  if (repaint_ack_pending_) {
+    TRACE_EVENT_ASYNC_END0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
+  }
   repaint_ack_pending_ = false;
   in_flight_size_.SetSize(0, 0);
 }
@@ -699,6 +703,8 @@
   if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
     repaint_start_time_ = TimeTicks::Now();
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, view_size));
   }
 
@@ -760,7 +766,8 @@
 }
 
 void RenderWidgetHostImpl::ScheduleComposite() {
-  if (is_hidden_ || !is_accelerated_compositing_active_) {
+  if (is_hidden_ || !is_accelerated_compositing_active_ ||
+      current_size_.IsEmpty()) {
       return;
   }
 
@@ -768,6 +775,8 @@
   if (!repaint_ack_pending_ && !resize_ack_pending_ && !view_being_painted_) {
     repaint_start_time_ = TimeTicks::Now();
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, current_size_));
   }
 }
@@ -1651,6 +1660,9 @@
   bool is_repaint_ack =
       ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
   if (is_repaint_ack) {
+    DCHECK(repaint_ack_pending_);
+    TRACE_EVENT_ASYNC_END0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     repaint_ack_pending_ = false;
     TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
     UMA_HISTOGRAM_TIMES("MPArch.RWH_RepaintDelta", delta);
@@ -2159,7 +2171,10 @@
                                            &scheduled_completion_callback);
   if (needs_full_paint) {
     repaint_start_time_ = TimeTicks::Now();
+    DCHECK(!repaint_ack_pending_);
     repaint_ack_pending_ = true;
+    TRACE_EVENT_ASYNC_BEGIN0(
+        "renderer_host", "RenderWidgetHostImpl::repaint_ack_pending_", this);
     Send(new ViewMsg_Repaint(routing_id_, view_size));
   }
 
diff --git a/content/common/gpu/image_transport_surface.cc b/content/common/gpu/image_transport_surface.cc
index 18689b8..1378f90 100644
--- a/content/common/gpu/image_transport_surface.cc
+++ b/content/common/gpu/image_transport_surface.cc
@@ -322,6 +322,7 @@
   DCHECK(transport_);
   Resize(new_size_);
 
+  TRACE_EVENT_ASYNC_END0("gpu", "OnResize", this);
   helper_->SetScheduled(true);
 }
 
@@ -331,6 +332,8 @@
   if (transport_) {
     helper_->SendResizeView(size);
     helper_->SetScheduled(false);
+    TRACE_EVENT_ASYNC_BEGIN2("gpu", "OnResize", this,
+                             "width", size.width(), "height", size.height());
   } else {
     Resize(new_size_);
   }
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index fc2caddc..47587c0 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -334,6 +334,10 @@
   layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height);
 }
 
+void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) {
+  layer_tree_host_->SetNeedsRedrawRect(damage_rect);
+}
+
 bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) {
   scoped_ptr<cc::Thread> impl_thread;
   scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy =
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h
index a442526..76686da 100644
--- a/content/renderer/gpu/render_widget_compositor.h
+++ b/content/renderer/gpu/render_widget_compositor.h
@@ -11,6 +11,7 @@
 #include "cc/trees/layer_tree_settings.h"
 #include "skia/ext/refptr.h"
 #include "third_party/WebKit/Source/Platform/chromium/public/WebLayerTreeView.h"
+#include "ui/gfx/rect.h"
 
 class SkPicture;
 
@@ -39,6 +40,7 @@
                               bool enable_showing,
                               bool animate);
   void SetOverdrawBottomHeight(float overdraw_bottom_height);
+  void SetNeedsRedrawRect(gfx::Rect damage_rect);
 
   // WebLayerTreeView implementation.
   virtual void setSurfaceReady();
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index f58b8a0..01f9089 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1871,16 +1871,20 @@
   return true;
 }
 
-void RenderWidget::OnRepaint(const gfx::Size& size_to_paint) {
+void RenderWidget::OnRepaint(gfx::Size size_to_paint) {
   // During shutdown we can just ignore this message.
   if (!webwidget_)
     return;
 
+  // Even if the browser provides an empty damage rect, it's still expecting to
+  // receive a repaint ack so just damage the entire widget bounds.
+  if (size_to_paint.IsEmpty()) {
+    size_to_paint = size_;
+  }
+
   set_next_paint_is_repaint_ack();
-  if (is_accelerated_compositing_active_) {
-    if (compositor_)
-      compositor_->setNeedsRedraw();
-    scheduleComposite();
+  if (is_accelerated_compositing_active_ && compositor_) {
+    compositor_->SetNeedsRedrawRect(gfx::Rect(size_to_paint));
   } else {
     gfx::Rect repaint_rect(size_to_paint.width(), size_to_paint.height());
     didInvalidateRect(repaint_rect);
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 47c8ca4..f3b0f03 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -308,7 +308,7 @@
                      int tag,
                      const gfx::Size& page_size,
                      const gfx::Size& desired_size);
-  void OnRepaint(const gfx::Size& size_to_paint);
+  void OnRepaint(gfx::Size size_to_paint);
   void OnSmoothScrollCompleted(int gesture_id);
   void OnSetTextDirection(WebKit::WebTextDirection direction);
   void OnGetFPS();