diff options
27 files changed, 380 insertions, 510 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..ba191fc 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); + 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 // 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_; + 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(¶ms); + ViewHostMsg_UpdateRect_Params params; + InitUpdateRectParams(¶ms); - ViewHostMsg_PaintRect message(render_widget_id, params); + ViewHostMsg_UpdateRect message(render_widget_id, params); *msg = message; return true; } @@ -251,9 +252,9 @@ TEST_F(RenderWidgetHostTest, Resize) { // Send out a paint that's not a resize ack. This should not clean the // resize ack pending flag. - ViewHostMsg_PaintRect_Params params; - process_->InitPaintRectParams(¶ms); - host_->OnMsgPaintRect(params); + ViewHostMsg_UpdateRect_Params params; + process_->InitUpdateRectParams(¶ms); + host_->OnMsgUpdateRect(params); EXPECT_TRUE(host_->resize_ack_pending_); EXPECT_EQ(original_size.size(), host_->in_flight_size_); @@ -271,9 +272,9 @@ TEST_F(RenderWidgetHostTest, Resize) { // 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)); @@ -398,42 +399,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 // 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 +443,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 @@ -456,13 +457,13 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) { // Send it a paint as from the renderer. process_->sink().ClearMessages(); - ViewHostMsg_PaintRect_Params params; - process_->InitPaintRectParams(¶ms); - host_->OnMsgPaintRect(params); + ViewHostMsg_UpdateRect_Params params; + process_->InitUpdateRectParams(¶ms); + 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 2bcccb2..c0cc742 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/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(¤t_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(¤t_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(¤t_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_; |