Tile priority in Android WebView

Cherry pick of chromium r286731

Conflicts:
        cc/layers/picture_layer_impl_unittest.cc

Original Description:
Tiling priorities in Android Webview.

Use the parent compositor's clip and transform for tile
priorities in child compositor.

When the transform matrix changes in parent compositor
(hardware_renderer.cc), it posts the matrix and the clip to
the child compositor. (The parent clip is in screen space
and the parent matrix transforms from webview space to
screen space) Child compositor will use them for tile
prioritization.

In child compositor during updating tile priority, the clip
from parent is transformed from screen space to view space,
then from view space to content space. Then the result rect
will intersect with content_bounds() and the intersection
is used as tile priority input.

BUG:15771042
Change-Id: I3d1625f46649f032215810729d24717e5faceff7
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 2efc46c..a01b499 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -190,6 +190,8 @@
         'browser/net/init_native_callback.h',
         'browser/net/input_stream_reader.cc',
         'browser/net/input_stream_reader.h',
+        'browser/parent_compositor_draw_constraints.cc',
+        'browser/parent_compositor_draw_constraints.h',
         'browser/parent_output_surface.cc',
         'browser/parent_output_surface.h',
         'browser/renderer_host/aw_render_view_host_ext.cc',
diff --git a/android_webview/android_webview_common.target.darwin-arm.mk b/android_webview/android_webview_common.target.darwin-arm.mk
index e19a13b..9f3b0ce 100644
--- a/android_webview/android_webview_common.target.darwin-arm.mk
+++ b/android_webview/android_webview_common.target.darwin-arm.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.darwin-arm64.mk b/android_webview/android_webview_common.target.darwin-arm64.mk
index 42b6eee..2360d099 100644
--- a/android_webview/android_webview_common.target.darwin-arm64.mk
+++ b/android_webview/android_webview_common.target.darwin-arm64.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.darwin-mips.mk b/android_webview/android_webview_common.target.darwin-mips.mk
index 17fd1f8..4aee34b 100644
--- a/android_webview/android_webview_common.target.darwin-mips.mk
+++ b/android_webview/android_webview_common.target.darwin-mips.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.darwin-x86.mk b/android_webview/android_webview_common.target.darwin-x86.mk
index 73d4359..1b5cd85 100644
--- a/android_webview/android_webview_common.target.darwin-x86.mk
+++ b/android_webview/android_webview_common.target.darwin-x86.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.darwin-x86_64.mk b/android_webview/android_webview_common.target.darwin-x86_64.mk
index 320cfac..9dc3726 100644
--- a/android_webview/android_webview_common.target.darwin-x86_64.mk
+++ b/android_webview/android_webview_common.target.darwin-x86_64.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.linux-arm.mk b/android_webview/android_webview_common.target.linux-arm.mk
index e19a13b..9f3b0ce 100644
--- a/android_webview/android_webview_common.target.linux-arm.mk
+++ b/android_webview/android_webview_common.target.linux-arm.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.linux-arm64.mk b/android_webview/android_webview_common.target.linux-arm64.mk
index 42b6eee..2360d099 100644
--- a/android_webview/android_webview_common.target.linux-arm64.mk
+++ b/android_webview/android_webview_common.target.linux-arm64.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.linux-mips.mk b/android_webview/android_webview_common.target.linux-mips.mk
index 17fd1f8..4aee34b 100644
--- a/android_webview/android_webview_common.target.linux-mips.mk
+++ b/android_webview/android_webview_common.target.linux-mips.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.linux-x86.mk b/android_webview/android_webview_common.target.linux-x86.mk
index 73d4359..1b5cd85 100644
--- a/android_webview/android_webview_common.target.linux-x86.mk
+++ b/android_webview/android_webview_common.target.linux-x86.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/android_webview_common.target.linux-x86_64.mk b/android_webview/android_webview_common.target.linux-x86_64.mk
index 320cfac..9dc3726 100644
--- a/android_webview/android_webview_common.target.linux-x86_64.mk
+++ b/android_webview/android_webview_common.target.linux-x86_64.mk
@@ -62,6 +62,7 @@
 	android_webview/browser/net/aw_url_request_job_factory.cc \
 	android_webview/browser/net_disk_cache_remover.cc \
 	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/parent_compositor_draw_constraints.cc \
 	android_webview/browser/parent_output_surface.cc \
 	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
 	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index c2875bc..bba3e4a 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -255,14 +255,29 @@
   draw_gl_input->width = width_;
   draw_gl_input->height = height_;
 
-  gfx::Transform transform;
+  parent_draw_constraints_ = shared_renderer_state_->ParentDrawConstraints();
   gfx::Size surface_size(width_, height_);
   gfx::Rect viewport(surface_size);
-  // TODO(boliu): Should really be |last_on_draw_global_visible_rect_|.
-  // See crbug.com/372073.
   gfx::Rect clip = viewport;
-  scoped_ptr<cc::CompositorFrame> frame = compositor_->DemandDrawHw(
-      surface_size, transform, viewport, clip);
+  gfx::Transform transform_for_tile_priority =
+      parent_draw_constraints_.transform;
+
+  // If the WebView is on a layer, WebView does not know what transform is
+  // applied onto the layer so global visible rect does not make sense here.
+  // In this case, just use the surface rect for tiling.
+  gfx::Rect viewport_rect_for_tile_priority;
+  if (parent_draw_constraints_.is_layer)
+    viewport_rect_for_tile_priority = parent_draw_constraints_.surface_rect;
+  else
+    viewport_rect_for_tile_priority = last_on_draw_global_visible_rect_;
+
+  scoped_ptr<cc::CompositorFrame> frame =
+      compositor_->DemandDrawHw(surface_size,
+                                gfx::Transform(),
+                                viewport,
+                                clip,
+                                viewport_rect_for_tile_priority,
+                                transform_for_tile_priority);
   if (!frame.get())
     return false;
 
@@ -275,6 +290,14 @@
   return client_->RequestDrawGL(java_canvas, false);
 }
 
+void BrowserViewRenderer::UpdateParentDrawConstraints() {
+  // Post an invalidate if the parent draw constraints are stale and there is
+  // no pending invalidate.
+  if (!parent_draw_constraints_.Equals(
+          shared_renderer_state_->ParentDrawConstraints()))
+    EnsureContinuousInvalidation(true);
+}
+
 void BrowserViewRenderer::ReturnUnusedResource(scoped_ptr<DrawGLInput> input) {
   if (!input.get())
     return;
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index e130334..bf660df 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -7,6 +7,7 @@
 
 #include "android_webview/browser/global_tile_manager.h"
 #include "android_webview/browser/global_tile_manager_client.h"
+#include "android_webview/browser/parent_compositor_draw_constraints.h"
 #include "android_webview/browser/shared_renderer_state.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/callback.h"
@@ -140,6 +141,8 @@
   virtual void SetNumTiles(size_t num_tiles,
                            bool effective_immediately) OVERRIDE;
 
+  void UpdateParentDrawConstraints();
+
  private:
   void SetTotalRootLayerScrollOffset(gfx::Vector2dF new_value_dip);
   // Checks the continuous invalidate and block invalidate state, and schedule
@@ -199,6 +202,10 @@
   gfx::Vector2d last_on_draw_scroll_offset_;
   gfx::Rect last_on_draw_global_visible_rect_;
 
+  // The draw constraints from the parent compositor. These are only used for
+  // tiling priority.
+  ParentCompositorDrawConstraints parent_draw_constraints_;
+
   // When true, we should continuously invalidate and keep drawing, for example
   // to drive animation. This value is set by the compositor and should always
   // reflect the expectation of the compositor and not be reused for other
diff --git a/android_webview/browser/browser_view_renderer_client.h b/android_webview/browser/browser_view_renderer_client.h
index 41fbf5a..2fba4d2 100644
--- a/android_webview/browser/browser_view_renderer_client.h
+++ b/android_webview/browser/browser_view_renderer_client.h
@@ -28,6 +28,9 @@
   // Called to trigger view invalidations.
   virtual void PostInvalidate() = 0;
 
+  // Called to update the parent draw constraints in browser view renderer.
+  virtual void UpdateParentDrawConstraints() = 0;
+
   // Called to get view's absolute location on the screen.
   virtual gfx::Point GetLocationOnScreen() = 0;
 
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index df7e361..e0dab89 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -191,6 +191,21 @@
   if (last_egl_context_ != current_context)
     DLOG(WARNING) << "EGLContextChanged";
 
+  gfx::Transform transform(gfx::Transform::kSkipInitialization);
+  transform.matrix().setColMajorf(draw_info->transform);
+  transform.Translate(scroll_offset_.x(), scroll_offset_.y());
+
+  // Need to post the new transform matrix back to child compositor
+  // because there is no onDraw during a Render Thread animation, and child
+  // compositor might not have the tiles rasterized as the animation goes on.
+  ParentCompositorDrawConstraints draw_constraints(
+      draw_info->is_layer, transform, gfx::Rect(viewport_));
+  if (!draw_constraints_.Equals(draw_constraints)) {
+    draw_constraints_ = draw_constraints;
+    shared_renderer_state_->PostExternalDrawConstraintsToChildCompositor(
+        draw_constraints);
+  }
+
   viewport_.SetSize(draw_info->width, draw_info->height);
   layer_tree_host_->SetViewportSize(viewport_);
   clip_.SetRect(draw_info->clip_left,
@@ -199,9 +214,6 @@
                 draw_info->clip_bottom - draw_info->clip_top);
   stencil_enabled_ = stencil_enabled;
 
-  gfx::Transform transform(gfx::Transform::kSkipInitialization);
-  transform.matrix().setColMajorf(draw_info->transform);
-  transform.Translate(scroll_offset_.x(), scroll_offset_.y());
   delegated_layer_->SetTransform(transform);
 
   gl_surface_->SetBackingFrameBufferObject(framebuffer_binding_ext);
diff --git a/android_webview/browser/hardware_renderer.h b/android_webview/browser/hardware_renderer.h
index f69d587..f87890b 100644
--- a/android_webview/browser/hardware_renderer.h
+++ b/android_webview/browser/hardware_renderer.h
@@ -5,6 +5,7 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_H_
 #define ANDROID_WEBVIEW_BROWSER_HARDWARE_RENDERER_H_
 
+#include "android_webview/browser/parent_compositor_draw_constraints.h"
 #include "android_webview/browser/shared_renderer_state.h"
 #include "base/memory/scoped_ptr.h"
 #include "cc/layers/delegated_frame_resource_collection.h"
@@ -89,6 +90,8 @@
   // This is owned indirectly by |layer_tree_host_|.
   ParentOutputSurface* output_surface_;
 
+  ParentCompositorDrawConstraints draw_constraints_;
+
   DISALLOW_COPY_AND_ASSIGN(HardwareRenderer);
 };
 
diff --git a/android_webview/browser/parent_compositor_draw_constraints.cc b/android_webview/browser/parent_compositor_draw_constraints.cc
new file mode 100644
index 0000000..e507d43
--- /dev/null
+++ b/android_webview/browser/parent_compositor_draw_constraints.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/parent_compositor_draw_constraints.h"
+
+namespace android_webview {
+
+ParentCompositorDrawConstraints::ParentCompositorDrawConstraints()
+    : is_layer(false) {
+}
+
+ParentCompositorDrawConstraints::ParentCompositorDrawConstraints(
+    bool is_layer,
+    const gfx::Transform& transform,
+    const gfx::Rect& surface_rect)
+    : is_layer(is_layer), transform(transform), surface_rect(surface_rect) {
+}
+
+bool ParentCompositorDrawConstraints::Equals(
+    const ParentCompositorDrawConstraints& other) const {
+  if (is_layer != other.is_layer || transform != other.transform)
+    return false;
+
+  // Don't care about the surface size when neither is on a layer.
+  return !is_layer || surface_rect == other.surface_rect;
+}
+
+}  // namespace webview
diff --git a/android_webview/browser/parent_compositor_draw_constraints.h b/android_webview/browser/parent_compositor_draw_constraints.h
new file mode 100644
index 0000000..4355aa9
--- /dev/null
+++ b/android_webview/browser/parent_compositor_draw_constraints.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_PARENT_COMPOSITOR_DRAW_CONSTRAINTS_H_
+#define ANDROID_WEBVIEW_BROWSER_PARENT_COMPOSITOR_DRAW_CONSTRAINTS_H_
+
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
+
+namespace android_webview {
+
+struct ParentCompositorDrawConstraints {
+  bool is_layer;
+  gfx::Transform transform;
+  gfx::Rect surface_rect;
+
+  ParentCompositorDrawConstraints();
+  ParentCompositorDrawConstraints(bool is_layer,
+                                  const gfx::Transform& transform,
+                                  const gfx::Rect& surface_rect);
+  bool Equals(const ParentCompositorDrawConstraints& other) const;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_PARENT_COMPOSITOR_DRAW_CONSTRAINTS_H_
diff --git a/android_webview/browser/parent_output_surface.cc b/android_webview/browser/parent_output_surface.cc
index 54b7f97..0680bc7 100644
--- a/android_webview/browser/parent_output_surface.cc
+++ b/android_webview/browser/parent_output_surface.cc
@@ -30,7 +30,8 @@
   const gfx::Transform identity;
   const gfx::Rect empty;
   const bool resourceless_software_draw = false;
-  SetExternalDrawConstraints(identity, empty, clip, resourceless_software_draw);
+  SetExternalDrawConstraints(
+      identity, empty, clip, clip, identity, resourceless_software_draw);
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/shared_renderer_state.cc b/android_webview/browser/shared_renderer_state.cc
index 582908e..200e2ab 100644
--- a/android_webview/browser/shared_renderer_state.cc
+++ b/android_webview/browser/shared_renderer_state.cc
@@ -51,6 +51,11 @@
   }
 }
 
+void SharedRendererState::UpdateParentDrawConstraintsOnUIThread() {
+  DCHECK(ui_loop_->BelongsToCurrentThread());
+  client_on_ui_->UpdateParentDrawConstraints();
+}
+
 void SharedRendererState::SetDrawGLInput(scoped_ptr<DrawGLInput> input) {
   base::AutoLock lock(lock_);
   DCHECK(!draw_gl_input_.get());
@@ -62,6 +67,26 @@
   return draw_gl_input_.Pass();
 }
 
+void SharedRendererState::PostExternalDrawConstraintsToChildCompositor(
+    const ParentCompositorDrawConstraints& parent_draw_constraints) {
+  {
+    base::AutoLock lock(lock_);
+    parent_draw_constraints_ = parent_draw_constraints;
+  }
+
+  // No need to hold the lock_ during the post task.
+  ui_loop_->PostTask(
+      FROM_HERE,
+      base::Bind(&SharedRendererState::UpdateParentDrawConstraintsOnUIThread,
+                 ui_thread_weak_ptr_));
+}
+
+const ParentCompositorDrawConstraints
+SharedRendererState::ParentDrawConstraints() const {
+  base::AutoLock lock(lock_);
+  return parent_draw_constraints_;
+}
+
 void SharedRendererState::SetInsideHardwareRelease(bool inside) {
   base::AutoLock lock(lock_);
   inside_hardware_release_ = inside;
diff --git a/android_webview/browser/shared_renderer_state.h b/android_webview/browser/shared_renderer_state.h
index 01363f1..cf0c889 100644
--- a/android_webview/browser/shared_renderer_state.h
+++ b/android_webview/browser/shared_renderer_state.h
@@ -5,6 +5,7 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_
 #define ANDROID_WEBVIEW_BROWSER_SHARED_RENDERER_STATE_H_
 
+#include "android_webview/browser/parent_compositor_draw_constraints.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/synchronization/lock.h"
@@ -50,6 +51,10 @@
   scoped_ptr<DrawGLInput> PassDrawGLInput();
 
   bool IsInsideHardwareRelease() const;
+  void PostExternalDrawConstraintsToChildCompositor(
+      const ParentCompositorDrawConstraints& parent_draw_constraints);
+
+  const ParentCompositorDrawConstraints ParentDrawConstraints() const;
 
   void SetSharedContext(gpu::GLInProcessContext* context);
   gpu::GLInProcessContext* GetSharedContext() const;
@@ -62,6 +67,7 @@
   friend class InsideHardwareReleaseReset;
 
   void ClientRequestDrawGLOnUIThread();
+  void UpdateParentDrawConstraintsOnUIThread();
   void SetInsideHardwareRelease(bool inside);
 
   scoped_refptr<base::MessageLoopProxy> ui_loop_;
@@ -73,6 +79,7 @@
   mutable base::Lock lock_;
   scoped_ptr<DrawGLInput> draw_gl_input_;
   bool inside_hardware_release_;
+  ParentCompositorDrawConstraints parent_draw_constraints_;
   gpu::GLInProcessContext* share_context_;
   cc::ReturnedResourceArray returned_resources_;
 
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index cc5e6a3..04b6da1 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -746,6 +746,11 @@
     Java_AwContents_postInvalidateOnAnimation(env, obj.obj());
 }
 
+void AwContents::UpdateParentDrawConstraints() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  browser_view_renderer_.UpdateParentDrawConstraints();
+}
+
 void AwContents::OnNewPicture() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   JNIEnv* env = AttachCurrentThread();
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index ddfeaf3..1381007 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -192,6 +192,7 @@
   // BrowserViewRendererClient implementation.
   virtual bool RequestDrawGL(jobject canvas, bool wait_for_completion) OVERRIDE;
   virtual void PostInvalidate() OVERRIDE;
+  virtual void UpdateParentDrawConstraints() OVERRIDE;
   virtual void OnNewPicture() OVERRIDE;
   virtual gfx::Point GetLocationOnScreen() OVERRIDE;
   virtual void ScrollContainerViewTo(gfx::Vector2d new_value) OVERRIDE;
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 52b1658..8759219 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -398,7 +398,8 @@
   // resourceless software draw, so don't update them.
   if (!layer_tree_impl()->resourceless_software_draw()) {
     visible_rect_for_tile_priority_ = visible_content_rect();
-    viewport_size_for_tile_priority_ = layer_tree_impl()->DrawViewportSize();
+    viewport_rect_for_tile_priority_ =
+        layer_tree_impl()->ViewportRectForTilePriority();
     screen_space_transform_for_tile_priority_ = screen_space_transform();
   }
 
@@ -457,16 +458,22 @@
   if (!tiling_needs_update)
     return;
 
-  // Use visible_content_rect, unless it's empty. If it's empty, then
-  // try to inverse project the viewport into layer space and use that.
+  // If visible_rect_for_tile_priority_ is empty or
+  // viewport_rect_for_tile_priority_ is set to be different from the device
+  // viewport, try to inverse project the viewport into layer space and use
+  // that. Otherwise just use visible_rect_for_tile_priority_
   gfx::Rect visible_rect_in_content_space = visible_rect_for_tile_priority_;
-  if (visible_rect_in_content_space.IsEmpty()) {
-    gfx::Transform screen_to_layer(gfx::Transform::kSkipInitialization);
-    if (screen_space_transform_for_tile_priority_.GetInverse(
-            &screen_to_layer)) {
+
+  if (visible_rect_in_content_space.IsEmpty() ||
+      layer_tree_impl()->DeviceViewport() != viewport_rect_for_tile_priority_) {
+    gfx::Transform view_to_layer(gfx::Transform::kSkipInitialization);
+
+    if (screen_space_transform_for_tile_priority_.GetInverse(&view_to_layer)) {
+      // Transform from view space to content space.
       visible_rect_in_content_space =
           gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
-              screen_to_layer, gfx::Rect(viewport_size_for_tile_priority_)));
+              view_to_layer, viewport_rect_for_tile_priority_));
+
       visible_rect_in_content_space.Intersect(gfx::Rect(content_bounds()));
     }
   }
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 6b1703e..ad30821 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -201,7 +201,7 @@
   // Save a copy of the visible rect and viewport size of the last frame that
   // has a valid viewport for prioritizing tiles.
   gfx::Rect visible_rect_for_tile_priority_;
-  gfx::Size viewport_size_for_tile_priority_;
+  gfx::Rect viewport_rect_for_tile_priority_;
   gfx::Transform screen_space_transform_for_tile_priority_;
 
   friend class PictureLayer;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 83b775e..180ed78 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include <set>
 #include <utility>
 
+#include "cc/base/math_util.h"
 #include "cc/layers/append_quads_data.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/test/fake_content_layer_client.h"
@@ -300,6 +301,103 @@
     VerifyAllTilesExistAndHavePile(tilings->tiling_at(i), active_pile.get());
 }
 
+TEST_F(PictureLayerImplTest, ExternalViewportRectForPrioritizingTiles) {
+  base::TimeTicks time_ticks;
+  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+  gfx::Size tile_size(100, 100);
+  gfx::Size layer_bounds(400, 400);
+
+  scoped_refptr<FakePicturePileImpl> pending_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+  scoped_refptr<FakePicturePileImpl> active_pile =
+      FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
+
+  SetupTrees(pending_pile, active_pile);
+
+  Region invalidation;
+  AddDefaultTilingsWithInvalidation(invalidation);
+  SetupDrawPropertiesAndUpdateTiles(active_layer_, 1.f, 1.f, 1.f, 1.f, false);
+
+  // Update tiles with viewport for tile priority as (0, 0, 100, 100) and the
+  // identify transform for tile priority.
+  bool resourceless_software_draw = false;
+  gfx::Rect viewport = gfx::Rect(layer_bounds),
+            viewport_rect_for_tile_priority = gfx::Rect(0, 0, 100, 100);
+  gfx::Transform transform, transform_for_tile_priority;
+
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport_rect_for_tile_priority,
+                                        transform_for_tile_priority,
+                                        resourceless_software_draw);
+  active_layer_->draw_properties().visible_content_rect = viewport;
+  active_layer_->draw_properties().screen_space_transform = transform;
+  active_layer_->UpdateTiles();
+
+  gfx::Rect viewport_rect_for_tile_priority_in_view_space =
+      viewport_rect_for_tile_priority;
+
+  // Verify the viewport rect for tile priority is used in picture layer impl.
+  EXPECT_EQ(active_layer_->viewport_rect_for_tile_priority(),
+            viewport_rect_for_tile_priority_in_view_space);
+
+  // Verify the viewport rect for tile priority is used in picture layer tiling.
+  PictureLayerTilingSet* tilings = active_layer_->tilings();
+  for (size_t i = 0; i < tilings->num_tilings(); i++) {
+    PictureLayerTiling* tiling = tilings->tiling_at(i);
+    EXPECT_EQ(
+        tiling->GetCurrentVisibleRectForTesting(),
+        gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
+                                  tiling->contents_scale()));
+  }
+
+  // Update tiles with viewport for tile priority as (200, 200, 100, 100) in
+  // screen space and the transform for tile priority is translated and
+  // rotated. The actual viewport for tile priority used by PictureLayerImpl
+  // should be (200, 200, 100, 100) applied with the said transform.
+  time_ticks += base::TimeDelta::FromMilliseconds(200);
+  host_impl_.SetCurrentFrameTimeTicks(time_ticks);
+
+  viewport_rect_for_tile_priority = gfx::Rect(200, 200, 100, 100);
+  transform_for_tile_priority.Translate(100, 100);
+  transform_for_tile_priority.Rotate(45);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport_rect_for_tile_priority,
+                                        transform_for_tile_priority,
+                                        resourceless_software_draw);
+  active_layer_->draw_properties().visible_content_rect = viewport;
+  active_layer_->draw_properties().screen_space_transform = transform;
+  active_layer_->UpdateTiles();
+
+  gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
+  bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
+  EXPECT_TRUE(success);
+
+  viewport_rect_for_tile_priority_in_view_space =
+      gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+          screen_to_view, viewport_rect_for_tile_priority));
+
+  // Verify the viewport rect for tile priority is used in PictureLayerImpl.
+  EXPECT_EQ(active_layer_->viewport_rect_for_tile_priority(),
+            viewport_rect_for_tile_priority_in_view_space);
+
+  // Interset viewport_rect_for_tile_priority_in_view_space with the layer
+  // bounds and the result should be used in PictureLayerTiling.
+  viewport_rect_for_tile_priority_in_view_space.Intersect(
+      gfx::Rect(layer_bounds));
+  tilings = active_layer_->tilings();
+  for (size_t i = 0; i < tilings->num_tilings(); i++) {
+    PictureLayerTiling* tiling = tilings->tiling_at(i);
+    EXPECT_EQ(
+        tiling->GetCurrentVisibleRectForTesting(),
+        gfx::ScaleToEnclosingRect(viewport_rect_for_tile_priority_in_view_space,
+                                  tiling->contents_scale()));
+  }
+}
+
 TEST_F(PictureLayerImplTest, InvalidViewportForPrioritizingTiles) {
   base::TimeTicks time_ticks;
   host_impl_.SetCurrentFrameTimeTicks(time_ticks);
@@ -324,8 +422,12 @@
   bool resourceless_software_draw = false;
   gfx::Rect viewport = gfx::Rect(layer_bounds);
   gfx::Transform transform;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
   active_layer_->UpdateTiles();
@@ -333,9 +435,9 @@
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
   EXPECT_FALSE(visible_rect_for_tile_priority.IsEmpty());
-  gfx::Size viewport_size_for_tile_priority =
-      active_layer_->viewport_size_for_tile_priority();
-  EXPECT_FALSE(viewport_size_for_tile_priority.IsEmpty());
+  gfx::Rect viewport_rect_for_tile_priority =
+      active_layer_->viewport_rect_for_tile_priority();
+  EXPECT_FALSE(viewport_rect_for_tile_priority.IsEmpty());
   gfx::Transform screen_space_transform_for_tile_priority =
       active_layer_->screen_space_transform_for_tile_priority();
 
@@ -348,14 +450,18 @@
   transform.Translate(1.f, 1.f);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->UpdateTiles();
 
   EXPECT_RECT_EQ(visible_rect_for_tile_priority,
                  active_layer_->visible_rect_for_tile_priority());
-  EXPECT_SIZE_EQ(viewport_size_for_tile_priority,
-                 active_layer_->viewport_size_for_tile_priority());
+  EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
+                 active_layer_->viewport_rect_for_tile_priority());
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       screen_space_transform_for_tile_priority,
       active_layer_->screen_space_transform_for_tile_priority());
@@ -364,14 +470,18 @@
   time_ticks += base::TimeDelta::FromMilliseconds(200);
   host_impl_.SetCurrentFrameTimeTicks(time_ticks);
   resourceless_software_draw = false;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->UpdateTiles();
 
   EXPECT_FALSE(visible_rect_for_tile_priority ==
                active_layer_->visible_rect_for_tile_priority());
-  EXPECT_FALSE(viewport_size_for_tile_priority ==
-               active_layer_->viewport_size_for_tile_priority());
+  EXPECT_FALSE(viewport_rect_for_tile_priority ==
+               active_layer_->viewport_rect_for_tile_priority());
   EXPECT_FALSE(screen_space_transform_for_tile_priority ==
                active_layer_->screen_space_transform_for_tile_priority());
 }
@@ -395,8 +505,13 @@
 
   bool resourceless_software_draw = true;
   gfx::Rect viewport = gfx::Rect(layer_bounds);
-  host_impl_.SetExternalDrawConstraints(
-      gfx::Transform(), viewport, viewport, resourceless_software_draw);
+  gfx::Transform identity = gfx::Transform();
+  host_impl_.SetExternalDrawConstraints(identity,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        identity,
+                                        resourceless_software_draw);
   ResetTilingsAndRasterScales();
   host_impl_.pending_tree()->UpdateDrawProperties();
   host_impl_.active_tree()->UpdateDrawProperties();
@@ -2420,8 +2535,12 @@
   bool resourceless_software_draw = false;
   gfx::Rect viewport = gfx::Rect(layer_bounds);
   gfx::Transform transform;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
   active_layer_->UpdateTiles();
@@ -2429,9 +2548,9 @@
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
   EXPECT_FALSE(visible_rect_for_tile_priority.IsEmpty());
-  gfx::Size viewport_size_for_tile_priority =
-      active_layer_->viewport_size_for_tile_priority();
-  EXPECT_FALSE(viewport_size_for_tile_priority.IsEmpty());
+  gfx::Rect viewport_rect_for_tile_priority =
+      active_layer_->viewport_rect_for_tile_priority();
+  EXPECT_FALSE(viewport_rect_for_tile_priority.IsEmpty());
   gfx::Transform screen_space_transform_for_tile_priority =
       active_layer_->screen_space_transform_for_tile_priority();
 
@@ -2444,14 +2563,18 @@
   transform.Translate(1.f, 1.f);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->UpdateTiles();
 
   EXPECT_RECT_EQ(visible_rect_for_tile_priority,
                  active_layer_->visible_rect_for_tile_priority());
-  EXPECT_SIZE_EQ(viewport_size_for_tile_priority,
-                 active_layer_->viewport_size_for_tile_priority());
+  EXPECT_RECT_EQ(viewport_rect_for_tile_priority,
+                 active_layer_->viewport_rect_for_tile_priority());
   EXPECT_TRANSFORMATION_MATRIX_EQ(
       screen_space_transform_for_tile_priority,
       active_layer_->screen_space_transform_for_tile_priority());
@@ -2460,14 +2583,18 @@
   time_ticks += base::TimeDelta::FromMilliseconds(200);
   host_impl_.SetCurrentFrameTimeTicks(time_ticks);
   resourceless_software_draw = false;
-  host_impl_.SetExternalDrawConstraints(
-      transform, viewport, viewport, resourceless_software_draw);
+  host_impl_.SetExternalDrawConstraints(transform,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        transform,
+                                        resourceless_software_draw);
   active_layer_->UpdateTiles();
 
   EXPECT_FALSE(visible_rect_for_tile_priority ==
                active_layer_->visible_rect_for_tile_priority());
-  EXPECT_FALSE(viewport_size_for_tile_priority ==
-               active_layer_->viewport_size_for_tile_priority());
+  EXPECT_FALSE(viewport_rect_for_tile_priority ==
+               active_layer_->viewport_rect_for_tile_priority());
   EXPECT_FALSE(screen_space_transform_for_tile_priority ==
                active_layer_->screen_space_transform_for_tile_priority());
 }
@@ -2491,8 +2618,13 @@
 
   bool resourceless_software_draw = true;
   gfx::Rect viewport = gfx::Rect(layer_bounds);
-  host_impl_.SetExternalDrawConstraints(
-      gfx::Transform(), viewport, viewport, resourceless_software_draw);
+  gfx::Transform identity = gfx::Transform();
+  host_impl_.SetExternalDrawConstraints(identity,
+                                        viewport,
+                                        viewport,
+                                        viewport,
+                                        identity,
+                                        resourceless_software_draw);
   ResetTilingsAndRasterScales();
   host_impl_.pending_tree()->UpdateDrawProperties();
   host_impl_.active_tree()->UpdateDrawProperties();
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 4b6b5af..b663a09 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -108,9 +108,15 @@
     const gfx::Transform& transform,
     const gfx::Rect& viewport,
     const gfx::Rect& clip,
+    const gfx::Rect& viewport_rect_for_tile_priority,
+    const gfx::Transform& transform_for_tile_priority,
     bool resourceless_software_draw) {
-  client_->SetExternalDrawConstraints(
-      transform, viewport, clip, resourceless_software_draw);
+  client_->SetExternalDrawConstraints(transform,
+                                      viewport,
+                                      clip,
+                                      viewport_rect_for_tile_priority,
+                                      transform_for_tile_priority,
+                                      resourceless_software_draw);
 }
 
 OutputSurface::~OutputSurface() {
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 01fdd72..876379c 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -167,10 +167,13 @@
   void ReclaimResources(const CompositorFrameAck* ack);
   void DidLoseOutputSurface();
   void SetExternalStencilTest(bool enabled);
-  void SetExternalDrawConstraints(const gfx::Transform& transform,
-                                  const gfx::Rect& viewport,
-                                  const gfx::Rect& clip,
-                                  bool resourceless_software_draw);
+  void SetExternalDrawConstraints(
+      const gfx::Transform& transform,
+      const gfx::Rect& viewport,
+      const gfx::Rect& clip,
+      const gfx::Rect& viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority,
+      bool resourceless_software_draw);
 
  private:
   void SetUpContext3d();
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h
index 2c6c128..bb37a91 100644
--- a/cc/output/output_surface_client.h
+++ b/cc/output/output_surface_client.h
@@ -38,10 +38,13 @@
   virtual void DidSwapBuffersComplete() = 0;
   virtual void ReclaimResources(const CompositorFrameAck* ack) = 0;
   virtual void DidLoseOutputSurface() = 0;
-  virtual void SetExternalDrawConstraints(const gfx::Transform& transform,
-                                          const gfx::Rect& viewport,
-                                          const gfx::Rect& clip,
-                                          bool resourceless_software_draw) = 0;
+  virtual void SetExternalDrawConstraints(
+      const gfx::Transform& transform,
+      const gfx::Rect& viewport,
+      const gfx::Rect& clip,
+      const gfx::Rect& viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority,
+      bool resourceless_software_draw) = 0;
   virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) = 0;
   // If set, |callback| will be called subsequent to each new tree activation,
   // regardless of the compositor visibility or damage. |callback| must remain
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index fc7505c..79c5900 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -155,6 +155,10 @@
     return all_tiles;
   }
 
+  const gfx::Rect& GetCurrentVisibleRectForTesting() const {
+    return current_visible_rect_in_content_space_;
+  }
+
   // Iterate over all tiles to fill content_rect.  Even if tiles are invalid
   // (i.e. no valid resource) this tiling should still iterate over them.
   // The union of all geometry_rect calls for each element iterated over should
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h
index 673178b..9139bc0 100644
--- a/cc/surfaces/display.h
+++ b/cc/surfaces/display.h
@@ -57,6 +57,8 @@
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
       const gfx::Rect& clip,
+      const gfx::Rect& viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority,
       bool resourceless_software_draw) OVERRIDE {}
   virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE {}
   virtual void SetTreeActivationCallback(
diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h
index 5e887b8..7ecb6cf 100644
--- a/cc/test/fake_output_surface_client.h
+++ b/cc/test/fake_output_surface_client.h
@@ -42,6 +42,8 @@
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
       const gfx::Rect& clip,
+      const gfx::Rect& viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority,
       bool resourceless_software_draw) OVERRIDE {}
   virtual void SetMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
   virtual void SetTreeActivationCallback(const base::Closure&) OVERRIDE {}
diff --git a/cc/test/fake_picture_layer_impl.h b/cc/test/fake_picture_layer_impl.h
index 04661c4..4cac7ab 100644
--- a/cc/test/fake_picture_layer_impl.h
+++ b/cc/test/fake_picture_layer_impl.h
@@ -78,8 +78,8 @@
   gfx::Rect visible_rect_for_tile_priority() {
     return visible_rect_for_tile_priority_;
   }
-  gfx::Size viewport_size_for_tile_priority() {
-    return viewport_size_for_tile_priority_;
+  gfx::Rect viewport_rect_for_tile_priority() {
+    return viewport_rect_for_tile_priority_;
   }
   gfx::Transform screen_space_transform_for_tile_priority() {
     return screen_space_transform_for_tile_priority_;
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index f85cac3..74d3819 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -76,8 +76,13 @@
   // Be that influence!
   viewport += gfx::Vector2d(20, 10);
   bool resourceless_software_draw = false;
-  impl->SetExternalDrawConstraints(
-      gfx::Transform(), viewport, viewport, resourceless_software_draw);
+  gfx::Transform identity = gfx::Transform();
+  impl->SetExternalDrawConstraints(identity,
+                                   viewport,
+                                   viewport,
+                                   viewport,
+                                   identity,
+                                   resourceless_software_draw);
   EXPECT_EQ(viewport.ToString(), impl->DeviceViewport().ToString());
 }
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 6dd4b3e..5b5d491 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -65,6 +65,7 @@
 #include "cc/trees/tree_synchronizer.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "ui/gfx/frame_time.h"
+#include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/size_conversions.h"
 #include "ui/gfx/vector2d_conversions.h"
 
@@ -1312,15 +1313,32 @@
     const gfx::Transform& transform,
     const gfx::Rect& viewport,
     const gfx::Rect& clip,
+    const gfx::Rect& viewport_rect_for_tile_priority,
+    const gfx::Transform& transform_for_tile_priority,
     bool resourceless_software_draw) {
+  gfx::Rect viewport_rect_for_tile_priority_in_view_space;
+  if (!resourceless_software_draw) {
+    gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
+    if (transform_for_tile_priority.GetInverse(&screen_to_view)) {
+      // Convert from screen space to view space.
+      viewport_rect_for_tile_priority_in_view_space =
+          gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
+              screen_to_view, viewport_rect_for_tile_priority));
+    }
+  }
+
   if (external_transform_ != transform || external_viewport_ != viewport ||
-      resourceless_software_draw_ != resourceless_software_draw) {
+      resourceless_software_draw_ != resourceless_software_draw ||
+      viewport_rect_for_tile_priority_ !=
+          viewport_rect_for_tile_priority_in_view_space) {
     active_tree_->set_needs_update_draw_properties();
   }
 
   external_transform_ = transform;
   external_viewport_ = viewport;
   external_clip_ = clip;
+  viewport_rect_for_tile_priority_ =
+      viewport_rect_for_tile_priority_in_view_space;
   resourceless_software_draw_ = resourceless_software_draw;
 }
 
@@ -2118,6 +2136,13 @@
   SetFullRootLayerDamage();
 }
 
+const gfx::Rect LayerTreeHostImpl::ViewportRectForTilePriority() const {
+  if (viewport_rect_for_tile_priority_.IsEmpty())
+    return DeviceViewport();
+
+  return viewport_rect_for_tile_priority_;
+}
+
 gfx::Size LayerTreeHostImpl::DrawViewportSize() const {
   return DeviceViewport().size();
 }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index f53001a..d1a6e33 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -219,6 +219,9 @@
   // for draw properties, tilings, quads and render passes.
   gfx::Size DrawViewportSize() const;
 
+  // Viewport rect in view space used for tiling prioritization.
+  const gfx::Rect ViewportRectForTilePriority() const;
+
   // Viewport size for scrolling and fixed-position compensation. This value
   // excludes the URL bar and non-overlay scrollbars and is in DIP (and
   // invariant relative to page scale).
@@ -246,10 +249,13 @@
                                      base::TimeDelta interval) OVERRIDE;
   virtual void SetNeedsRedrawRect(const gfx::Rect& rect) OVERRIDE;
   virtual void BeginFrame(const BeginFrameArgs& args) OVERRIDE;
+
   virtual void SetExternalDrawConstraints(
       const gfx::Transform& transform,
       const gfx::Rect& viewport,
       const gfx::Rect& clip,
+      const gfx::Rect& viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority,
       bool resourceless_software_draw) OVERRIDE;
   virtual void DidLoseOutputSurface() OVERRIDE;
   virtual void DidSwapBuffers() OVERRIDE;
@@ -656,9 +662,12 @@
   // - external_viewport_ is used DrawProperties, tile management and
   // glViewport/window projection matrix.
   // - external_clip_ specifies a top-level clip rect
+  // - viewport_rect_for_tile_priority_ is the rect in view space used for
+  // tiling priority.
   gfx::Transform external_transform_;
   gfx::Rect external_viewport_;
   gfx::Rect external_clip_;
+  gfx::Rect viewport_rect_for_tile_priority_;
   bool resourceless_software_draw_;
 
   gfx::Rect viewport_damage_rect_;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 4a132cd..fd4261b 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -5572,6 +5572,8 @@
   host_impl_->SetExternalDrawConstraints(external_transform,
                                          external_viewport,
                                          external_clip,
+                                         external_viewport,
+                                         external_transform,
                                          resourceless_software_draw);
 
   EXPECT_EQ(0, software_device->frames_began_);
@@ -5605,6 +5607,8 @@
   host_impl_->SetExternalDrawConstraints(external_transform,
                                          external_viewport,
                                          external_clip,
+                                         external_viewport,
+                                         external_transform,
                                          resourceless_software_draw);
 
   // SolidColorLayerImpl will be drawn.
@@ -6605,6 +6609,10 @@
   host_impl_->SetExternalDrawConstraints(external_transform,
                                          external_viewport,
                                          external_clip,
+                                         external_viewport,
+                                         external_transform,
+                                         external_viewport,
+                                         external_transform,
                                          resourceless_software_draw);
   DrawFrame();
   EXPECT_TRANSFORMATION_MATRIX_EQ(
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 9327257..9ca3308 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -713,10 +713,18 @@
   layer_tree_host_impl_->SetNeedsCommit();
 }
 
+gfx::Rect LayerTreeImpl::DeviceViewport() const {
+  return layer_tree_host_impl_->DeviceViewport();
+}
+
 gfx::Size LayerTreeImpl::DrawViewportSize() const {
   return layer_tree_host_impl_->DrawViewportSize();
 }
 
+const gfx::Rect LayerTreeImpl::ViewportRectForTilePriority() const {
+  return layer_tree_host_impl_->ViewportRectForTilePriority();
+}
+
 scoped_ptr<ScrollbarAnimationController>
 LayerTreeImpl::CreateScrollbarAnimationController(LayerImpl* scrolling_layer) {
   DCHECK(settings().scrollbar_fade_delay_ms);
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 66d1f49..47f3ce1 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -85,7 +85,9 @@
   base::TimeTicks CurrentFrameTimeTicks() const;
   base::TimeDelta begin_impl_frame_interval() const;
   void SetNeedsCommit();
+  gfx::Rect DeviceViewport() const;
   gfx::Size DrawViewportSize() const;
+  const gfx::Rect ViewportRectForTilePriority() const;
   scoped_ptr<ScrollbarAnimationController> CreateScrollbarAnimationController(
       LayerImpl* scrolling_layer);
   void DidAnimateScrollOffset();
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc
index 1b5ccb7..f7ac3df 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -124,12 +124,19 @@
     gfx::Size surface_size,
     const gfx::Transform& transform,
     gfx::Rect viewport,
-    gfx::Rect clip) {
+    gfx::Rect clip,
+    gfx::Rect viewport_rect_for_tile_priority,
+    const gfx::Transform& transform_for_tile_priority) {
   DCHECK(CalledOnValidThread());
   DCHECK(output_surface_);
 
   scoped_ptr<cc::CompositorFrame> frame =
-      output_surface_->DemandDrawHw(surface_size, transform, viewport, clip);
+      output_surface_->DemandDrawHw(surface_size,
+                                    transform,
+                                    viewport,
+                                    clip,
+                                    viewport_rect_for_tile_priority,
+                                    transform_for_tile_priority);
   if (frame.get())
     UpdateFrameMetaData(frame->metadata);
   return frame.Pass();
diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h
index 6ac80cb..f5cfe96 100644
--- a/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -55,7 +55,9 @@
       gfx::Size surface_size,
       const gfx::Transform& transform,
       gfx::Rect viewport,
-      gfx::Rect clip) OVERRIDE;
+      gfx::Rect clip,
+      gfx::Rect viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority) OVERRIDE;
   virtual bool DemandDrawSw(SkCanvas* canvas) OVERRIDE;
   virtual void ReturnResources(
       const cc::CompositorFrameAck& frame_ack) OVERRIDE;
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index 4e8ff8d..6092bd5 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -162,13 +162,20 @@
     gfx::Size surface_size,
     const gfx::Transform& transform,
     gfx::Rect viewport,
-    gfx::Rect clip) {
+    gfx::Rect clip,
+    gfx::Rect viewport_rect_for_tile_priority,
+    const gfx::Transform& transform_for_tile_priority) {
   DCHECK(CalledOnValidThread());
   DCHECK(HasClient());
   DCHECK(context_provider_);
 
   surface_size_ = surface_size;
-  InvokeComposite(transform, viewport, clip, true);
+  InvokeComposite(transform,
+                  viewport,
+                  clip,
+                  viewport_rect_for_tile_priority,
+                  transform_for_tile_priority,
+                  true);
 
   return frame_holder_.Pass();
 }
@@ -190,7 +197,9 @@
   surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
                             canvas->getDeviceSize().height());
 
-  InvokeComposite(transform, clip, clip, false);
+  // Resourceless software draw does not need viewport_for_tiling.
+  gfx::Rect empty;
+  InvokeComposite(transform, clip, clip, empty, gfx::Transform(), false);
 
   return frame_holder_.Pass();
 }
@@ -199,6 +208,8 @@
     const gfx::Transform& transform,
     gfx::Rect viewport,
     gfx::Rect clip,
+    gfx::Rect viewport_rect_for_tile_priority,
+    gfx::Transform transform_for_tile_priority,
     bool hardware_draw) {
   DCHECK(!invoking_composite_);
   DCHECK(!frame_holder_.get());
@@ -206,8 +217,12 @@
 
   gfx::Transform adjusted_transform = transform;
   AdjustTransform(&adjusted_transform, viewport);
-  SetExternalDrawConstraints(
-      adjusted_transform, viewport, clip, !hardware_draw);
+  SetExternalDrawConstraints(adjusted_transform,
+                             viewport,
+                             clip,
+                             viewport_rect_for_tile_priority,
+                             transform_for_tile_priority,
+                             !hardware_draw);
   SetNeedsRedrawRect(gfx::Rect(viewport.size()));
   client_->BeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor());
 
@@ -218,11 +233,16 @@
     cached_hw_transform_ = adjusted_transform;
     cached_hw_viewport_ = viewport;
     cached_hw_clip_ = clip;
+    cached_hw_viewport_rect_for_tile_priority_ =
+        viewport_rect_for_tile_priority;
+    cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
   } else {
     bool resourceless_software_draw = false;
     SetExternalDrawConstraints(cached_hw_transform_,
                                cached_hw_viewport_,
                                cached_hw_clip_,
+                               cached_hw_viewport_rect_for_tile_priority_,
+                               cached_hw_transform_for_tile_priority_,
                                resourceless_software_draw);
   }
 
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.h b/content/browser/android/in_process/synchronous_compositor_output_surface.h
index 2c04ed2..b966ae7 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.h
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.h
@@ -64,10 +64,13 @@
   bool InitializeHwDraw(
       scoped_refptr<cc::ContextProvider> onscreen_context_provider);
   void ReleaseHwDraw();
-  scoped_ptr<cc::CompositorFrame> DemandDrawHw(gfx::Size surface_size,
-                                               const gfx::Transform& transform,
-                                               gfx::Rect viewport,
-                                               gfx::Rect clip);
+  scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+      gfx::Size surface_size,
+      const gfx::Transform& transform,
+      gfx::Rect viewport,
+      gfx::Rect clip,
+      gfx::Rect viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority);
   void ReturnResources(const cc::CompositorFrameAck& frame_ack);
   scoped_ptr<cc::CompositorFrame> DemandDrawSw(SkCanvas* canvas);
   void SetMemoryPolicy(const SynchronousCompositorMemoryPolicy& policy);
@@ -79,6 +82,8 @@
   void InvokeComposite(const gfx::Transform& transform,
                        gfx::Rect viewport,
                        gfx::Rect clip,
+                       gfx::Rect viewport_rect_for_tile_priority,
+                       gfx::Transform transform_for_tile_priority,
                        bool hardware_draw);
   bool CalledOnValidThread() const;
   SynchronousCompositorOutputSurfaceDelegate* GetDelegate();
@@ -90,6 +95,8 @@
   gfx::Transform cached_hw_transform_;
   gfx::Rect cached_hw_viewport_;
   gfx::Rect cached_hw_clip_;
+  gfx::Rect cached_hw_viewport_rect_for_tile_priority_;
+  gfx::Transform cached_hw_transform_for_tile_priority_;
 
   // Only valid (non-NULL) during a DemandDrawSw() call.
   SkCanvas* current_sw_canvas_;
diff --git a/content/public/browser/android/synchronous_compositor.h b/content/public/browser/android/synchronous_compositor.h
index 62485f1..72c2b19 100644
--- a/content/public/browser/android/synchronous_compositor.h
+++ b/content/public/browser/android/synchronous_compositor.h
@@ -91,7 +91,9 @@
       gfx::Size surface_size,
       const gfx::Transform& transform,
       gfx::Rect viewport,
-      gfx::Rect clip) = 0;
+      gfx::Rect clip,
+      gfx::Rect viewport_rect_for_tile_priority,
+      const gfx::Transform& transform_for_tile_priority) = 0;
 
   // For delegated rendering, return resources from parent compositor to this.
   // Note that all resources must be returned before ReleaseHwDraw.