summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/surface/transport_dib.h4
-rw-r--r--chrome/browser/renderer_host/backing_store.h15
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.h3
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.mm4
-rw-r--r--chrome/browser/renderer_host/backing_store_manager.cc13
-rw-r--r--chrome/browser/renderer_host/backing_store_manager.h11
-rw-r--r--chrome/browser/renderer_host/backing_store_proxy.cc15
-rw-r--r--chrome/browser/renderer_host/backing_store_proxy.h9
-rw-r--r--chrome/browser/renderer_host/backing_store_win.cc7
-rw-r--r--chrome/browser/renderer_host/backing_store_win.h3
-rw-r--r--chrome/browser/renderer_host/backing_store_x.cc4
-rw-r--r--chrome/browser/renderer_host/backing_store_x.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc44
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h14
-rw-r--r--chrome/browser/renderer_host/test/test_backing_store.cc3
-rw-r--r--chrome/browser/renderer_host/test/test_backing_store.h3
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/renderer/render_widget.cc41
-rw-r--r--chrome/renderer/render_widget.h8
19 files changed, 148 insertions, 61 deletions
diff --git a/app/surface/transport_dib.h b/app/surface/transport_dib.h
index 6606c2b..2f439e6 100644
--- a/app/surface/transport_dib.h
+++ b/app/surface/transport_dib.h
@@ -63,6 +63,10 @@ class TransportDIB {
return other.sequence_num < sequence_num;
}
+ bool operator==(const HandleAndSequenceNum& other) const {
+ return !(*this < other) && !(other < *this);
+ }
+
HANDLE handle;
uint32 sequence_num;
};
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index 53d0288..3977c07 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -42,16 +42,21 @@ class BackingStore {
// the backingstore to be painted from the bitmap.
//
// The value placed into |*painted_synchronously| indicates if the paint was
- // completed synchronously and the TransportDIB can be freed. False means that
- // the backing store may still be using the transport DIB and it will manage
- // notifying the RenderWidgetHost that it's done with it via
- // DonePaintingToBackingStore().
+ // completed synchronously and the renderer can begin generating another
+ // update. If the paint is being done asynchronously, the backing store will
+ // call DonePaintingToBackingStore() when finished.
+ //
+ // |*done_copying_bitmap| is set to true if the browser is done using
+ // the TransportDIB and to false otherwise. In the false case, the backing
+ // store will manage notifying the RenderWidgetHost that it's done with it via
+ // DoneCopyingBitmapToBackingStore().
virtual void PaintToBackingStore(
RenderProcessHost* process,
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) = 0;
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) = 0;
// Extracts the gives subset of the backing store and copies it to the given
// PlatformCanvas. The PlatformCanvas should not be initialized. This function
diff --git a/chrome/browser/renderer_host/backing_store_mac.h b/chrome/browser/renderer_host/backing_store_mac.h
index 0c1e4a7..0c1df14 100644
--- a/chrome/browser/renderer_host/backing_store_mac.h
+++ b/chrome/browser/renderer_host/backing_store_mac.h
@@ -29,7 +29,8 @@ class BackingStoreMac : public BackingStore {
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
virtual bool CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformCanvas* output);
virtual void ScrollBackingStore(int dx, int dy,
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index f793395..d7156ea 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -56,10 +56,12 @@ void BackingStoreMac::PaintToBackingStore(
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
// Our paints are always synchronous and the caller can free the TransportDIB,
// even on failure.
*painted_synchronously = true;
+ *done_copying_bitmap = true;
DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
diff --git a/chrome/browser/renderer_host/backing_store_manager.cc b/chrome/browser/renderer_host/backing_store_manager.cc
index 4325f31..9b7cfa2 100644
--- a/chrome/browser/renderer_host/backing_store_manager.cc
+++ b/chrome/browser/renderer_host/backing_store_manager.cc
@@ -197,9 +197,11 @@ void BackingStoreManager::PrepareBackingStore(
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
bool* needs_full_paint,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
// Default to declaring we're done using the transport DIB so it can be freed.
*painted_synchronously = true;
+ *done_copying_bitmap = true;
BackingStore* backing_store = GetBackingStore(host, backing_store_size);
if (!backing_store) {
@@ -217,9 +219,12 @@ void BackingStoreManager::PrepareBackingStore(
backing_store = CreateBackingStore(host, backing_store_size);
}
- backing_store->PaintToBackingStore(host->process(), bitmap,
- bitmap_rect, copy_rects,
- painted_synchronously);
+ backing_store->PaintToBackingStore(host->process(),
+ bitmap,
+ bitmap_rect,
+ copy_rects,
+ painted_synchronously,
+ done_copying_bitmap);
}
// static
diff --git a/chrome/browser/renderer_host/backing_store_manager.h b/chrome/browser/renderer_host/backing_store_manager.h
index 1ab78cc..38f6574 100644
--- a/chrome/browser/renderer_host/backing_store_manager.h
+++ b/chrome/browser/renderer_host/backing_store_manager.h
@@ -44,10 +44,10 @@ class BackingStoreManager {
// Set if we need to send out a request to paint the view
// to the renderer.
// painted_synchronously
- // Will be set by the function if the request was processed synchronously,
- // and the bitmap is done being used. False means that the backing store
- // will paint the bitmap at a later time and that the TransportDIB can't be
- // freed (it will be the backing store's job to free it later).
+ // Will be set by the function if the request was processed synchronously.
+ // done_copying_bitmap
+ // False means that the backing store is still using the TransportDIB and it
+ // can't be freed (it will be the backing store's job to free it later).
static void PrepareBackingStore(
RenderWidgetHost* host,
const gfx::Size& backing_store_size,
@@ -55,7 +55,8 @@ class BackingStoreManager {
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
bool* needs_full_paint,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
// Returns a matching backing store for the host.
// Returns NULL if we fail to find one.
diff --git a/chrome/browser/renderer_host/backing_store_proxy.cc b/chrome/browser/renderer_host/backing_store_proxy.cc
index ba3538b..40c5636 100644
--- a/chrome/browser/renderer_host/backing_store_proxy.cc
+++ b/chrome/browser/renderer_host/backing_store_proxy.cc
@@ -23,7 +23,8 @@ BackingStoreProxy::BackingStoreProxy(RenderWidgetHost* widget,
: BackingStore(widget, size),
process_shim_(process_shim),
routing_id_(routing_id),
- waiting_for_paint_ack_(false) {
+ waiting_for_paint_ack_(false),
+ current_bitmap_(TransportDIB::Id()) {
process_shim_->AddRoute(routing_id_, this);
}
@@ -36,7 +37,8 @@ void BackingStoreProxy::PaintToBackingStore(
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
DCHECK(!waiting_for_paint_ack_);
base::ProcessId process_id;
@@ -49,12 +51,17 @@ void BackingStoreProxy::PaintToBackingStore(
if (process_shim_->Send(new GpuMsg_PaintToBackingStore(
routing_id_, process_id, bitmap, bitmap_rect, copy_rects))) {
// Message sent successfully, so the caller can not destroy the
- // TransportDIB. OnDonePaintingToBackingStore will free it later.
+ // TransportDIB. DoneCopyingBitmapToBackingStore will release it later, and
+ // DonePaintingToBackingStore will let the renderer know that it can send us
+ // the next update.
*painted_synchronously = false;
+ *done_copying_bitmap = false;
waiting_for_paint_ack_ = true;
+ current_bitmap_ = bitmap;
} else {
// On error, we're done with the TransportDIB and the caller can free it.
*painted_synchronously = true;
+ *done_copying_bitmap = true;
}
}
@@ -96,6 +103,8 @@ void BackingStoreProxy::OnChannelError() {
void BackingStoreProxy::OnPaintToBackingStoreACK() {
DCHECK(waiting_for_paint_ack_);
+ render_widget_host()->DoneCopyingBitmapToBackingStore(current_bitmap_);
render_widget_host()->DonePaintingToBackingStore();
waiting_for_paint_ack_ = false;
+ current_bitmap_ = TransportDIB::Id();
}
diff --git a/chrome/browser/renderer_host/backing_store_proxy.h b/chrome/browser/renderer_host/backing_store_proxy.h
index 610f7ef..0976b58 100644
--- a/chrome/browser/renderer_host/backing_store_proxy.h
+++ b/chrome/browser/renderer_host/backing_store_proxy.h
@@ -12,6 +12,7 @@
class GpuProcessHostUIShim;
+// This class proxies renderer updates to the GPU process.
class BackingStoreProxy : public BackingStore,
public IPC::Channel::Listener {
public:
@@ -24,7 +25,8 @@ class BackingStoreProxy : public BackingStore,
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
virtual bool CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformCanvas* output);
virtual void ScrollBackingStore(int dx, int dy,
@@ -45,9 +47,12 @@ class BackingStoreProxy : public BackingStore,
// Set to true when we're waiting for the GPU process to do a paint and send
// back a "done" message. In this case, the renderer will be waiting for our
- // message that we're done using the backing store.
+ // message that we're done using the bitmap.
bool waiting_for_paint_ack_;
+ // Bitmap currently being used by the GPU process.
+ TransportDIB::Id current_bitmap_;
+
DISALLOW_COPY_AND_ASSIGN(BackingStoreProxy);
};
diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc
index 94d9cbf..b13d652 100644
--- a/chrome/browser/renderer_host/backing_store_win.cc
+++ b/chrome/browser/renderer_host/backing_store_win.cc
@@ -69,7 +69,8 @@ void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h,
} // namespace
-BackingStoreWin::BackingStoreWin(RenderWidgetHost* widget, const gfx::Size& size)
+BackingStoreWin::BackingStoreWin(RenderWidgetHost* widget,
+ const gfx::Size& size)
: BackingStore(widget, size),
backing_store_dib_(NULL),
original_bitmap_(NULL) {
@@ -117,10 +118,12 @@ void BackingStoreWin::PaintToBackingStore(
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
// Our paints are always synchronous and the TransportDIB can be freed when
// we're done (even on error).
*painted_synchronously = true;
+ *done_copying_bitmap = true;
if (!backing_store_dib_) {
backing_store_dib_ = CreateDIB(hdc_, size().width(),
diff --git a/chrome/browser/renderer_host/backing_store_win.h b/chrome/browser/renderer_host/backing_store_win.h
index 221e0aa..4ea1480 100644
--- a/chrome/browser/renderer_host/backing_store_win.h
+++ b/chrome/browser/renderer_host/backing_store_win.h
@@ -27,7 +27,8 @@ class BackingStoreWin : public BackingStore {
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
virtual bool CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformCanvas* output);
virtual void ScrollBackingStore(int dx, int dy,
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
index f2704c8..a7750ae4 100644
--- a/chrome/browser/renderer_host/backing_store_x.cc
+++ b/chrome/browser/renderer_host/backing_store_x.cc
@@ -161,10 +161,12 @@ void BackingStoreX::PaintToBackingStore(
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
// Our paints are always synchronous and the caller can free the TransportDIB
// when we're done, even on error.
*painted_synchronously = true;
+ *done_copying_bitmap = true;
if (!display_)
return;
diff --git a/chrome/browser/renderer_host/backing_store_x.h b/chrome/browser/renderer_host/backing_store_x.h
index 283c19f..816d520 100644
--- a/chrome/browser/renderer_host/backing_store_x.h
+++ b/chrome/browser/renderer_host/backing_store_x.h
@@ -54,7 +54,8 @@ class BackingStoreX : public BackingStore {
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
virtual bool CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformCanvas* output);
virtual void ScrollBackingStore(int dx, int dy,
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 20aafd3..027528e0 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -370,6 +370,11 @@ BackingStore* RenderWidgetHost::AllocBackingStore(const gfx::Size& size) {
return view_->AllocBackingStore(size);
}
+void RenderWidgetHost::DoneCopyingBitmapToBackingStore(
+ TransportDIB::Id bitmap) {
+ Send(new ViewMsg_DoneUsingBitmap(routing_id(), bitmap));
+}
+
void RenderWidgetHost::DonePaintingToBackingStore() {
Send(new ViewMsg_UpdateRect_ACK(routing_id()));
}
@@ -792,6 +797,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
DCHECK(!params.view_size.IsEmpty());
bool painted_synchronously = true; // Default to sending a paint ACK below.
+ bool done_copying_bitmap = true;
if (!is_gpu_rendering_active_) {
const size_t size = params.bitmap_rect.height() *
params.bitmap_rect.width() * 4;
@@ -814,20 +820,25 @@ void RenderWidgetHost::OnMsgUpdateRect(
// 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(params.bitmap, params.bitmap_rect,
- params.copy_rects, params.view_size,
- &painted_synchronously);
+ PaintBackingStoreRect(params.bitmap,
+ params.bitmap_rect,
+ params.copy_rects,
+ params.view_size,
+ &painted_synchronously,
+ &done_copying_bitmap);
}
}
}
- // ACK early so we can prefetch the next PaintRect 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. If the backing
- // store is painting asynchronously, it will manage issuing this IPC.
+ // Tell the renderer that the bitmap can be re-used, so the bitmap may be
+ // invalid after this call. If the backing store is still using the bitmap, it
+ // will manage issuing this IPC.
+ if (done_copying_bitmap)
+ DoneCopyingBitmapToBackingStore(params.bitmap);
+
+ // ACK early so we can prefetch the next UpdateRect if there is a next one.
if (painted_synchronously)
- Send(new ViewMsg_UpdateRect_ACK(routing_id_));
+ DonePaintingToBackingStore();
// 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
@@ -1083,10 +1094,12 @@ void RenderWidgetHost::PaintBackingStoreRect(
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
const gfx::Size& view_size,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
// On failure, we need to be sure our caller knows we're done with the
// backing store.
*painted_synchronously = true;
+ *done_copying_bitmap = true;
// The view may be destroyed already.
if (!view_)
@@ -1101,9 +1114,14 @@ void RenderWidgetHost::PaintBackingStoreRect(
}
bool needs_full_paint = false;
- BackingStoreManager::PrepareBackingStore(this, view_size, bitmap, bitmap_rect,
- copy_rects, &needs_full_paint,
- painted_synchronously);
+ BackingStoreManager::PrepareBackingStore(this,
+ view_size,
+ bitmap,
+ bitmap_rect,
+ copy_rects,
+ &needs_full_paint,
+ painted_synchronously,
+ done_copying_bitmap);
if (needs_full_paint) {
repaint_start_time_ = TimeTicks::Now();
repaint_ack_pending_ = true;
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 0e5fa4a..91215d6 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -238,9 +238,14 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// (for example, if we don't currently have a RenderWidgetHostView.)
BackingStore* AllocBackingStore(const gfx::Size& size);
- // When a backing store does asynchronous painting, it will call this function
- // when it is done with the DIB. We will then forward a message to the
- // renderer to send another paint.
+ // When a backing store is copying a TransportDIB asynchronously, it calls
+ // this function when it is done using it. We then send a message to the
+ // renderer letting it know that the bitmap can be reused.
+ void DoneCopyingBitmapToBackingStore(TransportDIB::Id bitmap);
+
+ // When a backing store does asynchronous painting, it calls this function
+ // when it is done painting. We then send a message to the renderer to send
+ // another update.
void DonePaintingToBackingStore();
// GPU accelerated version of GetBackingStore function. This will
@@ -526,7 +531,8 @@ class RenderWidgetHost : public IPC::Channel::Listener,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
const gfx::Size& view_size,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
// 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
diff --git a/chrome/browser/renderer_host/test/test_backing_store.cc b/chrome/browser/renderer_host/test/test_backing_store.cc
index d90c7fd..8e2a9b8 100644
--- a/chrome/browser/renderer_host/test/test_backing_store.cc
+++ b/chrome/browser/renderer_host/test/test_backing_store.cc
@@ -17,7 +17,8 @@ void TestBackingStore::PaintToBackingStore(
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously) {
+ bool* painted_synchronously,
+ bool* done_copying_bitmap) {
}
bool TestBackingStore::CopyFromBackingStore(const gfx::Rect& rect,
diff --git a/chrome/browser/renderer_host/test/test_backing_store.h b/chrome/browser/renderer_host/test/test_backing_store.h
index f9db76e..ee5ffce 100644
--- a/chrome/browser/renderer_host/test/test_backing_store.h
+++ b/chrome/browser/renderer_host/test/test_backing_store.h
@@ -19,7 +19,8 @@ class TestBackingStore : public BackingStore {
TransportDIB::Id bitmap,
const gfx::Rect& bitmap_rect,
const std::vector<gfx::Rect>& copy_rects,
- bool* painted_synchronously);
+ bool* painted_synchronously,
+ bool* done_copying_bitmap);
virtual bool CopyFromBackingStore(const gfx::Rect& rect,
skia::PlatformCanvas* output);
virtual void ScrollBackingStore(int dx, int dy,
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 13a475c..a35d911 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -177,6 +177,11 @@ IPC_BEGIN_MESSAGES(View)
gfx::Size /* page_size */,
gfx::Size /* desired_size */)
+ // Sent when the backing store is finished using a TransportDIB received from
+ // the renderer via a ViewHostMsg_UpdateRect message.
+ IPC_MESSAGE_ROUTED1(ViewMsg_DoneUsingBitmap,
+ TransportDIB::Id /* bitmap */)
+
// 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)
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index f5a7ebe..3293589 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -4,6 +4,8 @@
#include "chrome/renderer/render_widget.h"
+#include <utility>
+
#include "app/surface/transport_dib.h"
#include "base/command_line.h"
#include "base/logging.h"
@@ -61,7 +63,6 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread,
opener_id_(MSG_ROUTING_NONE),
render_thread_(render_thread),
host_window_(0),
- current_paint_buf_(NULL),
next_paint_flags_(0),
update_reply_pending_(false),
did_show_(false),
@@ -82,9 +83,9 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread,
RenderWidget::~RenderWidget() {
DCHECK(!webwidget_) << "Leaking our WebWidget!";
- if (current_paint_buf_) {
- RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
- current_paint_buf_ = NULL;
+ for (TransportDIBMap::iterator it = current_paint_bufs_.begin();
+ it != current_paint_bufs_.end(); ++it) {
+ RenderProcess::current()->ReleaseTransportDIB(it->second);
}
RenderProcess::current()->ReleaseProcess();
}
@@ -169,6 +170,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_DoneUsingBitmap, OnDoneUsingBitmap)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
IPC_MESSAGE_HANDLER(ViewMsg_CreateVideo_ACK, OnCreateVideoAck)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateVideo_ACK, OnUpdateVideoAck)
@@ -299,17 +301,27 @@ void RenderWidget::OnRequestMoveAck() {
pending_window_rect_count_--;
}
+void RenderWidget::OnDoneUsingBitmap(TransportDIB::Id id) {
+ // If we sent an UpdateRect message with a zero-sized bitmap, then we should
+ // get an empty bitmap in response.
+ // TODO(derat): Don't send the "done using bitmap" message at all in this
+ // case.
+ if (id == TransportDIB::Id())
+ return;
+
+ TransportDIBMap::iterator it = current_paint_bufs_.find(id);
+ if (it != current_paint_bufs_.end()) {
+ RenderProcess::current()->ReleaseTransportDIB(it->second);
+ current_paint_bufs_.erase(it);
+ return;
+ }
+ NOTREACHED() << "Browser returned unexpected TransportDIB to renderer";
+}
+
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 paint buffer.
- if (current_paint_buf_) {
- RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
- current_paint_buf_ = NULL;
- }
-
// Notify subclasses.
DidFlushPaint();
@@ -515,18 +527,19 @@ void RenderWidget::DoDeferredUpdate() {
!is_gpu_rendering_active_ &&
GetBitmapForOptimizedPluginPaint(bounds, &dib, &optimized_copy_location,
&optimized_copy_rect)) {
+ current_paint_bufs_.insert(std::make_pair(dib->id(), dib));
bounds = optimized_copy_location;
copy_rects.push_back(optimized_copy_rect);
dib_id = dib->id();
} else if (!is_gpu_rendering_active_) {
// Compute a buffer for painting and cache it.
scoped_ptr<skia::PlatformCanvas> canvas(
- RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
- bounds));
+ RenderProcess::current()->GetDrawingCanvas(&dib, bounds));
if (!canvas.get()) {
NOTREACHED();
return;
}
+ current_paint_bufs_.insert(std::make_pair(dib->id(), dib));
// We may get back a smaller canvas than we asked for.
// TODO(darin): This seems like it could cause painting problems!
@@ -552,7 +565,7 @@ void RenderWidget::DoDeferredUpdate() {
for (size_t i = 0; i < copy_rects.size(); ++i)
PaintRect(copy_rects[i], bounds.origin(), canvas.get());
- dib_id = current_paint_buf_->id();
+ dib_id = dib->id();
} else { // Accelerated compositing path
// Begin painting.
bool finish = next_paint_is_resize_ack();
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 47bdf38..8aede6c 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -6,6 +6,7 @@
#define CHROME_RENDERER_RENDER_WIDGET_H_
#pragma once
+#include <map>
#include <vector>
#include "app/surface/transport_dib.h"
@@ -129,6 +130,8 @@ class RenderWidget : public IPC::Channel::Listener,
// without ref-counting is an error.
friend class base::RefCounted<RenderWidget>;
+ typedef std::map<TransportDIB::Id, TransportDIB*> TransportDIBMap;
+
RenderWidget(RenderThreadBase* render_thread,
WebKit::WebPopupType popup_type);
virtual ~RenderWidget();
@@ -171,6 +174,7 @@ class RenderWidget : public IPC::Channel::Listener,
const gfx::Rect& resizer_rect);
virtual void OnWasHidden();
virtual void OnWasRestored(bool needs_repainting);
+ void OnDoneUsingBitmap(TransportDIB::Id id);
void OnUpdateRectAck();
void OnCreateVideoAck(int32 video_id);
void OnUpdateVideoAck(int32 video_id);
@@ -288,8 +292,8 @@ class RenderWidget : public IPC::Channel::Listener,
// The size of the RenderWidget.
gfx::Size size_;
- // The TransportDIB that is being used to transfer an image to the browser.
- TransportDIB* current_paint_buf_;
+ // TransportDIBs currently being used to transfer images to the browser.
+ TransportDIBMap current_paint_bufs_;
PaintAggregator paint_aggregator_;