diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-23 23:14:11 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-23 23:14:11 +0000 |
commit | bcfc90e8a909bbc199f4d80143f5eb24abda1544 (patch) | |
tree | 2ea9ba7885047e901fe55f2c4938c46633e0ee09 | |
parent | 2a5af8a6e448b72044353b691ab7766e989db152 (diff) | |
download | chromium_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
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/renderer_host/backing_store.cc | 243 | ||||
-rw-r--r-- | chrome/browser/renderer_host/backing_store.h | 130 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.cc | 356 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host.h | 66 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view.h | 10 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_win.cc | 56 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_win.h | 2 |
8 files changed, 505 insertions, 366 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 6995730..efb1ee4 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -1946,6 +1946,14 @@ > </File> <File + RelativePath=".\renderer_host\backing_store.cc" + > + </File> + <File + RelativePath=".\renderer_host\backing_store.h" + > + </File> + <File RelativePath=".\renderer_host\browser_render_process_host.cc" > </File> diff --git a/chrome/browser/renderer_host/backing_store.cc b/chrome/browser/renderer_host/backing_store.cc new file mode 100644 index 0000000..c12d0bd --- /dev/null +++ b/chrome/browser/renderer_host/backing_store.cc @@ -0,0 +1,243 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/backing_store.h"
+
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/common/win_util.h"
+
+#if defined(OS_WIN)
+#include "base/gfx/gdi_util.h"
+#endif
+
+namespace {
+
+typedef OwningMRUCache<RenderWidgetHost*, BackingStore*> BackingStoreCache;
+static BackingStoreCache* cache = NULL;
+
+// 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.
+BackingStore* CreateBackingStore(RenderWidgetHost* host,
+ const gfx::Rect& backing_store_rect) {
+ BackingStoreManager::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;
+}
+
+} // namespace
+
+#if defined(OS_WIN)
+
+// BackingStore (Windows) ------------------------------------------------------
+
+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);
+}
+
+BackingStore::~BackingStore() {
+ DCHECK(hdc_);
+
+ DeleteDC(hdc_);
+
+ if (backing_store_dib_) {
+ DeleteObject(backing_store_dib_);
+ backing_store_dib_ = NULL;
+ }
+}
+
+bool BackingStore::PaintRect(base::ProcessHandle 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;
+}
+
+void BackingStore::ScrollRect(base::ProcessHandle process,
+ HANDLE bitmap, const gfx::Rect& bitmap_rect,
+ int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size) {
+ RECT damaged_rect, r = clip_rect.ToRECT();
+ ScrollDC(hdc_, 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);
+
+ PaintRect(process, bitmap, bitmap_rect);
+}
+
+HANDLE 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;
+}
+
+#elif defined(OS_LINUX)
+
+// BackingStore (Linux) --------------------------------------------------------
+
+
+
+#elif defined(OS_MAC)
+
+// BackingStore (Mac) ----------------------------------------------------------
+
+
+
+#endif
+
+// BackingStoreManager ---------------------------------------------------------
+
+// static
+BackingStore* BackingStoreManager::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;
+}
+
+// static
+BackingStore* BackingStoreManager::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->PaintRect(process_handle, bitmap_section, bitmap_rect);
+ return backing_store;
+}
+
+// static
+BackingStore* BackingStoreManager::Lookup(RenderWidgetHost* host) {
+ if (cache) {
+ BackingStoreCache::iterator it = cache->Peek(host);
+ if (it != cache->end())
+ return it->second;
+ }
+ return NULL;
+}
+
+// static
+void BackingStoreManager::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;
+ }
+}
+
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h new file mode 100644 index 0000000..07ed517 --- /dev/null +++ b/chrome/browser/renderer_host/backing_store.h @@ -0,0 +1,130 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_H_
+#define CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_H_
+
+#include "base/basictypes.h"
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "base/process.h"
+#include "build/build_config.h"
+#include "chrome/common/mru_cache.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+class RenderWidgetHost;
+
+// BackingStore ----------------------------------------------------------------
+
+// Represents a backing store for the pixels in a RenderWidgetHost.
+class BackingStore {
+ public:
+ BackingStore(const gfx::Size& size);
+ ~BackingStore();
+
+ const gfx::Size& size() { return size_; }
+
+#if defined(OS_WIN)
+ HDC hdc() { return hdc_; }
+#endif
+
+ // Paints the bitmap from the renderer onto the backing store.
+ // TODO(port): The HANDLE is a shared section on Windows. Abstract this.
+ bool PaintRect(base::ProcessHandle process,
+ HANDLE bitmap_section,
+ const gfx::Rect& bitmap_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.
+ // TODO(port): The HANDLE is a shared section on Windows. Abstract this.
+ void ScrollRect(base::ProcessHandle process,
+ HANDLE bitmap, const gfx::Rect& bitmap_rect,
+ int dx, int dy,
+ const gfx::Rect& clip_rect,
+ const gfx::Size& view_size);
+
+ private:
+ // The size of the backing store.
+ gfx::Size size_;
+
+#if defined(OS_WIN)
+ // Creates a dib conforming to the height/width/section parameters passed
+ // in. The use_os_color_depth parameter controls whether we use the color
+ // depth to create an appropriate dib or not.
+ HANDLE CreateDIB(HDC dc,
+ int width, int height,
+ bool use_os_color_depth,
+ HANDLE section);
+
+ // The backing store dc.
+ HDC hdc_;
+
+ // Handle to the backing store dib.
+ HANDLE backing_store_dib_;
+
+ // Handle to the original bitmap in the dc.
+ HANDLE original_bitmap_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStore);
+};
+
+// 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 BackingStoreManager {
+ public:
+ // Returns a backing store which matches the desired dimensions.
+ //
+ // 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);
+
+ // 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.
+ //
+ // 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.
+ // TODO(port): The HANDLE is a shared section on Windows. Abstract this.
+ static BackingStore* PrepareBackingStore(RenderWidgetHost* host,
+ const gfx::Rect& backing_store_rect,
+ base::ProcessHandle process_handle,
+ HANDLE bitmap_section,
+ const gfx::Rect& bitmap_rect,
+ bool* needs_full_paint);
+
+ // Returns a matching backing store for the host.
+ // Returns NULL if we fail to find one.
+ static BackingStore* Lookup(RenderWidgetHost* host);
+
+ // Removes the backing store for the host.
+ static void RemoveBackingStore(RenderWidgetHost* host);
+
+ private:
+ // Not intended for instantiation.
+ BackingStoreManager() {}
+
+ DISALLOW_COPY_AND_ASSIGN(BackingStoreManager);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BACKING_STORE_H_
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)); } diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index d683e84..5992b69 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -157,13 +157,6 @@ class RenderWidgetHost : public IPC::Channel::Listener { // Indicates if the page has finished loading. virtual void SetIsLoading(bool is_loading); - // Represents a device-dependent drawing surface used to hold the rendering - // of a RenderWidgetHost. - class BackingStore; - - // Manages a set of backing stores. - class BackingStoreManager; - // Get access to the widget's backing store. If a resize is in progress, // then the current size of the backing store may be less than the size of // the widget's view. This method returns NULL if the backing store could @@ -226,9 +219,6 @@ class RenderWidgetHost : public IPC::Channel::Listener { void OnMsgImeUpdateStatus(ViewHostMsg_ImeControl control, const gfx::Rect& caret_rect); - void MovePluginWindows( - const std::vector<WebPluginGeometry>& plugin_window_moves); - // TODO(beng): (Cleanup) remove this friendship once we expose a clean API to // RenderWidgetHost Views. This exists only to give RenderWidgetHostView // access to Forward*Event. @@ -239,14 +229,6 @@ class RenderWidgetHost : public IPC::Channel::Listener { void ForwardWheelEvent(const WebMouseWheelEvent& wheel_event); void ForwardInputEvent(const WebInputEvent& input_event, int event_size); - // Called to paint a region of the backing store - void PaintRect(HANDLE bitmap, const gfx::Rect& bitmap_rect, - const gfx::Size& view_size); - - // Called to scroll a region of the backing store - void ScrollRect(HANDLE bitmap, const gfx::Rect& bitmap_rect, int dx, int dy, - const gfx::Rect& clip_rect, const gfx::Size& view_size); - // Tell this object to destroy itself. void Destroy(); @@ -324,38 +306,22 @@ class RenderWidgetHost : public IPC::Channel::Listener { // operation to finish. base::TimeTicks repaint_start_time_; - DISALLOW_EVIL_CONSTRUCTORS(RenderWidgetHost); -}; - -class RenderWidgetHost::BackingStore { - public: - BackingStore(const gfx::Size& size); - ~BackingStore(); - - HDC dc() { return hdc_; } - const gfx::Size& size() { return size_; } - - // Paints the bitmap from the renderer onto the backing store. - bool Refresh(HANDLE process, HANDLE bitmap_section, - const gfx::Rect& bitmap_rect); - private: - // Creates a dib conforming to the height/width/section parameters passed - // in. The use_os_color_depth parameter controls whether we use the color - // depth to create an appropriate dib or not. - HANDLE CreateDIB(HDC dc, int width, int height, bool use_os_color_depth, - HANDLE section); - - // The backing store dc. - HDC hdc_; - // The size of the backing store. - gfx::Size size_; - // Handle to the backing store dib. - HANDLE backing_store_dib_; - // Handle to the original bitmap in the dc. - HANDLE original_bitmap_; - - DISALLOW_COPY_AND_ASSIGN(BackingStore); + // Paints the given bitmap to the current backing store at the given location. + void PaintBackingStoreRect(HANDLE bitmap, + const gfx::Rect& bitmap_rect, + const gfx::Size& view_size); + + // Scrolls the given |clip_rect| in the backing by the given dx/dy amount. The + // |bitmap| and its corresponding location |bitmap_rect| in the backing store + // is the newly painted pixels by the renderer. + void ScrollBackingStoreRect(HANDLE bitmap, + const gfx::Rect& bitmap_rect, + int dx, int dy, + const gfx::Rect& clip_rect, + const gfx::Size& view_size); + + DISALLOW_COPY_AND_ASSIGN(RenderWidgetHost); }; class RenderWidgetHost::PaintObserver { @@ -366,4 +332,4 @@ class RenderWidgetHost::PaintObserver { virtual void RenderWidgetHostDidPaint(RenderWidgetHost* rwh) = 0; }; -#endif // #ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_ +#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_H_ diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index 8e6152f..1a3facfa 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -59,6 +59,10 @@ class RenderWidgetHostView { // Retrieves the HWND used to contain plugin HWNDs. virtual HWND GetPluginHWND() = 0; + // Moves all plugin windows as described in the given list. + virtual void MovePluginWindows( + const std::vector<WebPluginGeometry>& plugin_window_moves) = 0; + // Sends the specified mouse event to the renderer. virtual void ForwardMouseEventToRenderer(UINT message, WPARAM wparam, @@ -92,10 +96,14 @@ class RenderWidgetHostView { const gfx::Rect& caret_rect) = 0; // Informs the view that a portion of the widget's backing store was painted. + // The view should copy the given rect from the backing store of the render + // widget onto the screen. virtual void DidPaintRect(const gfx::Rect& rect) = 0; // Informs the view that a portion of the widget's backing store was scrolled - // by dx pixels horizontally and dy pixels vertically. + // 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( const gfx::Rect& rect, int dx, int dy) = 0; 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 f628809..eacf329 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -12,10 +12,8 @@ #include "chrome/browser/browser_accessibility.h" #include "chrome/browser/browser_accessibility_manager.h" #include "chrome/browser/browser_trial.h" +#include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/render_process_host.h" -// TODO(beng): (Cleanup) we should not need to include this file... see comment -// in |DidBecomeSelected|. -#include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_switches.h" @@ -143,6 +141,53 @@ HWND RenderWidgetHostViewWin::GetPluginHWND() { return m_hWnd; } +void RenderWidgetHostViewWin::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 RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, WPARAM wparam, LPARAM lparam) { @@ -401,8 +446,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { CPaintDC paint_dc(m_hWnd); HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); - RenderWidgetHost::BackingStore* backing_store = - render_widget_host_->GetBackingStore(); + BackingStore* backing_store = render_widget_host_->GetBackingStore(); if (backing_store) { gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); @@ -417,7 +461,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { paint_rect.y(), paint_rect.width(), paint_rect.height(), - backing_store->dc(), + backing_store->hdc(), paint_rect.x(), paint_rect.y(), SRCCOPY); 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 a735ab0..e8456be 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -125,6 +125,8 @@ class RenderWidgetHostViewWin : virtual void WasHidden(); virtual void SetSize(const gfx::Size& size); virtual HWND GetPluginHWND(); + virtual void MovePluginWindows( + const std::vector<WebPluginGeometry>& plugin_window_moves); virtual void ForwardMouseEventToRenderer(UINT message, WPARAM wparam, LPARAM lparam); |