diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-22 01:27:38 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-22 01:27:38 +0000 |
commit | 4115925c9a0c074e79c0b5a181a7cf8d50180b86 (patch) | |
tree | 779ffaa81d9c4e1c6d4a491241f0f44cb0e1b815 | |
parent | 5bc0feb22687326cc26214c100c4658c79ce314f (diff) | |
download | chromium_src-4115925c9a0c074e79c0b5a181a7cf8d50180b86.zip chromium_src-4115925c9a0c074e79c0b5a181a7cf8d50180b86.tar.gz chromium_src-4115925c9a0c074e79c0b5a181a7cf8d50180b86.tar.bz2 |
More speedup of scrolling when many windowed plugins in a page. Scrolling is now at parity with single process browsers in my testing.
This works by making painting of child windows asynchronous. The key is to send, not post, the custom message. This allows the redraw message to jump the queue and get dispatched before other queued [Windows, IPC] messages, which eliminates painting artifacts.
Now that painting is asynchronous, I had to take out the SWP_NOREDRAW flag to DeferWindowPos. While it's slightly faster without it, the visual aritfacts are noticable.
Review URL: http://codereview.chromium.org/18637
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8432 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 3 | ||||
-rw-r--r-- | chrome/browser/render_widget_host.cc | 5 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.cc | 62 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_constants_win.h | 13 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 24 |
6 files changed, 83 insertions, 28 deletions
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 0362423..7c272a5 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -39,6 +39,7 @@ #include "net/proxy/proxy_service.h" #include "net/url_request/url_request.h" #include "sandbox/src/sandbox.h" +#include "webkit/glue/plugins/plugin_constants_win.h" static const char kDefaultPluginFinderURL[] = "http://dl.google.com/chrome/plugins/plugins2.xml"; @@ -389,7 +390,7 @@ class CreateWindowTask : public Task { wcex.hCursor = 0; wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); wcex.lpszMenuName = 0; - wcex.lpszClassName = L"NativeWindowClassWrapper"; + wcex.lpszClassName = kWrapperNativeWindowClassName; wcex.hIconSm = 0; window_class = RegisterClassEx(&wcex); } diff --git a/chrome/browser/render_widget_host.cc b/chrome/browser/render_widget_host.cc index 9ce5f0a..fdbec92 100644 --- a/chrome/browser/render_widget_host.cc +++ b/chrome/browser/render_widget_host.cc @@ -448,10 +448,7 @@ void RenderWidgetHost::MovePluginWindows( } for (size_t i = 0; i < plugin_window_moves.size(); ++i) { - // Don't invalidate now because that would result in cross process calls - // that make scrolling slow. Instead the window is invalidated - // asynchronously by the plugin code. - unsigned long flags = SWP_NOREDRAW; + unsigned long flags = 0; const WebPluginGeometry& move = plugin_window_moves[i]; if (move.visible) diff --git a/chrome/browser/render_widget_host_view_win.cc b/chrome/browser/render_widget_host_view_win.cc index 0aa756d..251a8c7 100644 --- a/chrome/browser/render_widget_host_view_win.cc +++ b/chrome/browser/render_widget_host_view_win.cc @@ -24,6 +24,8 @@ #include "chrome/common/win_util.h" // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h! #include "chrome/views/widget_win.h" +#include "webkit/glue/plugins/plugin_constants_win.h" +#include "webkit/glue/plugins/webplugin_delegate_impl.h" #include "webkit/glue/webcursor.h" using base::TimeDelta; @@ -259,22 +261,51 @@ void RenderWidgetHostViewWin::IMEUpdateStatus(ViewHostMsg_ImeControl control, } } -void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) { - if (is_hidden_) - return; +BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) { + if (!WebPluginDelegateImpl::IsPluginDelegateWindow(hwnd)) + return TRUE; - RECT invalid_rect = rect.ToRECT(); + gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam); + static UINT msg = RegisterWindowMessage(kPaintMessageName); + WPARAM wparam = rect->x() << 16 | rect->y(); + lparam = rect->width() << 16 | rect->height(); + // SendMessage gets the message across much quicker than PostMessage, since it + // doesn't get queued. When the plugin thread calls PeekMessage or other + // Win32 APIs, sent messages are dispatched automatically. + SendNotifyMessage(hwnd, msg, wparam, lparam); + + return TRUE; +} + +void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) { // Paint the invalid region synchronously. Our caller will not paint again // until we return, so by painting to the screen here, we ensure effective // rate-limiting of backing store updates. This helps a lot on pages that // have animations or fairly expensive layout (e.g., google maps). // - // Please refer to the RenderWidgetHostViewWin::DidScrollRect function for the - // reasoning behind the combination of flags passed to RedrawWindow. + // We paint this window synchronously, however child windows (i.e. plugins) + // are painted asynchronously. By avoiding synchronous cross-process window + // message dispatching we allow scrolling to be smooth, and also avoid the + // browser process locking up if the plugin process is hung. // - RedrawWindow(&invalid_rect, NULL, - RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME); + RedrawWindow( + &rect.ToRECT(), NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN); + + // Send the invalid rect in screen coordinates. + gfx::Rect screen_rect = GetViewBounds(); + gfx::Rect invalid_screen_rect = rect; + invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); + + LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect); + EnumChildWindows(m_hWnd, EnumChildProc, lparam); +} + +void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) { + if (is_hidden_) + return; + + Redraw(rect); } void RenderWidgetHostViewWin::DidScrollRect( @@ -291,20 +322,7 @@ void RenderWidgetHostViewWin::DidScrollRect( RECT invalid_rect = {0}; GetUpdateRect(&invalid_rect); - - // Paint the invalid region synchronously. Our caller will not paint again - // until we return, so by painting to the screen here, we ensure effective - // rate-limiting of backing store updates. This helps a lot on pages that - // have animations or fairly expensive layout (e.g., google maps). - // - // Our RenderWidgetHostViewWin does not have a non-client area, whereas the - // children (plugin windows) may. If we don't pass in RDW_FRAME then the - // children don't receive WM_NCPAINT messages while scrolling, which causes - // painting problems (http://b/issue?id=923945). We need to pass - // RDW_INVALIDATE as it is required for RDW_FRAME to work. - // - RedrawWindow(&invalid_rect, NULL, - RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME); + Redraw(gfx::Rect(invalid_rect)); } void RenderWidgetHostViewWin::RendererGone() { diff --git a/chrome/browser/render_widget_host_view_win.h b/chrome/browser/render_widget_host_view_win.h index bbf6e63..91b3684 100644 --- a/chrome/browser/render_widget_host_view_win.h +++ b/chrome/browser/render_widget_host_view_win.h @@ -209,6 +209,10 @@ class RenderWidgetHostViewWin : // invoke it from the message loop. void ShutdownHost(); + // Redraws the window synchronously, and any child windows (i.e. plugins) + // asynchronously. + void Redraw(const gfx::Rect& invalid_rect); + // The associated Model. RenderWidgetHost* render_widget_host_; diff --git a/webkit/glue/plugins/plugin_constants_win.h b/webkit/glue/plugins/plugin_constants_win.h index 9b91335..170ae62 100644 --- a/webkit/glue/plugins/plugin_constants_win.h +++ b/webkit/glue/plugins/plugin_constants_win.h @@ -20,4 +20,17 @@ #define kActiveXShimFileNameForMediaPlayer \ L"Microsoft\xAE Windows Media Player Firefox Plugin" + +// The window class name for a plugin window. +#define kNativeWindowClassName L"NativeWindowClass" + +// The name of the window class name for the wrapper HWND around the actual +// plugin window that's used when running in multi-process mode. This window +// is created on the browser UI thread. +#define kWrapperNativeWindowClassName L"WrapperNativeWindowClass" + +// The name of the custom window message that the browser uses to tell the +// plugin process to paint a window. +#define kPaintMessageName L"Chrome_CustomPaint" + #endif // WEBKIT_GLUE_PLUGIN_PLUGIN_LIST_H_ diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index a0de8da..3abcbd6 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -14,6 +14,7 @@ #include "webkit/default_plugin/plugin_impl.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/webplugin.h" +#include "webkit/glue/plugins/plugin_constants_win.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/plugins/plugin_lib.h" #include "webkit/glue/plugins/plugin_list.h" @@ -22,7 +23,6 @@ static StatsCounter windowless_queue("Plugin.ThrottleQueue"); -static const wchar_t kNativeWindowClassName[] = L"NativeWindowClass"; static const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; static const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom"; @@ -793,6 +793,28 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc( return TRUE; } + static UINT custom_msg = RegisterWindowMessage(kPaintMessageName); + if (message == custom_msg) { + // Get the invalid rect which is in screen coordinates and convert to + // window coordinates. + gfx::Rect invalid_rect; + invalid_rect.set_x(wparam >> 16); + invalid_rect.set_y(wparam & 0xFFFF); + invalid_rect.set_width(lparam >> 16); + invalid_rect.set_height(lparam & 0xFFFF); + + RECT window_rect; + GetWindowRect(hwnd, &window_rect); + invalid_rect.Offset(-window_rect.left, -window_rect.top); + + // The plugin window might have non-client area. If we don't pass in + // RDW_FRAME then the children don't receive WM_NCPAINT messages while + // scrolling, which causes painting problems (http://b/issue?id=923945). + RedrawWindow(hwnd, &invalid_rect.ToRECT(), NULL, + RDW_UPDATENOW | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME); + return FALSE; + } + current_plugin_instance_ = delegate; switch (message) { |