summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-21 04:42:05 +0000
committerdarin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-21 04:42:05 +0000
commit53d3f3046205f2d6151f61b8ef835ad708215761 (patch)
tree8dd4f4ac91f3f0f2e7ba7cf0a1fac8a5969af5b3
parentc9086fbde71e70d3b89e574d6affc005cc190c7d (diff)
downloadchromium_src-53d3f3046205f2d6151f61b8ef835ad708215761.zip
chromium_src-53d3f3046205f2d6151f61b8ef835ad708215761.tar.gz
chromium_src-53d3f3046205f2d6151f61b8ef835ad708215761.tar.bz2
Combine ViewHostMsg_{Paint,Scroll}Rect into one IPC.
The combined IPC means that scrolling only requires one transport DIB instead of two. Previously, we'd use one in the ScrollRect IPC to pass up the pixels for the exposed region, and then we'd use a second one in the PaintRect IPC to pass up the pixels for the updated scroll bar rendering. Now all paints are done using a single transport DIB. Optimize RenderWidgetHostViewWin::OnPaint to only paint the damaged regions. This means calling GetUpdateRgn and GetRegionData to enumerate the list of damage rects. Then only those rects are copied from the backing store. The same optimization is not done for Linux or Mac yet. R=brettw BUG=29591 TEST=none Originally reviewed at http://codereview.chromium.org/506013 Review URL: http://codereview.chromium.org/509005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35078 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/renderer_host/backing_store.h9
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.mm8
-rw-r--r--chrome/browser/renderer_host/backing_store_win.cc10
-rw-r--r--chrome/browser/renderer_host/backing_store_x.cc7
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc9
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h6
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.cc6
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.h6
-rw-r--r--chrome/browser/renderer_host/render_process_host.h10
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.cc40
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.h48
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc95
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h11
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc124
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc20
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm33
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc95
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h6
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc4
-rw-r--r--chrome/browser/renderer_host/test/render_view_host_unittest.cc4
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h6
-rw-r--r--chrome/common/render_messages.h111
-rw-r--r--chrome/common/render_messages_internal.h23
-rw-r--r--chrome/renderer/render_widget.cc187
-rw-r--r--chrome/renderer/render_widget.h26
28 files changed, 394 insertions, 523 deletions
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index 387a564..68514e4 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -98,12 +98,9 @@ class BackingStore {
const gfx::Rect& bitmap_rect,
const gfx::Rect& copy_rect);
- // Scrolls the given rect in the backing store, replacing the given region
- // identified by |bitmap_rect| by the bitmap in the file identified by the
- // given file handle.
- void ScrollRect(base::ProcessHandle process,
- TransportDIB* bitmap, const gfx::Rect& bitmap_rect,
- int dx, int dy,
+ // Scrolls the contents of clip_rect in the backing store by dx or dy (but dx
+ // and dy cannot both be non-zero).
+ void ScrollRect(int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size);
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index 1de83b2..0b8fa6e 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -99,10 +99,7 @@ void BackingStore::PaintRect(base::ProcessHandle process,
}
// Scroll the contents of our CGLayer
-void BackingStore::ScrollRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
+void BackingStore::ScrollRect(int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
@@ -158,9 +155,6 @@ void BackingStore::ScrollRect(base::ProcessHandle process,
cg_bitmap_.swap(new_bitmap);
}
}
- // Now paint the new bitmap data
- PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
- return;
}
CGLayerRef BackingStore::CreateCGLayer() {
diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc
index 6cbaa34..ae772dc 100644
--- a/chrome/browser/renderer_host/backing_store_win.cc
+++ b/chrome/browser/renderer_host/backing_store_win.cc
@@ -146,10 +146,7 @@ void BackingStore::PaintRect(base::ProcessHandle process,
reinterpret_cast<BITMAPINFO*>(&hdr));
}
-void BackingStore::ScrollRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
+void BackingStore::ScrollRect(int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
RECT damaged_rect, r = clip_rect.ToRECT();
@@ -157,9 +154,4 @@ void BackingStore::ScrollRect(base::ProcessHandle process,
// TODO(darin): this doesn't work if dx and dy are both non-zero!
DCHECK(dx == 0 || dy == 0);
-
- // We expect that damaged_rect should equal bitmap_rect.
- DCHECK(gfx::Rect(damaged_rect) == bitmap_rect);
-
- PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
}
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
index 74ea8ac..a1173b8 100644
--- a/chrome/browser/renderer_host/backing_store_x.cc
+++ b/chrome/browser/renderer_host/backing_store_x.cc
@@ -311,10 +311,7 @@ void BackingStore::PaintRect(base::ProcessHandle process,
XFreePixmap(display_, pixmap);
}
-void BackingStore::ScrollRect(base::ProcessHandle process,
- TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
+void BackingStore::ScrollRect(int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
if (!display_)
@@ -346,8 +343,6 @@ void BackingStore::ScrollRect(base::ProcessHandle process,
clip_rect.y() /* dest x */);
}
}
-
- PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
}
void BackingStore::ShowRect(const gfx::Rect& rect, XID target) {
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index a6f02a3..2d7d2f8 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -347,15 +347,16 @@ void BrowserRenderProcessHost::CrossSiteClosePageACK(
widget_helper_->CrossSiteClosePageACK(params);
}
-bool BrowserRenderProcessHost::WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool BrowserRenderProcessHost::WaitForUpdateMsg(
+ int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
// The post task to this thread with the process id could be in queue, and we
// don't want to dispatch a message before then since it will need the handle.
if (child_process_.get() && child_process_->IsStarting())
return false;
- return widget_helper_->WaitForPaintMsg(render_widget_id, max_delay, msg);
+ return widget_helper_->WaitForUpdateMsg(render_widget_id, max_delay, msg);
}
void BrowserRenderProcessHost::ReceivedBadMessage(uint32 msg_type) {
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index cd94bf5..3a6e83b 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -63,9 +63,9 @@ class BrowserRenderProcessHost : public RenderProcessHost,
virtual int GetNextRoutingID();
virtual void CancelResourceRequests(int render_widget_id);
virtual void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- virtual bool WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
virtual void ReceivedBadMessage(uint32 msg_type);
virtual void WidgetRestored();
virtual void WidgetHidden();
diff --git a/chrome/browser/renderer_host/mock_render_process_host.cc b/chrome/browser/renderer_host/mock_render_process_host.cc
index 8be0416..b18cc50 100644
--- a/chrome/browser/renderer_host/mock_render_process_host.cc
+++ b/chrome/browser/renderer_host/mock_render_process_host.cc
@@ -31,9 +31,9 @@ void MockRenderProcessHost::CrossSiteClosePageACK(
const ViewMsg_ClosePage_Params& params) {
}
-bool MockRenderProcessHost::WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool MockRenderProcessHost::WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
return false;
}
diff --git a/chrome/browser/renderer_host/mock_render_process_host.h b/chrome/browser/renderer_host/mock_render_process_host.h
index aa04651..70ed985 100644
--- a/chrome/browser/renderer_host/mock_render_process_host.h
+++ b/chrome/browser/renderer_host/mock_render_process_host.h
@@ -35,9 +35,9 @@ class MockRenderProcessHost : public RenderProcessHost {
virtual int GetNextRoutingID();
virtual void CancelResourceRequests(int render_widget_id);
virtual void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- virtual bool WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
virtual void ReceivedBadMessage(uint32 msg_type);
virtual void WidgetRestored();
virtual void WidgetHidden();
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index aad1f83..7979d24 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -165,12 +165,12 @@ class RenderProcessHost : public IPC::Channel::Sender,
virtual void CrossSiteClosePageACK(
const ViewMsg_ClosePage_Params& params) = 0;
- // Called on the UI thread to wait for the next PaintRect message for the
+ // Called on the UI thread to wait for the next UpdateRect message for the
// specified render widget. Returns true if successful, and the msg out-
- // param will contain a copy of the received PaintRect message.
- virtual bool WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) = 0;
+ // param will contain a copy of the received UpdateRect message.
+ virtual bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) = 0;
// Called when a received message cannot be decoded.
virtual void ReceivedBadMessage(uint32 msg_type) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_helper.cc b/chrome/browser/renderer_host/render_widget_helper.cc
index 8916c70..dffc9c5 100644
--- a/chrome/browser/renderer_host/render_widget_helper.cc
+++ b/chrome/browser/renderer_host/render_widget_helper.cc
@@ -14,24 +14,24 @@
// A Task used with InvokeLater that we hold a pointer to in pending_paints_.
// Instances are deleted by MessageLoop after it calls their Run method.
-class RenderWidgetHelper::PaintMsgProxy : public Task {
+class RenderWidgetHelper::UpdateMsgProxy : public Task {
public:
- PaintMsgProxy(RenderWidgetHelper* h, const IPC::Message& m)
+ UpdateMsgProxy(RenderWidgetHelper* h, const IPC::Message& m)
: helper(h),
message(m),
cancelled(false) {
}
- ~PaintMsgProxy() {
+ ~UpdateMsgProxy() {
// If the paint message was never dispatched, then we need to let the
// helper know that we are going away.
if (!cancelled && helper)
- helper->OnDiscardPaintMsg(this);
+ helper->OnDiscardUpdateMsg(this);
}
virtual void Run() {
if (!cancelled) {
- helper->OnDispatchPaintMsg(this);
+ helper->OnDispatchUpdateMsg(this);
helper = NULL;
}
}
@@ -40,7 +40,7 @@ class RenderWidgetHelper::PaintMsgProxy : public Task {
IPC::Message message;
bool cancelled; // If true, then the message will not be dispatched.
- DISALLOW_COPY_AND_ASSIGN(PaintMsgProxy);
+ DISALLOW_COPY_AND_ASSIGN(UpdateMsgProxy);
};
RenderWidgetHelper::RenderWidgetHelper()
@@ -94,17 +94,17 @@ void RenderWidgetHelper::CrossSiteClosePageACK(
params));
}
-bool RenderWidgetHelper::WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool RenderWidgetHelper::WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
base::TimeTicks time_start = base::TimeTicks::Now();
for (;;) {
- PaintMsgProxy* proxy = NULL;
+ UpdateMsgProxy* proxy = NULL;
{
AutoLock lock(pending_paints_lock_);
- PaintMsgProxyMap::iterator it = pending_paints_.find(render_widget_id);
+ UpdateMsgProxyMap::iterator it = pending_paints_.find(render_widget_id);
if (it != pending_paints_.end()) {
proxy = it->second;
@@ -134,25 +134,25 @@ bool RenderWidgetHelper::WaitForPaintMsg(int render_widget_id,
return false;
}
-void RenderWidgetHelper::DidReceivePaintMsg(const IPC::Message& msg) {
+void RenderWidgetHelper::DidReceiveUpdateMsg(const IPC::Message& msg) {
int render_widget_id = msg.routing_id();
- PaintMsgProxy* proxy = NULL;
+ UpdateMsgProxy* proxy = NULL;
{
AutoLock lock(pending_paints_lock_);
- PaintMsgProxyMap::value_type new_value(render_widget_id, NULL);
+ UpdateMsgProxyMap::value_type new_value(render_widget_id, NULL);
// We expect only a single PaintRect message at a time. Optimize for the
// case that we don't already have an entry by using the 'insert' method.
- std::pair<PaintMsgProxyMap::iterator, bool> result =
+ std::pair<UpdateMsgProxyMap::iterator, bool> result =
pending_paints_.insert(new_value);
if (!result.second) {
NOTREACHED() << "Unexpected PaintRect message!";
return;
}
- result.first->second = (proxy = new PaintMsgProxy(this, msg));
+ result.first->second = (proxy = new UpdateMsgProxy(this, msg));
}
// Notify anyone waiting on the UI thread that there is a new entry in the
@@ -164,14 +164,14 @@ void RenderWidgetHelper::DidReceivePaintMsg(const IPC::Message& msg) {
ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, proxy);
}
-void RenderWidgetHelper::OnDiscardPaintMsg(PaintMsgProxy* proxy) {
+void RenderWidgetHelper::OnDiscardUpdateMsg(UpdateMsgProxy* proxy) {
const IPC::Message& msg = proxy->message;
// Remove the proxy from the map now that we are going to handle it normally.
{
AutoLock lock(pending_paints_lock_);
- PaintMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id());
+ UpdateMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id());
DCHECK(it != pending_paints_.end());
DCHECK(it->second == proxy);
@@ -179,8 +179,8 @@ void RenderWidgetHelper::OnDiscardPaintMsg(PaintMsgProxy* proxy) {
}
}
-void RenderWidgetHelper::OnDispatchPaintMsg(PaintMsgProxy* proxy) {
- OnDiscardPaintMsg(proxy);
+void RenderWidgetHelper::OnDispatchUpdateMsg(UpdateMsgProxy* proxy) {
+ OnDiscardUpdateMsg(proxy);
// It is reasonable for the host to no longer exist.
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
diff --git a/chrome/browser/renderer_host/render_widget_helper.h b/chrome/browser/renderer_host/render_widget_helper.h
index 1220970..d7e863e 100644
--- a/chrome/browser/renderer_host/render_widget_helper.h
+++ b/chrome/browser/renderer_host/render_widget_helper.h
@@ -37,20 +37,20 @@ struct ViewMsg_ClosePage_Params;
// RenderWidgetHelper is used to implement optimized resize. When the
// RenderWidgetHost is resized, it sends a Resize message to its RenderWidget
// counterpart in the renderer process. The RenderWidget generates a
-// PaintRect message in response to the Resize message, and it sets the
-// IS_RESIZE_ACK flag in the PaintRect message to true.
+// UpdateRect message in response to the Resize message, and it sets the
+// IS_RESIZE_ACK flag in the UpdateRect message to true.
//
// Back in the browser process, when the RenderProcessHost's MessageFilter
-// sees a PaintRect message, it directs it to the RenderWidgetHelper by
-// calling the DidReceivePaintMsg method. That method stores the data for
-// the PaintRect message in a map, where it can be directly accessed by the
+// sees a UpdateRect message, it directs it to the RenderWidgetHelper by
+// calling the DidReceiveUpdateMsg method. That method stores the data for
+// the UpdateRect message in a map, where it can be directly accessed by the
// RenderWidgetHost on the UI thread during a call to RenderWidgetHost's
// GetBackingStore method.
//
// When the RenderWidgetHost's GetBackingStore method is called, it first
// checks to see if it is waiting for a resize ack. If it is, then it calls
-// the RenderWidgetHelper's WaitForPaintMsg to check if there is already a
-// resulting PaintRect message (or to wait a short amount of time for one to
+// the RenderWidgetHelper's WaitForUpdateMsg to check if there is already a
+// resulting UpdateRect message (or to wait a short amount of time for one to
// arrive). The main goal of this mechanism is to short-cut the usual way in
// which IPC messages are proxied over to the UI thread via InvokeLater.
// This approach is necessary since window resize is followed up immediately
@@ -60,19 +60,19 @@ struct ViewMsg_ClosePage_Params;
// OPTIMIZED TAB SWITCHING
//
// When a RenderWidgetHost is in a background tab, it is flagged as hidden.
-// This causes the corresponding RenderWidget to stop sending PaintRect
+// This causes the corresponding RenderWidget to stop sending UpdateRect
// messages. The RenderWidgetHost also discards its backingstore when it is
// hidden, which helps free up memory. As a result, when a RenderWidgetHost
// is restored, it can be momentarily without a backingstore. (Restoring a
// RenderWidgetHost results in a WasRestored message being sent to the
-// RenderWidget, which triggers a full PaintRect message.) This can lead to
+// RenderWidget, which triggers a full UpdateRect message.) This can lead to
// an observed rendering glitch as the TabContents will just have to fill
// white overtop the RenderWidgetHost until the RenderWidgetHost receives a
-// PaintRect message to refresh its backingstore.
+// UpdateRect message to refresh its backingstore.
//
// To avoid this 'white flash', the RenderWidgetHost again makes use of the
-// RenderWidgetHelper's WaitForPaintMsg method. When the RenderWidgetHost's
-// GetBackingStore method is called, it will call WaitForPaintMsg if it has
+// RenderWidgetHelper's WaitForUpdateMsg method. When the RenderWidgetHost's
+// GetBackingStore method is called, it will call WaitForUpdateMsg if it has
// no backingstore.
//
// TRANSPORT DIB CREATION
@@ -103,9 +103,9 @@ class RenderWidgetHelper
// for documentation.
void CancelResourceRequests(int render_widget_id);
void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- bool WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
#if defined(OS_MACOSX)
// Given the id of a transport DIB, return a mapping to it or NULL on error.
@@ -115,8 +115,8 @@ class RenderWidgetHelper
// IO THREAD ONLY -----------------------------------------------------------
- // Called on the IO thread when a PaintRect message is received.
- void DidReceivePaintMsg(const IPC::Message& msg);
+ // Called on the IO thread when a UpdateRect message is received.
+ void DidReceiveUpdateMsg(const IPC::Message& msg);
void CreateNewWindow(int opener_id,
bool user_gesture,
@@ -135,20 +135,20 @@ class RenderWidgetHelper
private:
// A class used to proxy a paint message. PaintMsgProxy objects are created
// on the IO thread and destroyed on the UI thread.
- class PaintMsgProxy;
- friend class PaintMsgProxy;
+ class UpdateMsgProxy;
+ friend class UpdateMsgProxy;
friend class base::RefCountedThreadSafe<RenderWidgetHelper>;
// Map from render_widget_id to live PaintMsgProxy instance.
- typedef base::hash_map<int, PaintMsgProxy*> PaintMsgProxyMap;
+ typedef base::hash_map<int, UpdateMsgProxy*> UpdateMsgProxyMap;
~RenderWidgetHelper();
// Called on the UI thread to discard a paint message.
- void OnDiscardPaintMsg(PaintMsgProxy* proxy);
+ void OnDiscardUpdateMsg(UpdateMsgProxy* proxy);
// Called on the UI thread to dispatch a paint message if necessary.
- void OnDispatchPaintMsg(PaintMsgProxy* proxy);
+ void OnDispatchUpdateMsg(UpdateMsgProxy* proxy);
// Called on the UI thread to finish creating a window.
void OnCreateWindowOnUI(int opener_id,
@@ -179,12 +179,12 @@ class RenderWidgetHelper
// A map of live paint messages. Must hold pending_paints_lock_ to access.
// The PaintMsgProxy objects are not owned by this map. (See PaintMsgProxy
// for details about how the lifetime of instances are managed.)
- PaintMsgProxyMap pending_paints_;
+ UpdateMsgProxyMap pending_paints_;
Lock pending_paints_lock_;
int render_process_id_;
- // Event used to implement WaitForPaintMsg.
+ // Event used to implement WaitForUpdateMsg.
base::WaitableEvent event_;
// The next routing id to use.
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index c40bbf8..ad94aa6 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -124,8 +124,7 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnMsgRenderViewGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
- IPC_MESSAGE_HANDLER(ViewHostMsg_PaintRect, OnMsgPaintRect)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ScrollRect, OnMsgScrollRect)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur)
@@ -299,9 +298,9 @@ BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) {
if (resize_ack_pending_ || !backing_store) {
IPC::Message msg;
TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
- if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) {
- ViewHostMsg_PaintRect::Dispatch(
- &msg, this, &RenderWidgetHost::OnMsgPaintRect);
+ if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) {
+ ViewHostMsg_UpdateRect::Dispatch(
+ &msg, this, &RenderWidgetHost::OnMsgUpdateRect);
backing_store = BackingStoreManager::GetBackingStore(this, current_size_);
}
}
@@ -618,15 +617,15 @@ void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) {
}
}
-void RenderWidgetHost::OnMsgPaintRect(
- const ViewHostMsg_PaintRect_Params& params) {
+void RenderWidgetHost::OnMsgUpdateRect(
+ const ViewHostMsg_UpdateRect_Params& params) {
TimeTicks paint_start = TimeTicks::Now();
// Update our knowledge of the RenderWidget's size.
current_size_ = params.view_size;
bool is_resize_ack =
- ViewHostMsg_PaintRect_Flags::is_resize_ack(params.flags);
+ ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
// resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
// that will end up reaching GetBackingStore.
@@ -637,7 +636,7 @@ void RenderWidgetHost::OnMsgPaintRect(
}
bool is_repaint_ack =
- ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags);
+ ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
if (is_repaint_ack) {
repaint_ack_pending_ = false;
TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
@@ -653,12 +652,19 @@ void RenderWidgetHost::OnMsgPaintRect(
if (dib) {
if (dib->size() < size) {
DLOG(WARNING) << "Transport DIB too small for given rectangle";
- process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID);
+ process()->ReceivedBadMessage(ViewHostMsg_UpdateRect__ID);
} else {
+ // Scroll the backing store.
+ if (!params.scroll_rect.IsEmpty()) {
+ ScrollBackingStoreRect(params.dx, params.dy,
+ params.scroll_rect,
+ params.view_size);
+ }
+
// Paint the backing store. This will update it with the renderer-supplied
// bits. The view will read out of the backing store later to actually
// draw to the screen.
- PaintBackingStoreRect(dib, params.bitmap_rect, params.update_rects,
+ PaintBackingStoreRect(dib, params.bitmap_rect, params.copy_rects,
params.view_size);
}
}
@@ -667,7 +673,7 @@ void RenderWidgetHost::OnMsgPaintRect(
// This must be done AFTER we're done painting with the bitmap supplied by the
// renderer. This ACK is a signal to the renderer that the backing store can
// be re-used, so the bitmap may be invalid after this call.
- Send(new ViewMsg_PaintRect_ACK(routing_id_));
+ Send(new ViewMsg_UpdateRect_ACK(routing_id_));
// We don't need to update the view if the view is hidden. We must do this
// early return after the ACK is sent, however, or the renderer will not send
@@ -679,7 +685,12 @@ void RenderWidgetHost::OnMsgPaintRect(
if (view_) {
view_->MovePluginWindows(params.plugin_window_moves);
view_being_painted_ = true;
- view_->DidPaintRect(params.bitmap_rect);
+ if (!params.scroll_rect.IsEmpty()) {
+ view_->DidScrollBackingStoreRect(params.scroll_rect,
+ params.dx,
+ params.dy);
+ }
+ view_->DidPaintBackingStoreRects(params.copy_rects);
view_being_painted_ = false;
}
@@ -700,56 +711,7 @@ void RenderWidgetHost::OnMsgPaintRect(
// Log the time delta for processing a paint message.
TimeDelta delta = TimeTicks::Now() - paint_start;
- UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta);
-}
-
-void RenderWidgetHost::OnMsgScrollRect(
- const ViewHostMsg_ScrollRect_Params& params) {
- TimeTicks scroll_start = TimeTicks::Now();
-
- DCHECK(!params.view_size.IsEmpty());
-
- const size_t size = params.bitmap_rect.height() *
- params.bitmap_rect.width() * 4;
- TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
- if (dib) {
- if (dib->size() < size) {
- LOG(WARNING) << "Transport DIB too small for given rectangle";
- process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID);
- } else {
- // Scroll the backing store.
- ScrollBackingStoreRect(dib, params.bitmap_rect,
- params.dx, params.dy,
- params.clip_rect, params.view_size);
- }
- }
-
- // ACK early so we can prefetch the next ScrollRect if there is a next one.
- // This must be done AFTER we're done painting with the bitmap supplied by the
- // renderer. This ACK is a signal to the renderer that the backing store can
- // be re-used, so the bitmap may be invalid after this call.
- Send(new ViewMsg_ScrollRect_ACK(routing_id_));
-
- // We don't need to update the view if the view is hidden. We must do this
- // early return after the ACK is sent, however, or the renderer will not send
- // is more data.
- if (is_hidden_)
- return;
-
- // Paint the view. Watch out: it might be destroyed already.
- if (view_) {
- view_being_painted_ = true;
- view_->MovePluginWindows(params.plugin_window_moves);
- view_->DidScrollRect(params.clip_rect, params.dx, params.dy);
- view_being_painted_ = false;
- }
-
- if (painting_observer_)
- painting_observer_->WidgetDidUpdateBackingStore(this);
-
- // Log the time delta for processing a scroll message.
- TimeDelta delta = TimeTicks::Now() - scroll_start;
- UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta);
+ UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
}
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
@@ -891,9 +853,7 @@ void RenderWidgetHost::PaintBackingStoreRect(
}
}
-void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
+void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
if (is_hidden_) {
@@ -910,8 +870,7 @@ void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap,
BackingStore* backing_store = BackingStoreManager::Lookup(this);
if (!backing_store || (backing_store->size() != view_size))
return;
- backing_store->ScrollRect(process_->GetHandle(), bitmap, bitmap_rect,
- dx, dy, clip_rect, view_size);
+ backing_store->ScrollRect(dx, dy, clip_rect, view_size);
}
void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index dc425b0..d59fc4e 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -38,9 +38,8 @@ class RenderWidgetHostView;
class RenderWidgetHostPaintingObserver;
class TransportDIB;
class WebCursor;
-struct ViewHostMsg_PaintRect_Params;
-struct ViewHostMsg_ScrollRect_Params;
struct ViewHostMsg_ShowPopup_Params;
+struct ViewHostMsg_UpdateRect_Params;
// This class manages the browser side of a browser<->renderer HWND connection.
// The HWND lives in the browser process, and windows events are sent over
@@ -413,8 +412,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
void OnMsgRenderViewGone();
void OnMsgClose();
void OnMsgRequestMove(const gfx::Rect& pos);
- void OnMsgPaintRect(const ViewHostMsg_PaintRect_Params& params);
- void OnMsgScrollRect(const ViewHostMsg_ScrollRect_Params& params);
+ void OnMsgUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
void OnMsgInputEventAck(const IPC::Message& message);
void OnMsgFocus();
void OnMsgBlur();
@@ -444,10 +442,7 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// Scrolls the given |clip_rect| in the backing by the given dx/dy amount. The
// |dib| and its corresponding location |bitmap_rect| in the backing store
// is the newly painted pixels by the renderer.
- void ScrollBackingStoreRect(TransportDIB* dib,
- const gfx::Rect& bitmap_rect,
- int dx, int dy,
- const gfx::Rect& clip_rect,
+ void ScrollBackingStoreRect(int dx, int dy, const gfx::Rect& clip_rect,
const gfx::Size& view_size);
// Called by OnMsgInputEventAck() to process a keyboard event ack message.
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index e3f4517..dc411dd 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -21,9 +21,9 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
public:
explicit RenderWidgetHostProcess(Profile* profile)
: MockRenderProcessHost(profile),
- current_paint_buf_(NULL),
- paint_msg_should_reply_(false),
- paint_msg_reply_flags_(0) {
+ current_update_buf_(NULL),
+ update_msg_should_reply_(false),
+ update_msg_reply_flags_(0) {
// DANGER! This is a hack. The RenderWidgetHost checks the channel to see
// if the process is still alive, but it doesn't actually dereference it.
// An IPC::SyncChannel is nontrivial, so we just fake it here. If you end up
@@ -34,64 +34,65 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
// We don't want to actually delete the channel, since it's not a real
// pointer.
channel_.release();
- if (current_paint_buf_)
- delete current_paint_buf_;
+ delete current_update_buf_;
}
- void set_paint_msg_should_reply(bool reply) {
- paint_msg_should_reply_ = reply;
+ void set_update_msg_should_reply(bool reply) {
+ update_msg_should_reply_ = reply;
}
- void set_paint_msg_reply_flags(int flags) {
- paint_msg_reply_flags_ = flags;
+ void set_update_msg_reply_flags(int flags) {
+ update_msg_reply_flags_ = flags;
}
- // Fills the given paint parameters with resonable default values.
- void InitPaintRectParams(ViewHostMsg_PaintRect_Params* params);
+ // Fills the given update parameters with resonable default values.
+ void InitUpdateRectParams(ViewHostMsg_UpdateRect_Params* params);
protected:
- virtual bool WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
- TransportDIB* current_paint_buf_;
+ TransportDIB* current_update_buf_;
- // Set to true when WaitForPaintMsg should return a successful paint messaage
+ // Set to true when WaitForUpdateMsg should return a successful update messaage
// reply. False implies timeout.
- bool paint_msg_should_reply_;
+ bool update_msg_should_reply_;
// Indicates the flags that should be sent with a the repaint request. This
- // only has an effect when paint_msg_should_reply_ is true.
- int paint_msg_reply_flags_;
+ // only has an effect when update_msg_should_reply_ is true.
+ int update_msg_reply_flags_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess);
};
-void RenderWidgetHostProcess::InitPaintRectParams(
- ViewHostMsg_PaintRect_Params* params) {
+void RenderWidgetHostProcess::InitUpdateRectParams(
+ ViewHostMsg_UpdateRect_Params* params) {
// Create the shared backing store.
const int w = 100, h = 100;
const size_t pixel_size = w * h * 4;
- if (!current_paint_buf_)
- current_paint_buf_ = TransportDIB::Create(pixel_size, 0);
- params->bitmap = current_paint_buf_->id();
+ if (!current_update_buf_)
+ current_update_buf_ = TransportDIB::Create(pixel_size, 0);
+ params->bitmap = current_update_buf_->id();
params->bitmap_rect = gfx::Rect(0, 0, w, h);
- params->update_rects.push_back(params->bitmap_rect);
+ params->dx = 0;
+ params->dy = 0;
+ params->copy_rects.push_back(params->bitmap_rect);
params->view_size = gfx::Size(w, h);
- params->flags = paint_msg_reply_flags_;
+ params->flags = update_msg_reply_flags_;
}
-bool RenderWidgetHostProcess::WaitForPaintMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
- if (!paint_msg_should_reply_)
+bool RenderWidgetHostProcess::WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
+ if (!update_msg_should_reply_)
return false;
- // Construct a fake paint reply.
- ViewHostMsg_PaintRect_Params params;
- InitPaintRectParams(&params);
+ // Construct a fake update reply.
+ ViewHostMsg_UpdateRect_Params params;
+ InitUpdateRectParams(&params);
- ViewHostMsg_PaintRect message(render_widget_id, params);
+ ViewHostMsg_UpdateRect message(render_widget_id, params);
*msg = message;
return true;
}
@@ -249,11 +250,11 @@ TEST_F(RenderWidgetHostTest, Resize) {
EXPECT_EQ(original_size.size(), host_->in_flight_size_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
- // Send out a paint that's not a resize ack. This should not clean the
+ // Send out a update that's not a resize ack. This should not clean the
// resize ack pending flag.
- ViewHostMsg_PaintRect_Params params;
- process_->InitPaintRectParams(&params);
- host_->OnMsgPaintRect(params);
+ ViewHostMsg_UpdateRect_Params params;
+ process_->InitUpdateRectParams(&params);
+ host_->OnMsgUpdateRect(params);
EXPECT_TRUE(host_->resize_ack_pending_);
EXPECT_EQ(original_size.size(), host_->in_flight_size_);
@@ -267,13 +268,13 @@ TEST_F(RenderWidgetHostTest, Resize) {
EXPECT_EQ(original_size.size(), host_->in_flight_size_);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
- // Send a paint that's a resize ack, but for the original_size we sent. Since
+ // Send a update that's a resize ack, but for the original_size we sent. Since
// this isn't the second_size, the message handler should immediately send
// a new resize message for the new size to the renderer.
process_->sink().ClearMessages();
- params.flags = ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK;
+ params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
params.view_size = original_size.size();
- host_->OnMsgPaintRect(params);
+ host_->OnMsgUpdateRect(params);
EXPECT_TRUE(host_->resize_ack_pending_);
EXPECT_EQ(second_size.size(), host_->in_flight_size_);
ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
@@ -281,7 +282,7 @@ TEST_F(RenderWidgetHostTest, Resize) {
// Send the resize ack for the latest size.
process_->sink().ClearMessages();
params.view_size = second_size.size();
- host_->OnMsgPaintRect(params);
+ host_->OnMsgUpdateRect(params);
EXPECT_FALSE(host_->resize_ack_pending_);
EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
@@ -320,7 +321,7 @@ TEST_F(RenderWidgetHostTest, Resize) {
}
// Test for crbug.com/25097. If a renderer crashes between a resize and the
-// corresponding paint message, we must be sure to clear the resize ack logic.
+// corresponding update message, we must be sure to clear the resize ack logic.
TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
// Setting the bounds to a "real" rect should send out the notification.
gfx::Rect original_size(0, 0, 100, 100);
@@ -330,8 +331,9 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
EXPECT_EQ(original_size.size(), host_->in_flight_size_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
- // Simulate a renderer crash before the paint message. Ensure all the resize
- // ack logic is cleared. Must clear the view first so it doesn't get deleted.
+ // Simulate a renderer crash before the update message. Ensure all the
+ // resize ack logic is cleared. Must clear the view first so it doesn't get
+ // deleted.
host_->set_view(NULL);
host_->RendererExited();
EXPECT_FALSE(host_->resize_ack_pending_);
@@ -398,42 +400,42 @@ TEST_F(RenderWidgetHostTest, Background) {
TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) {
// We don't currently have a backing store, and if the renderer doesn't send
// one in time, we should get nothing.
- process_->set_paint_msg_should_reply(false);
+ process_->set_update_msg_should_reply(false);
BackingStore* backing = host_->GetBackingStore(true);
EXPECT_FALSE(backing);
// The widget host should have sent a request for a repaint, and there should
// be no paint ACK.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_PaintRect_ACK::ID));
+ ViewMsg_UpdateRect_ACK::ID));
// Allowing the renderer to reply in time should give is a backing store.
process_->sink().ClearMessages();
- process_->set_paint_msg_should_reply(true);
- process_->set_paint_msg_reply_flags(0);
+ process_->set_update_msg_should_reply(true);
+ process_->set_update_msg_reply_flags(0);
backing = host_->GetBackingStore(true);
EXPECT_TRUE(backing);
// The widget host should NOT have sent a request for a repaint, since there
// was an ACK already pending.
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_PaintRect_ACK::ID));
+ ViewMsg_UpdateRect_ACK::ID));
}
// Tests getting the backing store with the renderer sending a repaint ack.
TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
- // Doing a request request with the paint message allowed should work and
+ // Doing a request request with the update message allowed should work and
// the repaint ack should work.
- process_->set_paint_msg_should_reply(true);
- process_->set_paint_msg_reply_flags(
- ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK);
+ process_->set_update_msg_should_reply(true);
+ process_->set_update_msg_reply_flags(
+ ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK);
BackingStore* backing = host_->GetBackingStore(true);
EXPECT_TRUE(backing);
// We still should not have sent out a repaint request since the last flags
// didn't have the repaint ack set, and the pending flag will still be set.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_PaintRect_ACK::ID));
+ ViewMsg_UpdateRect_ACK::ID));
// Asking again for the backing store should just re-use the existing one
// and not send any messagse.
@@ -442,7 +444,7 @@ TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
EXPECT_TRUE(backing);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_PaintRect_ACK::ID));
+ ViewMsg_UpdateRect_ACK::ID));
}
// Test that we don't paint when we're hidden, but we still send the ACK. Most
@@ -454,15 +456,15 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
EXPECT_TRUE(host_->is_hidden_);
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_WasHidden::ID));
- // Send it a paint as from the renderer.
+ // Send it an update as from the renderer.
process_->sink().ClearMessages();
- ViewHostMsg_PaintRect_Params params;
- process_->InitPaintRectParams(&params);
- host_->OnMsgPaintRect(params);
+ ViewHostMsg_UpdateRect_Params params;
+ process_->InitUpdateRectParams(&params);
+ host_->OnMsgUpdateRect(params);
// It should have sent out the ACK.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_PaintRect_ACK::ID));
+ ViewMsg_UpdateRect_ACK::ID));
// Now unhide.
process_->sink().ClearMessages();
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 3a71011..2a87291 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -110,13 +110,14 @@ class RenderWidgetHostView {
// (Worse, we might recursively call RenderWidgetHost::GetBackingStore().)
// Thus implementers should generally paint as much of |rect| as possible
// synchronously with as little overpainting as possible.
- virtual void DidPaintRect(const gfx::Rect& rect) = 0;
+ virtual void DidPaintBackingStoreRects(
+ const std::vector<gfx::Rect>& rects) = 0;
// Informs the view that a portion of the widget's backing store was scrolled
// by dx pixels horizontally and dy pixels vertically. The view should copy
// the exposed pixels from the backing store of the render widget (which has
// already been scrolled) onto the screen.
- virtual void DidScrollRect(
+ virtual void DidScrollBackingStoreRect(
const gfx::Rect& rect, int dx, int dy) = 0;
// Notifies the View that the renderer has ceased to exist.
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index cd38ec8..8ce8747 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -505,21 +505,27 @@ void RenderWidgetHostViewGtk::IMEUpdateStatus(int control,
key_bindings_handler_->set_enabled(control != IME_DISABLE);
}
-void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) {
+void RenderWidgetHostViewGtk::DidPaintBackingStoreRects(
+ const std::vector<gfx::Rect>& rects) {
if (is_hidden_)
return;
- if (about_to_validate_and_paint_)
- invalid_rect_ = invalid_rect_.Union(rect);
- else
- Paint(rect);
+ for (size_t i = 0; i < rects.size(); ++i) {
+ if (about_to_validate_and_paint_) {
+ invalid_rect_ = invalid_rect_.Union(rects[i]);
+ } else {
+ Paint(rects[i]);
+ }
+ }
}
-void RenderWidgetHostViewGtk::DidScrollRect(const gfx::Rect& rect, int dx,
- int dy) {
+void RenderWidgetHostViewGtk::DidScrollBackingStoreRect(const gfx::Rect& rect,
+ int dx, int dy) {
if (is_hidden_)
return;
+ // TODO(darin): Implement the equivalent of Win32's ScrollWindowEX. Can that
+ // be done using XCopyArea? Perhaps similar to BackingStore::ScrollRect?
Paint(rect);
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index 94f4f1a..5c05094 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -60,8 +60,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintRect(const gfx::Rect& rect);
- virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
+ virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void Destroy();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index c661578..3dc07b2 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -95,8 +95,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintRect(const gfx::Rect& rect);
- virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
+ virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {};
virtual void Destroy();
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 78d2736..55cfaef 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -275,26 +275,31 @@ void RenderWidgetHostViewMac::IMEUpdateStatus(int control,
caret_rect.width(), caret_rect.height());
}
-void RenderWidgetHostViewMac::DidPaintRect(const gfx::Rect& rect) {
+void RenderWidgetHostViewMac::DidPaintBackingStoreRects(
+ const std::vector<gfx::Rect>& rects) {
if (is_hidden_)
return;
- NSRect ns_rect = [cocoa_view_ RectToNSRect:rect];
+ for (size_t i = 0; i < rects.size(); ++i) {
+ NSRect ns_rect = [cocoa_view_ RectToNSRect:rects[i]];
+
+ if (about_to_validate_and_paint_) {
+ // As much as we'd like to use -setNeedsDisplayInRect: here, we can't.
+ // We're in the middle of executing a -drawRect:, and as soon as it
+ // returns Cocoa will clear its record of what needs display. If we want
+ // to handle the recursive drawing, we need to do it ourselves.
+ invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
+ } else {
+ [cocoa_view_ setNeedsDisplayInRect:ns_rect];
+ }
+ }
- if (about_to_validate_and_paint_) {
- // As much as we'd like to use -setNeedsDisplayInRect: here, we can't. We're
- // in the middle of executing a -drawRect:, and as soon as it returns Cocoa
- // will clear its record of what needs display. If we want to handle the
- // recursive drawing, we need to do it ourselves.
- invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
- } else {
- [cocoa_view_ setNeedsDisplayInRect:ns_rect];
+ if (!about_to_validate_and_paint_)
[cocoa_view_ displayIfNeeded];
- }
}
-void RenderWidgetHostViewMac::DidScrollRect(
- const gfx::Rect& rect, int dx, int dy) {
+void RenderWidgetHostViewMac::DidScrollBackingStoreRect(const gfx::Rect& rect,
+ int dx, int dy) {
if (is_hidden_)
return;
@@ -305,7 +310,7 @@ void RenderWidgetHostViewMac::DidScrollRect(
// TODO(rohitrao): Evaluate how slow this full redraw is. If it
// turns out to be a problem, consider scrolling only a portion of
// the view, based on where the findbar and blocked popups are.
- DidPaintRect(rect);
+ DidPaintBackingStoreRects(std::vector<gfx::Rect>(1, rect));
}
void RenderWidgetHostViewMac::RenderViewGone() {
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index e0b3832..8be4df5 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -568,7 +568,13 @@ BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) {
return TRUE;
}
-void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) {
+void RenderWidgetHostViewWin::Redraw() {
+ RECT damage_bounds;
+ GetUpdateRect(&damage_bounds, FALSE);
+
+ ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
+ GetUpdateRgn(damage_region, FALSE);
+
// Paint the invalid region synchronously. Our caller will not paint again
// until we return, so by painting to the screen here, we ensure effective
// rate-limiting of backing store updates. This helps a lot on pages that
@@ -579,12 +585,11 @@ void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) {
// message dispatching we allow scrolling to be smooth, and also avoid the
// browser process locking up if the plugin process is hung.
//
- RedrawWindow(
- &rect.ToRECT(), NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
+ RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN);
// Send the invalid rect in screen coordinates.
gfx::Rect screen_rect = GetViewBounds();
- gfx::Rect invalid_screen_rect = rect;
+ gfx::Rect invalid_screen_rect(damage_bounds);
invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect);
@@ -619,31 +624,29 @@ void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect,
}
}
-void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) {
+void RenderWidgetHostViewWin::DidPaintBackingStoreRects(
+ const std::vector<gfx::Rect>& rects) {
if (is_hidden_)
return;
- if (about_to_validate_and_paint_)
- InvalidateRect(&rect.ToRECT(), false);
- else
- Redraw(rect);
+ for (size_t i = 0; i < rects.size(); ++i)
+ InvalidateRect(&rects[i].ToRECT(), false);
+
+ if (!about_to_validate_and_paint_)
+ Redraw();
}
-void RenderWidgetHostViewWin::DidScrollRect(
+void RenderWidgetHostViewWin::DidScrollBackingStoreRect(
const gfx::Rect& rect, int dx, int dy) {
if (is_hidden_)
return;
- // We need to pass in SW_INVALIDATE to ScrollWindowEx. The MSDN
- // documentation states that it only applies to the HRGN argument, which is
- // wrong. Not passing in this flag does not invalidate the region which was
- // scrolled from, thus causing painting issues.
+ // We need to pass in SW_INVALIDATE to ScrollWindowEx. The documentation on
+ // MSDN states that it only applies to the HRGN argument, which is wrong.
+ // Not passing in this flag does not invalidate the region which was scrolled
+ // from, thus causing painting issues.
RECT clip_rect = rect.ToRECT();
ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
-
- RECT invalid_rect = {0};
- GetUpdateRect(&invalid_rect);
- Redraw(gfx::Rect(invalid_rect));
}
void RenderWidgetHostViewWin::RenderViewGone() {
@@ -765,6 +768,12 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) {
// GetBackingStore(), so that if it updates the invalid rect we'll catch the
// changes and repaint them.
about_to_validate_and_paint_ = false;
+
+ // Grab the region to paint before creation of paint_dc since it clears the
+ // damage region.
+ ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
+ GetUpdateRgn(damage_region, FALSE);
+
CPaintDC paint_dc(m_hWnd);
gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
@@ -772,28 +781,38 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) {
return;
if (backing_store) {
- gfx::Rect bitmap_rect(
- 0, 0, backing_store->size().width(), backing_store->size().height());
-
- gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect);
- if (!paint_rect.IsEmpty()) {
- DrawResizeCorner(paint_rect, backing_store->hdc());
- bool manage_colors = BackingStore::ColorManagementEnabled();
- if (manage_colors)
- SetICMMode(paint_dc.m_hDC, ICM_ON);
- BitBlt(paint_dc.m_hDC,
- paint_rect.x(),
- paint_rect.y(),
- paint_rect.width(),
- paint_rect.height(),
- backing_store->hdc(),
- paint_rect.x(),
- paint_rect.y(),
- SRCCOPY);
- if (manage_colors)
- SetICMMode(paint_dc.m_hDC, ICM_OFF);
+ gfx::Rect bitmap_rect(gfx::Point(), backing_store->size());
+
+ bool manage_colors = BackingStore::ColorManagementEnabled();
+ if (manage_colors)
+ SetICMMode(paint_dc.m_hDC, ICM_ON);
+
+ // Blit only the damaged regions from the backing store.
+ DWORD data_size = GetRegionData(damage_region, 0, NULL);
+ scoped_array<char> region_data_buf(new char[data_size]);
+ RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
+ GetRegionData(damage_region, data_size, region_data);
+
+ RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
+ for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
+ gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i]));
+ if (!paint_rect.IsEmpty()) {
+ DrawResizeCorner(paint_rect, backing_store->hdc());
+ BitBlt(paint_dc.m_hDC,
+ paint_rect.x(),
+ paint_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ backing_store->hdc(),
+ paint_rect.x(),
+ paint_rect.y(),
+ SRCCOPY);
+ }
}
+ if (manage_colors)
+ SetICMMode(paint_dc.m_hDC, ICM_OFF);
+
// Fill the remaining portion of the damaged_rect with the background
if (damaged_rect.right() > bitmap_rect.right()) {
RECT r;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 57b220b..3b54064 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -125,8 +125,8 @@ class RenderWidgetHostViewWin
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintRect(const gfx::Rect& rect);
- virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
+ virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh);
virtual void Destroy();
@@ -207,7 +207,7 @@ class RenderWidgetHostViewWin
// Redraws the window synchronously, and any child windows (i.e. plugins)
// asynchronously.
- void Redraw(const gfx::Rect& invalid_rect);
+ void Redraw();
// Draw the resize corner bitmap on top of the given HDC, if it intersects the
// given paint rect.
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 662a5c2..34520fe1 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -326,8 +326,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms,
OnRendererHistograms)
- IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect,
- render_widget_helper_->DidReceivePaintMsg(msg))
+ IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
+ render_widget_helper_->DidReceiveUpdateMsg(msg))
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync,
OnClipboardWriteObjects)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync,
diff --git a/chrome/browser/renderer_host/test/render_view_host_unittest.cc b/chrome/browser/renderer_host/test/render_view_host_unittest.cc
index 259634f..c281d63 100644
--- a/chrome/browser/renderer_host/test/render_view_host_unittest.cc
+++ b/chrome/browser/renderer_host/test/render_view_host_unittest.cc
@@ -36,9 +36,9 @@ TEST_F(RenderViewHostTest, BadMessageHandlerRenderViewHost) {
// ReceivedBadMessage() handler.
TEST_F(RenderViewHostTest, BadMessageHandlerRenderWidgetHost) {
EXPECT_EQ(0, process()->bad_msg_count());
- // craft an incorrect ViewHostMsg_PaintRect message. The real one has
+ // craft an incorrect ViewHostMsg_UpdateRect message. The real one has
// one payload item but the one we construct has none.
- IPC::Message message(0, ViewHostMsg_PaintRect::ID,
+ IPC::Message message(0, ViewHostMsg_UpdateRect::ID,
IPC::Message::PRIORITY_NORMAL);
rvh()->TestOnMessageReceived(message);
EXPECT_EQ(1, process()->bad_msg_count());
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index b1458a1..9990fab 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -64,8 +64,10 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor) {}
virtual void UpdateCursorIfOverSelf() {}
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect) {}
- virtual void DidPaintRect(const gfx::Rect& rect) {}
- virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {}
+ virtual void DidPaintBackingStoreRects(
+ const std::vector<gfx::Rect>& rects) {}
+ virtual void DidScrollBackingStoreRect(
+ const gfx::Rect& rect, int dx, int dy) {}
virtual void RenderViewGone() { delete this; }
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
virtual void Destroy() {}
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 9e2e6fc..c886522 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -176,8 +176,8 @@ struct ViewHostMsg_FrameNavigate_Params {
};
// Values that may be OR'd together to form the 'flags' parameter of a
-// ViewHostMsg_PaintRect message.
-struct ViewHostMsg_PaintRect_Flags {
+// ViewHostMsg_UpdateRect_Params structure.
+struct ViewHostMsg_UpdateRect_Flags {
enum {
IS_RESIZE_ACK = 1 << 0,
IS_RESTORE_ACK = 1 << 1,
@@ -189,13 +189,12 @@ struct ViewHostMsg_PaintRect_Flags {
static bool is_restore_ack(int flags) {
return (flags & IS_RESTORE_ACK) != 0;
}
-
static bool is_repaint_ack(int flags) {
return (flags & IS_REPAINT_ACK) != 0;
}
};
-struct ViewHostMsg_PaintRect_Params {
+struct ViewHostMsg_UpdateRect_Params {
// The bitmap to be painted into the view at the locations specified by
// update_rects.
TransportDIB::Id bitmap;
@@ -203,8 +202,18 @@ struct ViewHostMsg_PaintRect_Params {
// The position and size of the bitmap.
gfx::Rect bitmap_rect;
+ // The scroll offset. Only one of these can be non-zero, and if they are
+ // both zero, then it means there is no scrolling and the scroll_rect is
+ // ignored.
+ int dx;
+ int dy;
+
+ // The rectangular region to scroll.
+ gfx::Rect scroll_rect;
+
// The regions of the bitmap (in view coords) that contain updated pixels.
- std::vector<gfx::Rect> update_rects;
+ // In the case of scrolling, this includes the scroll damage rect.
+ std::vector<gfx::Rect> copy_rects;
// The size of the RenderView when this message was generated. This is
// included so the host knows how large the view is from the perspective of
@@ -217,42 +226,22 @@ struct ViewHostMsg_PaintRect_Params {
// The following describes the various bits that may be set in flags:
//
- // ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK
+ // ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK
// Indicates that this is a response to a ViewMsg_Resize message.
//
- // ViewHostMsg_PaintRect_Flags::IS_RESTORE_ACK
+ // ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK
// Indicates that this is a response to a ViewMsg_WasRestored message.
//
+ // ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK
+ // Indicates that this is a response to a ViewMsg_Repaint message.
+ //
// If flags is zero, then this message corresponds to an unsoliticed paint
- // request by the render view. Both of the above bits may be set in flags,
+ // request by the render view. Any of the above bits may be set in flags,
// which would indicate that this paint message is an ACK for multiple
// request messages.
int flags;
};
-// Parameters structure for ViewHostMsg_ScrollRect, which has too many data
-// parameters to be reasonably put in a predefined IPC message.
-struct ViewHostMsg_ScrollRect_Params {
- // The bitmap to be painted into the rect exposed by scrolling.
- TransportDIB::Id bitmap;
-
- // The position and size of the bitmap.
- gfx::Rect bitmap_rect;
-
- // The scroll offset. Only one of these can be non-zero.
- int dx;
- int dy;
-
- // The rectangular region to scroll.
- gfx::Rect clip_rect;
-
- // The size of the RenderView when this message was generated.
- gfx::Size view_size;
-
- // New window locations for plugin child windows.
- std::vector<webkit_glue::WebPluginGeometry> plugin_window_moves;
-};
-
// Information on closing a tab. This is used both for ViewMsg_ClosePage, and
// the corresponding ViewHostMsg_ClosePage_ACK.
struct ViewMsg_ClosePage_Params {
@@ -978,56 +967,20 @@ struct ParamTraits<ContextMenuParams> {
}
};
-// Traits for ViewHostMsg_PaintRect_Params structure to pack/unpack.
+// Traits for ViewHostMsg_UpdateRect_Params structure to pack/unpack.
template <>
-struct ParamTraits<ViewHostMsg_PaintRect_Params> {
- typedef ViewHostMsg_PaintRect_Params param_type;
- static void Write(Message* m, const param_type& p) {
- WriteParam(m, p.bitmap);
- WriteParam(m, p.bitmap_rect);
- WriteParam(m, p.update_rects);
- WriteParam(m, p.view_size);
- WriteParam(m, p.plugin_window_moves);
- WriteParam(m, p.flags);
- }
- static bool Read(const Message* m, void** iter, param_type* p) {
- return
- ReadParam(m, iter, &p->bitmap) &&
- ReadParam(m, iter, &p->bitmap_rect) &&
- ReadParam(m, iter, &p->update_rects) &&
- ReadParam(m, iter, &p->view_size) &&
- ReadParam(m, iter, &p->plugin_window_moves) &&
- ReadParam(m, iter, &p->flags);
- }
- static void Log(const param_type& p, std::wstring* l) {
- l->append(L"(");
- LogParam(p.bitmap, l);
- l->append(L", ");
- LogParam(p.bitmap_rect, l);
- l->append(L", ");
- LogParam(p.update_rects, l);
- l->append(L", ");
- LogParam(p.view_size, l);
- l->append(L", ");
- LogParam(p.plugin_window_moves, l);
- l->append(L", ");
- LogParam(p.flags, l);
- l->append(L")");
- }
-};
-
-// Traits for ViewHostMsg_ScrollRect_Params structure to pack/unpack.
-template <>
-struct ParamTraits<ViewHostMsg_ScrollRect_Params> {
- typedef ViewHostMsg_ScrollRect_Params param_type;
+struct ParamTraits<ViewHostMsg_UpdateRect_Params> {
+ typedef ViewHostMsg_UpdateRect_Params param_type;
static void Write(Message* m, const param_type& p) {
WriteParam(m, p.bitmap);
WriteParam(m, p.bitmap_rect);
WriteParam(m, p.dx);
WriteParam(m, p.dy);
- WriteParam(m, p.clip_rect);
+ WriteParam(m, p.scroll_rect);
+ WriteParam(m, p.copy_rects);
WriteParam(m, p.view_size);
WriteParam(m, p.plugin_window_moves);
+ WriteParam(m, p.flags);
}
static bool Read(const Message* m, void** iter, param_type* p) {
return
@@ -1035,9 +988,11 @@ struct ParamTraits<ViewHostMsg_ScrollRect_Params> {
ReadParam(m, iter, &p->bitmap_rect) &&
ReadParam(m, iter, &p->dx) &&
ReadParam(m, iter, &p->dy) &&
- ReadParam(m, iter, &p->clip_rect) &&
+ ReadParam(m, iter, &p->scroll_rect) &&
+ ReadParam(m, iter, &p->copy_rects) &&
ReadParam(m, iter, &p->view_size) &&
- ReadParam(m, iter, &p->plugin_window_moves);
+ ReadParam(m, iter, &p->plugin_window_moves) &&
+ ReadParam(m, iter, &p->flags);
}
static void Log(const param_type& p, std::wstring* l) {
l->append(L"(");
@@ -1049,11 +1004,15 @@ struct ParamTraits<ViewHostMsg_ScrollRect_Params> {
l->append(L", ");
LogParam(p.dy, l);
l->append(L", ");
- LogParam(p.clip_rect, l);
+ LogParam(p.scroll_rect, l);
+ l->append(L", ");
+ LogParam(p.copy_rects, l);
l->append(L", ");
LogParam(p.view_size, l);
l->append(L", ");
LogParam(p.plugin_window_moves, l);
+ l->append(L", ");
+ LogParam(p.flags, l);
l->append(L")");
}
};
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 3f9a1f1..ca3e80b 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -128,10 +128,6 @@ IPC_BEGIN_MESSAGES(View)
// render view responds with a ViewHostMsg_Thumbnail.
IPC_MESSAGE_ROUTED0(ViewMsg_CaptureThumbnail)
- // Tells the render view that a ViewHostMsg_PaintRect message was processed.
- // This signals the render view that it can send another PaintRect message.
- IPC_MESSAGE_ROUTED0(ViewMsg_PaintRect_ACK)
-
// Tells the render view to switch the CSS to print media type, renders every
// requested pages and switch back the CSS to display media type.
IPC_MESSAGE_ROUTED0(ViewMsg_PrintPages)
@@ -147,9 +143,9 @@ IPC_BEGIN_MESSAGES(View)
// JS garbage, not in purging irreplaceable objects.
IPC_MESSAGE_CONTROL0(ViewMsg_PurgeMemory)
- // Tells the render view that a ViewHostMsg_ScrollRect message was processed.
- // This signals the render view that it can send another ScrollRect message.
- IPC_MESSAGE_ROUTED0(ViewMsg_ScrollRect_ACK)
+ // Tells the render view that a ViewHostMsg_UpdateRect message was processed.
+ // This signals the render view that it can send another UpdateRect message.
+ IPC_MESSAGE_ROUTED0(ViewMsg_UpdateRect_ACK)
// Message payload includes:
// 1. A blob that should be cast to WebInputEvent
@@ -993,15 +989,10 @@ IPC_BEGIN_MESSAGES(ViewHost)
navigating to a POST again and we're going to
show the POST interstitial */ )
- // Sent to paint part of the view. In response to this message, the host
- // generates a ViewMsg_PaintRect_ACK message.
- IPC_MESSAGE_ROUTED1(ViewHostMsg_PaintRect,
- ViewHostMsg_PaintRect_Params)
-
- // Sent to scroll part of the view. In response to this message, the host
- // generates a ViewMsg_ScrollRect_ACK message.
- IPC_MESSAGE_ROUTED1(ViewHostMsg_ScrollRect,
- ViewHostMsg_ScrollRect_Params)
+ // Sent to update part of the view. In response to this message, the host
+ // generates a ViewMsg_UpdateRect_ACK message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateRect,
+ ViewHostMsg_UpdateRect_Params)
// Acknowledges receipt of a ViewMsg_HandleInputEvent message.
// Payload is a WebInputEvent::Type which is the type of the event, followed
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index 27955bb..8a3513c 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -50,9 +50,8 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable)
render_thread_(render_thread),
host_window_(0),
current_paint_buf_(NULL),
- current_scroll_buf_(NULL),
next_paint_flags_(0),
- paint_reply_pending_(false),
+ update_reply_pending_(false),
did_show_(false),
is_hidden_(false),
needs_repainting_on_restore_(false),
@@ -79,10 +78,6 @@ RenderWidget::~RenderWidget() {
RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
current_paint_buf_ = NULL;
}
- if (current_scroll_buf_) {
- RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
- current_scroll_buf_ = NULL;
- }
RenderProcess::current()->ReleaseProcess();
}
@@ -142,8 +137,7 @@ IPC_DEFINE_MESSAGE_MAP(RenderWidget)
IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasRestored, OnWasRestored)
- IPC_MESSAGE_HANDLER(ViewMsg_PaintRect_ACK, OnPaintRectAck)
- IPC_MESSAGE_HANDLER(ViewMsg_ScrollRect_ACK, OnScrollRectAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
@@ -258,11 +252,17 @@ void RenderWidget::OnWasRestored(bool needs_repainting) {
didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
}
-void RenderWidget::OnPaintRectAck() {
- DCHECK(paint_reply_pending());
- paint_reply_pending_ = false;
- // If we sent a PaintRect message with a zero-sized bitmap, then
- // we should have no current paint buf.
+void RenderWidget::OnRequestMoveAck() {
+ DCHECK(pending_window_rect_count_);
+ pending_window_rect_count_--;
+}
+
+void RenderWidget::OnUpdateRectAck() {
+ DCHECK(update_reply_pending());
+ update_reply_pending_ = false;
+
+ // If we sent an UpdateRect message with a zero-sized bitmap, then we should
+ // have no current update buf.
if (current_paint_buf_) {
RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
current_paint_buf_ = NULL;
@@ -275,23 +275,6 @@ void RenderWidget::OnPaintRectAck() {
CallDoDeferredUpdate();
}
-void RenderWidget::OnRequestMoveAck() {
- DCHECK(pending_window_rect_count_);
- pending_window_rect_count_--;
-}
-
-void RenderWidget::OnScrollRectAck() {
- DCHECK(scroll_reply_pending());
-
- if (current_scroll_buf_) {
- RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
- current_scroll_buf_ = NULL;
- }
-
- // Continue scrolling if necessary...
- CallDoDeferredUpdate();
-}
-
void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
void* iter = NULL;
@@ -405,9 +388,17 @@ void RenderWidget::PaintDebugBorder(const gfx::Rect& rect,
if (!kPaintBorder)
return;
+ // Cycle through these colors to help distinguish new paint rects.
+ const SkColor colors[] = {
+ SkColorSetARGB(0x3F, 0xFF, 0, 0),
+ SkColorSetARGB(0x3F, 0xFF, 0, 0xFF),
+ SkColorSetARGB(0x3F, 0, 0, 0xFF),
+ };
+ static int color_selector = 0;
+
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SkColorSetARGB(0x3F, 0xFF, 0, 0));
+ paint.setColor(colors[color_selector++ % arraysize(colors)]);
paint.setStrokeWidth(1);
SkIRect irect;
@@ -426,7 +417,7 @@ void RenderWidget::CallDoDeferredUpdate() {
void RenderWidget::DoDeferredUpdate() {
if (!webwidget_ || !paint_aggregator_.HasPendingUpdate() ||
- paint_reply_pending() || scroll_reply_pending())
+ update_reply_pending())
return;
// Suppress updating when we are hidden.
@@ -444,86 +435,56 @@ void RenderWidget::DoDeferredUpdate() {
PaintAggregator::PendingUpdate update = paint_aggregator_.GetPendingUpdate();
paint_aggregator_.ClearPendingUpdate();
- if (!update.scroll_rect.IsEmpty()) {
- // Optmized scrolling
-
- // Compute the region we will expose by scrolling, and paint that into a
- // shared memory section.
- gfx::Rect damaged_rect = update.GetScrollDamage();
-
- scoped_ptr<skia::PlatformCanvas> canvas(
- RenderProcess::current()->GetDrawingCanvas(&current_scroll_buf_,
- damaged_rect));
- if (!canvas.get()) {
- NOTREACHED();
- return;
- }
+ gfx::Rect scroll_damage = update.GetScrollDamage();
+ gfx::Rect bounds = update.GetPaintBounds().Union(scroll_damage);
- // We may get back a smaller canvas than we asked for.
- damaged_rect.set_width(canvas->getDevice()->width());
- damaged_rect.set_height(canvas->getDevice()->height());
-
- // Set these parameters before calling Paint, since that could result in
- // further invalidates (uncommon).
- ViewHostMsg_ScrollRect_Params params;
- params.bitmap_rect = damaged_rect;
- params.dx = update.scroll_delta.x();
- params.dy = update.scroll_delta.y();
- params.clip_rect = update.scroll_rect;
- params.view_size = size_;
- params.plugin_window_moves = plugin_window_moves_;
- params.bitmap = current_scroll_buf_->id();
-
- plugin_window_moves_.clear();
-
- PaintRect(damaged_rect, damaged_rect.origin(), canvas.get());
- Send(new ViewHostMsg_ScrollRect(routing_id_, params));
+ // Compute a buffer for painting and cache it.
+ scoped_ptr<skia::PlatformCanvas> canvas(
+ RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_, bounds));
+ if (!canvas.get()) {
+ NOTREACHED();
+ return;
}
- if (!update.paint_rects.empty()) {
- // Normal painting
-
- gfx::Rect bounds = update.GetPaintBounds();
-
- // Compute a buffer for painting and cache it.
- scoped_ptr<skia::PlatformCanvas> canvas(
- RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
- bounds));
- if (!canvas.get()) {
- NOTREACHED();
- return;
- }
-
- // We may get back a smaller canvas than we asked for.
- bounds.set_width(canvas->getDevice()->width());
- bounds.set_height(canvas->getDevice()->height());
-
- HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
-
- // TODO(darin): Re-enable painting multiple damage rects once the
- // page-cycler regressions are resolved. See bug 29589.
- if (update.scroll_rect.IsEmpty()) {
- update.paint_rects.clear();
- update.paint_rects.push_back(bounds);
- }
-
- for (size_t i = 0; i < update.paint_rects.size(); ++i)
- PaintRect(update.paint_rects[i], bounds.origin(), canvas.get());
+ // We may get back a smaller canvas than we asked for.
+ // TODO(darin): This seems like it could cause painting problems!
+ DCHECK_EQ(bounds.width(), canvas->getDevice()->width());
+ DCHECK_EQ(bounds.height(), canvas->getDevice()->height());
+ bounds.set_width(canvas->getDevice()->width());
+ bounds.set_height(canvas->getDevice()->height());
+
+ HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
+
+ // The scroll damage is just another rectangle to paint and copy.
+ std::vector<gfx::Rect> copy_rects;
+ copy_rects.swap(update.paint_rects);
+ if (!scroll_damage.IsEmpty())
+ copy_rects.push_back(scroll_damage);
+
+ // TODO(darin): Re-enable painting multiple damage rects once the
+ // page-cycler regressions are resolved. See bug 29589.
+ if (update.scroll_rect.IsEmpty()) {
+ update.paint_rects.clear();
+ update.paint_rects.push_back(bounds);
+ }
- ViewHostMsg_PaintRect_Params params;
- params.bitmap_rect = bounds;
- params.update_rects = update.paint_rects; // TODO(darin): clip to bounds?
- params.view_size = size_;
- params.plugin_window_moves = plugin_window_moves_;
- params.flags = next_paint_flags_;
- params.bitmap = current_paint_buf_->id();
+ for (size_t i = 0; i < copy_rects.size(); ++i)
+ PaintRect(copy_rects[i], bounds.origin(), canvas.get());
- plugin_window_moves_.clear();
+ ViewHostMsg_UpdateRect_Params params;
+ params.bitmap = current_paint_buf_->id();
+ params.bitmap_rect = bounds;
+ params.dx = update.scroll_delta.x();
+ params.dy = update.scroll_delta.y();
+ params.scroll_rect = update.scroll_rect;
+ params.copy_rects.swap(copy_rects); // TODO(darin): clip to bounds?
+ params.view_size = size_;
+ params.plugin_window_moves.swap(plugin_window_moves_);
+ params.flags = next_paint_flags_;
- paint_reply_pending_ = true;
- Send(new ViewHostMsg_PaintRect(routing_id_, params));
- next_paint_flags_ = 0;
- }
+ update_reply_pending_ = true;
+ Send(new ViewHostMsg_UpdateRect(routing_id_, params));
+ next_paint_flags_ = 0;
UpdateIME();
}
@@ -548,7 +509,7 @@ void RenderWidget::didInvalidateRect(const WebRect& rect) {
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (paint_reply_pending() || scroll_reply_pending())
+ if (update_reply_pending())
return;
// Perform updating asynchronously. This serves two purposes:
@@ -577,7 +538,7 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (paint_reply_pending() || scroll_reply_pending())
+ if (update_reply_pending())
return;
// Perform updating asynchronously. This serves two purposes:
@@ -773,23 +734,23 @@ void RenderWidget::SetBackground(const SkBitmap& background) {
}
bool RenderWidget::next_paint_is_resize_ack() const {
- return ViewHostMsg_PaintRect_Flags::is_resize_ack(next_paint_flags_);
+ return ViewHostMsg_UpdateRect_Flags::is_resize_ack(next_paint_flags_);
}
bool RenderWidget::next_paint_is_restore_ack() const {
- return ViewHostMsg_PaintRect_Flags::is_restore_ack(next_paint_flags_);
+ return ViewHostMsg_UpdateRect_Flags::is_restore_ack(next_paint_flags_);
}
void RenderWidget::set_next_paint_is_resize_ack() {
- next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK;
+ next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
}
void RenderWidget::set_next_paint_is_restore_ack() {
- next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESTORE_ACK;
+ next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK;
}
void RenderWidget::set_next_paint_is_repaint_ack() {
- next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK;
+ next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
}
void RenderWidget::UpdateIME() {
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index c25c99a..4cf033e 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -142,8 +142,7 @@ class RenderWidget : public IPC::Channel::Listener,
const gfx::Rect& resizer_rect);
void OnWasHidden();
void OnWasRestored(bool needs_repainting);
- void OnPaintRectAck();
- void OnScrollRectAck();
+ void OnUpdateRectAck();
void OnRequestMoveAck();
void OnHandleInputEvent(const IPC::Message& message);
void OnMouseCaptureLost();
@@ -167,14 +166,9 @@ class RenderWidget : public IPC::Channel::Listener,
bool is_hidden() const { return is_hidden_; }
- // True if a PaintRect_ACK message is pending.
- bool paint_reply_pending() const {
- return paint_reply_pending_;
- }
-
- // True if a ScrollRect_ACK message is pending.
- bool scroll_reply_pending() const {
- return current_scroll_buf_ != NULL;
+ // True if an UpdateRect_ACK message is pending.
+ bool update_reply_pending() const {
+ return update_reply_pending_;
}
bool next_paint_is_resize_ack() const;
@@ -238,22 +232,20 @@ class RenderWidget : public IPC::Channel::Listener,
// The size of the RenderWidget.
gfx::Size size_;
- // Transport DIBs that are currently in use to transfer an image to the
- // browser.
+ // The TransportDIB that is being used to transfer an image to the browser.
TransportDIB* current_paint_buf_;
- TransportDIB* current_scroll_buf_;
PaintAggregator paint_aggregator_;
// The area that must be reserved for drawing the resize corner.
gfx::Rect resizer_rect_;
- // Flags for the next ViewHostMsg_PaintRect message.
+ // Flags for the next ViewHostMsg_UpdateRect message.
int next_paint_flags_;
- // True if we are expecting a PaintRect_ACK message (i.e., that a PaintRect
- // message has been sent).
- bool paint_reply_pending_;
+ // True if we are expecting an UpdateRect_ACK message (i.e., that a
+ // UpdateRect message has been sent).
+ bool update_reply_pending_;
// Set to true if we should ignore RenderWidget::Show calls.
bool did_show_;