From bcfc90e8a909bbc199f4d80143f5eb24abda1544 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Fri, 23 Jan 2009 23:14:11 +0000 Subject: 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 --- chrome/browser/browser.vcproj | 8 + chrome/browser/renderer_host/backing_store.cc | 243 ++++++++++++++ chrome/browser/renderer_host/backing_store.h | 130 ++++++++ chrome/browser/renderer_host/render_widget_host.cc | 356 +++------------------ chrome/browser/renderer_host/render_widget_host.h | 66 +--- .../renderer_host/render_widget_host_view.h | 10 +- .../renderer_host/render_widget_host_view_win.cc | 56 +++- .../renderer_host/render_widget_host_view_win.h | 2 + 8 files changed, 505 insertions(+), 366 deletions(-) create mode 100644 chrome/browser/renderer_host/backing_store.cc create mode 100644 chrome/browser/renderer_host/backing_store.h (limited to 'chrome/browser') 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 @@ > + + + + 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 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(&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(&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 +#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(&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(&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 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& plugin_window_moves) { - if (plugin_window_moves.empty()) - return; - - HDWP defer_window_pos_info = - ::BeginDeferWindowPos(static_cast(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& 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& 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& plugin_window_moves) { + if (plugin_window_moves.empty()) + return; + + HDWP defer_window_pos_info = + ::BeginDeferWindowPos(static_cast(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(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& plugin_window_moves); virtual void ForwardMouseEventToRenderer(UINT message, WPARAM wparam, LPARAM lparam); -- cgit v1.1