summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host/render_widget_host.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-23 23:14:11 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-23 23:14:11 +0000
commitbcfc90e8a909bbc199f4d80143f5eb24abda1544 (patch)
tree2ea9ba7885047e901fe55f2c4938c46633e0ee09 /chrome/browser/renderer_host/render_widget_host.cc
parent2a5af8a6e448b72044353b691ab7766e989db152 (diff)
downloadchromium_src-bcfc90e8a909bbc199f4d80143f5eb24abda1544.zip
chromium_src-bcfc90e8a909bbc199f4d80143f5eb24abda1544.tar.gz
chromium_src-bcfc90e8a909bbc199f4d80143f5eb24abda1544.tar.bz2
Separate out the backing store from the RenderWidgetHost into its own file to
make porting easier. I also did some cleanup in the scrolling and painting areas, collapsing the confusing ScrollRect call inside OnMsgScrollRect to just be inside the function and call a new function on the backing store to scroll it. Same for painting. This also moves plugin window moving to the view. Review URL: http://codereview.chromium.org/18702 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8594 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host/render_widget_host.cc')
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc356
1 files changed, 47 insertions, 309 deletions
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index 354f54b..63dd0f3 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -7,10 +7,10 @@
#include "base/gfx/gdi_util.h"
#include "base/message_loop.h"
#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/browser/renderer_host/backing_store.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_helper.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/common/mru_cache.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/win_util.h"
#include "chrome/views/view.h"
@@ -31,241 +31,6 @@ static const int kPaintMsgTimeoutMS = 40;
static const int kHungRendererDelayMs = 20000;
///////////////////////////////////////////////////////////////////////////////
-// RenderWidget::BackingStore
-
-RenderWidgetHost::BackingStore::BackingStore(const gfx::Size& size)
- : size_(size),
- backing_store_dib_(NULL),
- original_bitmap_(NULL) {
- HDC screen_dc = ::GetDC(NULL);
- hdc_ = CreateCompatibleDC(screen_dc);
- ReleaseDC(NULL, screen_dc);
-}
-
-RenderWidgetHost::BackingStore::~BackingStore() {
- DCHECK(hdc_);
-
- DeleteDC(hdc_);
-
- if (backing_store_dib_) {
- DeleteObject(backing_store_dib_);
- backing_store_dib_ = NULL;
- }
-}
-
-bool RenderWidgetHost::BackingStore::Refresh(HANDLE process,
- HANDLE bitmap_section,
- const gfx::Rect& bitmap_rect) {
- // The bitmap received is valid only in the renderer process.
- HANDLE valid_bitmap =
- win_util::GetSectionFromProcess(bitmap_section, process, false);
- if (!valid_bitmap)
- return false;
-
- if (!backing_store_dib_) {
- backing_store_dib_ = CreateDIB(hdc_, size_.width(), size_.height(), true,
- NULL);
- DCHECK(backing_store_dib_ != NULL);
- original_bitmap_ = SelectObject(hdc_, backing_store_dib_);
- }
-
- // TODO(darin): protect against integer overflow
- DWORD size = 4 * bitmap_rect.width() * bitmap_rect.height();
- void* backing_store_data = MapViewOfFile(valid_bitmap, FILE_MAP_READ, 0, 0,
- size);
- // These values are shared with gfx::PlatformDevice
- BITMAPINFOHEADER hdr;
- gfx::CreateBitmapHeader(bitmap_rect.width(), bitmap_rect.height(), &hdr);
- // Account for a bitmap_rect that exceeds the bounds of our view
- gfx::Rect view_rect(0, 0, size_.width(), size_.height());
- gfx::Rect paint_rect = view_rect.Intersect(bitmap_rect);
-
- StretchDIBits(hdc_,
- paint_rect.x(),
- paint_rect.y(),
- paint_rect.width(),
- paint_rect.height(),
- 0, 0, // source x,y
- paint_rect.width(),
- paint_rect.height(),
- backing_store_data,
- reinterpret_cast<BITMAPINFO*>(&hdr),
- DIB_RGB_COLORS,
- SRCCOPY);
-
- UnmapViewOfFile(backing_store_data);
- CloseHandle(valid_bitmap);
- return true;
-}
-
-HANDLE RenderWidgetHost::BackingStore::CreateDIB(HDC dc, int width, int height,
- bool use_system_color_depth,
- HANDLE section) {
- BITMAPINFOHEADER hdr;
-
- if (use_system_color_depth) {
- HDC screen_dc = ::GetDC(NULL);
- int color_depth = GetDeviceCaps(screen_dc, BITSPIXEL);
- ::ReleaseDC(NULL, screen_dc);
-
- // Color depths less than 16 bpp require a palette to be specified in the
- // BITMAPINFO structure passed to CreateDIBSection. Instead of creating
- // the palette, we specify the desired color depth as 16 which allows the
- // OS to come up with an approximation. Tested this with 8bpp.
- if (color_depth < 16)
- color_depth = 16;
-
- gfx::CreateBitmapHeaderWithColorDepth(width, height, color_depth, &hdr);
- } else {
- gfx::CreateBitmapHeader(width, height, &hdr);
- }
- void* data = NULL;
- HANDLE dib =
- CreateDIBSection(hdc_, reinterpret_cast<BITMAPINFO*>(&hdr),
- 0, &data, section, 0);
- return dib;
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// RenderWidgetHost::BackingStoreManager
-
-// This class manages backing stores in the browsr. Every RenderWidgetHost
-// is associated with a backing store which it requests from this class.
-// The hosts don't maintain any references to the backing stores.
-// These backing stores are maintained in a cache which can be trimmed as
-// needed.
-class RenderWidgetHost::BackingStoreManager {
- public:
- // Returns a backing store which matches the desired dimensions.
- // Parameters:
- // host
- // A pointer to the RenderWidgetHost.
- // backing_store_rect
- // The desired backing store dimensions.
- // Returns a pointer to the backing store on success, NULL on failure.
- static BackingStore* GetBackingStore(RenderWidgetHost* host,
- const gfx::Size& desired_size) {
- BackingStore* backing_store = Lookup(host);
- if (backing_store) {
- // If we already have a backing store, then make sure it is the correct
- // size.
- if (backing_store->size() == desired_size)
- return backing_store;
- backing_store = NULL;
- }
-
- return backing_store;
- }
-
- // Returns a backing store which is fully ready for consumption,
- // i.e. the bitmap from the renderer has been copied into the
- // backing store dc, or the bitmap in the backing store dc references
- // the renderer bitmap.
- // Parameters:
- // host
- // A pointer to the RenderWidgetHost.
- // backing_store_rect
- // The desired backing store dimensions.
- // process_handle
- // The renderer process handle.
- // bitmap_section
- // The bitmap section from the renderer.
- // bitmap_rect
- // The rect to be painted into the backing store
- // needs_full_paint
- // Set if we need to send out a request to paint the view
- // to the renderer.
- static BackingStore* PrepareBackingStore(RenderWidgetHost* host,
- const gfx::Rect& backing_store_rect,
- HANDLE process_handle,
- HANDLE bitmap_section,
- const gfx::Rect& bitmap_rect,
- bool* needs_full_paint) {
- BackingStore* backing_store = GetBackingStore(host,
- backing_store_rect.size());
- if (!backing_store) {
- // We need to get Webkit to generate a new paint here, as we
- // don't have a previous snapshot.
- if (bitmap_rect != backing_store_rect) {
- DCHECK(needs_full_paint != NULL);
- *needs_full_paint = true;
- }
- backing_store = CreateBackingStore(host, backing_store_rect);
- }
-
- DCHECK(backing_store != NULL);
- backing_store->Refresh(process_handle, bitmap_section, bitmap_rect);
- return backing_store;
- }
-
- // Returns a matching backing store for the host.
- // Returns NULL if we fail to find one.
- static BackingStore* Lookup(RenderWidgetHost* host) {
- if (cache_) {
- BackingStoreCache::iterator it = cache_->Peek(host);
- if (it != cache_->end())
- return it->second;
- }
- return NULL;
- }
-
- // Removes the backing store for the host.
- static void RemoveBackingStore(RenderWidgetHost* host) {
- if (!cache_)
- return;
-
- BackingStoreCache::iterator it = cache_->Peek(host);
- if (it == cache_->end())
- return;
-
- cache_->Erase(it);
-
- if (cache_->empty()) {
- delete cache_;
- cache_ = NULL;
- }
- }
-
- private:
- // Not intended for instantiation.
- ~BackingStoreManager();
-
- typedef OwningMRUCache<RenderWidgetHost*, BackingStore*> BackingStoreCache;
- static BackingStoreCache* cache_;
-
- // Returns the size of the backing store cache.
- // TODO(iyengar) Make this dynamic, i.e. based on the available resources
- // on the machine.
- static int GetBackingStoreCacheSize() {
- const int kMaxSize = 5;
- return kMaxSize;
- }
-
- // Creates the backing store for the host based on the dimensions passed in.
- // Removes the existing backing store if there is one.
- static BackingStore* CreateBackingStore(
- RenderWidgetHost* host, const gfx::Rect& backing_store_rect) {
- RemoveBackingStore(host);
-
- BackingStore* backing_store = new BackingStore(backing_store_rect.size());
- int backing_store_cache_size = GetBackingStoreCacheSize();
- if (backing_store_cache_size > 0) {
- if (!cache_)
- cache_ = new BackingStoreCache(backing_store_cache_size);
- cache_->Put(host, backing_store);
- }
- return backing_store;
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(BackingStoreManager);
-};
-
-RenderWidgetHost::BackingStoreManager::BackingStoreCache*
- RenderWidgetHost::BackingStoreManager::cache_ = NULL;
-
-
-///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHost
RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process,
@@ -375,17 +140,27 @@ void RenderWidgetHost::OnMsgPaintRect(
DCHECK(!params.bitmap_rect.IsEmpty());
DCHECK(!params.view_size.IsEmpty());
- PaintRect(params.bitmap, params.bitmap_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(params.bitmap, params.bitmap_rect, params.view_size);
// 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.
Send(new ViewMsg_PaintRect_ACK(routing_id_));
- // TODO(darin): This should really be done by the view_!
- MovePluginWindows(params.plugin_window_moves);
+ // 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;
- // The view might be destroyed already. Check for this case.
+ // Now paint the view. Watch out: it might be destroyed already.
if (view_ && !suppress_view_updating_) {
view_being_painted_ = true;
+ view_->MovePluginWindows(params.plugin_window_moves);
view_->DidPaintRect(params.bitmap_rect);
view_being_painted_ = false;
}
@@ -413,18 +188,27 @@ void RenderWidgetHost::OnMsgScrollRect(
DCHECK(!params.view_size.IsEmpty());
- ScrollRect(params.bitmap, params.bitmap_rect, params.dx, params.dy,
- params.clip_rect, params.view_size);
+ // Scroll the backing store.
+ ScrollBackingStoreRect(params.bitmap, 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_));
- // TODO(darin): This should really be done by the view_!
- MovePluginWindows(params.plugin_window_moves);
+ // 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;
- // The view might be destroyed already. Check for this case
+ // 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;
}
@@ -434,53 +218,6 @@ void RenderWidgetHost::OnMsgScrollRect(
UMA_HISTOGRAM_TIMES(L"MPArch.RWH_OnMsgScrollRect", delta);
}
-void RenderWidgetHost::MovePluginWindows(
- const std::vector<WebPluginGeometry>& plugin_window_moves) {
- if (plugin_window_moves.empty())
- return;
-
- HDWP defer_window_pos_info =
- ::BeginDeferWindowPos(static_cast<int>(plugin_window_moves.size()));
-
- if (!defer_window_pos_info) {
- NOTREACHED();
- return;
- }
-
- for (size_t i = 0; i < plugin_window_moves.size(); ++i) {
- unsigned long flags = 0;
- const WebPluginGeometry& move = plugin_window_moves[i];
-
- if (move.visible)
- flags |= SWP_SHOWWINDOW;
- else
- flags |= SWP_HIDEWINDOW;
-
- HRGN hrgn = ::CreateRectRgn(move.clip_rect.x(),
- move.clip_rect.y(),
- move.clip_rect.right(),
- move.clip_rect.bottom());
- gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
-
- // Note: System will own the hrgn after we call SetWindowRgn,
- // so we don't need to call DeleteObject(hrgn)
- ::SetWindowRgn(move.window, hrgn, !move.clip_rect.IsEmpty());
-
- defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
- move.window, NULL,
- move.window_rect.x(),
- move.window_rect.y(),
- move.window_rect.width(),
- move.window_rect.height(), flags);
- if (!defer_window_pos_info) {
- DCHECK(false) << "DeferWindowPos given invalid window, so rest ignored.";
- return;
- }
- }
-
- ::EndDeferWindowPos(defer_window_pos_info);
-}
-
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
// Log the time delta for processing an input event.
TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
@@ -726,7 +463,7 @@ void RenderWidgetHost::SetIsLoading(bool is_loading) {
view_->SetIsLoading(is_loading);
}
-RenderWidgetHost::BackingStore* RenderWidgetHost::GetBackingStore() {
+BackingStore* RenderWidgetHost::GetBackingStore() {
// We should not be asked to paint while we are hidden. If we are hidden,
// then it means that our consumer failed to call WasRestored.
DCHECK(!is_hidden_) << "GetBackingStore called while hidden!";
@@ -761,9 +498,13 @@ RenderWidgetHost::BackingStore* RenderWidgetHost::GetBackingStore() {
return backing_store;
}
-void RenderWidgetHost::PaintRect(HANDLE bitmap, const gfx::Rect& bitmap_rect,
- const gfx::Size& view_size) {
+void RenderWidgetHost::PaintBackingStoreRect(HANDLE bitmap,
+ const gfx::Rect& bitmap_rect,
+ const gfx::Size& view_size) {
if (is_hidden_) {
+ // Don't bother updating the backing store when we're hidden. Just mark it
+ // as being totally invalid. This will cause a complete repaint when the
+ // view is restored.
needs_repainting_on_restore_ = true;
return;
}
@@ -786,10 +527,15 @@ void RenderWidgetHost::PaintRect(HANDLE bitmap, const gfx::Rect& bitmap_rect,
}
}
-void RenderWidgetHost::ScrollRect(HANDLE bitmap, const gfx::Rect& bitmap_rect,
- int dx, int dy, const gfx::Rect& clip_rect,
- const gfx::Size& view_size) {
+void RenderWidgetHost::ScrollBackingStoreRect(HANDLE bitmap,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
if (is_hidden_) {
+ // Don't bother updating the backing store when we're hidden. Just mark it
+ // as being totally invalid. This will cause a complete repaint when the
+ // view is restored.
needs_repainting_on_restore_ = true;
return;
}
@@ -800,19 +546,11 @@ void RenderWidgetHost::ScrollRect(HANDLE bitmap, const gfx::Rect& bitmap_rect,
BackingStore* backing_store = BackingStoreManager::Lookup(this);
if (!backing_store || (backing_store->size() != view_size))
return;
-
- RECT damaged_rect, r = clip_rect.ToRECT();
- ScrollDC(backing_store->dc(), dx, dy, NULL, &r, NULL, &damaged_rect);
-
- // 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);
-
- backing_store->Refresh(process_->process().handle(), bitmap, bitmap_rect);
+ backing_store->ScrollRect(process_->process().handle(), bitmap, bitmap_rect,
+ dx, dy, clip_rect, view_size);
}
+
void RenderWidgetHost::RestartHangMonitorTimeout() {
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs));
}