diff options
author | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 22:37:29 +0000 |
---|---|---|
committer | jochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 22:37:29 +0000 |
commit | 76697525b9e553a0473b17c9bd3384940300edf0 (patch) | |
tree | 3a3adb31bad4d6d437afb3fb024997e55af761a9 /content/shell | |
parent | 3214b6f596ff24dd398d0c10dea4011ac8d9e789 (diff) | |
download | chromium_src-76697525b9e553a0473b17c9bd3384940300edf0.zip chromium_src-76697525b9e553a0473b17c9bd3384940300edf0.tar.gz chromium_src-76697525b9e553a0473b17c9bd3384940300edf0.tar.bz2 |
[content shell] implement testRunner.display
For layout tests, we only generate frames at defined points (when the test finishes, and when e.g. testRunner.display() is invoked). For each frame, we must only paint the union of all invalidated rects since the last frame.
To achieve this, we forward paint related callbacks from the WebWidgetClient interface to the RenderViewObserver.
With that WebKitTestRunner can mimick the exact behavior of DRT.
BUG=111316
TEST=repaint tests pass
Review URL: https://codereview.chromium.org/11187020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162559 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/shell')
-rw-r--r-- | content/shell/shell_main_delegate.cc | 2 | ||||
-rw-r--r-- | content/shell/webkit_test_runner.cc | 135 | ||||
-rw-r--r-- | content/shell/webkit_test_runner.h | 27 | ||||
-rw-r--r-- | content/shell/webkit_test_runner.js | 2 | ||||
-rw-r--r-- | content/shell/webkit_test_runner_bindings.cc | 14 |
5 files changed, 156 insertions, 24 deletions
diff --git a/content/shell/shell_main_delegate.cc b/content/shell/shell_main_delegate.cc index 3a2532d..5ea181a 100644 --- a/content/shell/shell_main_delegate.cc +++ b/content/shell/shell_main_delegate.cc @@ -90,8 +90,6 @@ bool ShellMainDelegate::BasicStartupComplete(int* exit_code) { if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) { CommandLine::ForCurrentProcess()->AppendSwitch( switches::kAllowFileAccessFromFiles); - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kForceCompositingMode); CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kUseGL, gfx::kGLImplementationOSMesaName); CommandLine::ForCurrentProcess()->AppendSwitch( diff --git a/content/shell/webkit_test_runner.cc b/content/shell/webkit_test_runner.cc index 9970b39..5b07f41 100644 --- a/content/shell/webkit_test_runner.cc +++ b/content/shell/webkit_test_runner.cc @@ -4,6 +4,8 @@ #include "content/shell/webkit_test_runner.h" +#include <cmath> + #include "base/md5.h" #include "base/memory/scoped_ptr.h" #include "base/stringprintf.h" @@ -11,7 +13,6 @@ #include "content/shell/shell_messages.h" #include "skia/ext/platform_canvas.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" @@ -94,18 +95,6 @@ std::string DumpFrameScrollPosition(WebFrame* frame, bool recursive) { return result; } -bool PaintViewIntoCanvas(WebView* view, skia::PlatformCanvas& canvas) { - view->layout(); - const WebSize& size = view->size(); - - if (!canvas.initialize(size.width, size.height, true)) - return false; - - view->paint(webkit_glue::ToWebCanvas(&canvas), - WebRect(0, 0, size.width, size.height)); - return true; -} - #if !defined(OS_MACOSX) void MakeBitmapOpaque(SkBitmap* bitmap) { SkAutoLockPixels lock(*bitmap); @@ -118,12 +107,8 @@ void MakeBitmapOpaque(SkBitmap* bitmap) { } #endif -void CaptureSnapshot(WebView* view, SkBitmap* snapshot) { - skia::PlatformCanvas canvas; - if (!PaintViewIntoCanvas(view, canvas)) - return; - - SkDevice* device = skia::GetTopDevice(canvas); +void CopyCanvasToBitmap(skia::PlatformCanvas* canvas, SkBitmap* snapshot) { + SkDevice* device = skia::GetTopDevice(*canvas); const SkBitmap& bitmap = device->accessBitmap(false); bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config); @@ -138,7 +123,8 @@ void CaptureSnapshot(WebView* view, SkBitmap* snapshot) { } // namespace WebKitTestRunner::WebKitTestRunner(RenderView* render_view) - : RenderViewObserver(render_view) { + : RenderViewObserver(render_view), + RenderViewObserverTracker<WebKitTestRunner>(render_view) { } WebKitTestRunner::~WebKitTestRunner() { @@ -164,6 +150,32 @@ bool WebKitTestRunner::OnMessageReceived(const IPC::Message& message) { return handled; } +void WebKitTestRunner::DidInvalidateRect(const WebRect& rect) { + UpdatePaintRect(rect); +} + +void WebKitTestRunner::DidScrollRect(int dx, int dy, const WebRect& rect) { + DidInvalidateRect(rect); +} + +void WebKitTestRunner::DidRequestScheduleComposite() { + const WebSize& size = render_view()->GetWebView()->size(); + WebRect rect(0, 0, size.width, size.height); + DidInvalidateRect(rect); +} + +void WebKitTestRunner::DidRequestScheduleAnimation() { + DidRequestScheduleComposite(); +} + +void WebKitTestRunner::Display() { + const WebSize& size = render_view()->GetWebView()->size(); + WebRect rect(0, 0, size.width, size.height); + UpdatePaintRect(rect); + PaintInvalidatedRegion(); + DisplayRepaintMask(); +} + void WebKitTestRunner::OnCaptureTextDump(bool as_text, bool printing, bool recursive) { @@ -185,7 +197,8 @@ void WebKitTestRunner::OnCaptureTextDump(bool as_text, void WebKitTestRunner::OnCaptureImageDump( const std::string& expected_pixel_hash) { SkBitmap snapshot; - CaptureSnapshot(render_view()->GetWebView(), &snapshot); + PaintInvalidatedRegion(); + CopyCanvasToBitmap(GetCanvas(), &snapshot); SkAutoLockPixels snapshot_lock(snapshot); base::MD5Digest digest; @@ -217,4 +230,84 @@ void WebKitTestRunner::OnCaptureImageDump( routing_id(), actual_pixel_hash, snapshot)); } +skia::PlatformCanvas* WebKitTestRunner::GetCanvas() { + if (canvas_) + return canvas_.get(); + + WebView* view = render_view()->GetWebView(); + const WebSize& size = view->size(); + float device_scale_factor = view->deviceScaleFactor(); + canvas_.reset(new skia::PlatformCanvas); + canvas_->initialize(std::ceil(device_scale_factor * size.width), + std::ceil(device_scale_factor * size.height), + true); + return canvas_.get(); +} + +void WebKitTestRunner::UpdatePaintRect(const WebRect& rect) { + // Update paint_rect_ to the smallest rectangle that covers both rect and + // paint_rect_. + if (rect.isEmpty()) + return; + if (paint_rect_.isEmpty()) { + paint_rect_ = rect; + return; + } + int left = std::min(paint_rect_.x, rect.x); + int top = std::min(paint_rect_.y, rect.y); + int right = std::max(paint_rect_.x + paint_rect_.width, rect.x + rect.width); + int bottom = std::max(paint_rect_.y + paint_rect_.height, + rect.y + rect.height); + paint_rect_ = WebRect(left, top, right - left, bottom - top); +} + +void WebKitTestRunner::PaintRect(const WebRect& rect) { + WebView* view = render_view()->GetWebView(); + float device_scale_factor = view->deviceScaleFactor(); + int scaled_x = device_scale_factor * rect.x; + int scaled_y = device_scale_factor * rect.y; + int scaled_width = std::ceil(device_scale_factor * rect.width); + int scaled_height = std::ceil(device_scale_factor * rect.height); + // TODO(jochen): Verify that the scaling is correct once the HiDPI tests + // actually work. + WebRect device_rect(scaled_x, scaled_y, scaled_width, scaled_height); + view->paint(webkit_glue::ToWebCanvas(GetCanvas()), device_rect); +} + +void WebKitTestRunner::PaintInvalidatedRegion() { + WebView* view = render_view()->GetWebView(); + view->animate(0.0); + view->layout(); + const WebSize& widget_size = view->size(); + WebRect client_rect(0, 0, widget_size.width, widget_size.height); + + // Paint the canvas if necessary. Allow painting to generate extra rects + // for the first two calls. This is necessary because some WebCore rendering + // objects update their layout only when painted. + for (int i = 0; i < 3; ++i) { + // Make sure that paint_rect_ is always inside the RenderView's visible + // area. + int left = std::max(paint_rect_.x, client_rect.x); + int top = std::max(paint_rect_.y, client_rect.y); + int right = std::min(paint_rect_.x + paint_rect_.width, + client_rect.x + client_rect.width); + int bottom = std::min(paint_rect_.y + paint_rect_.height, + client_rect.y + client_rect.height); + if (left >= right || top >= bottom) + paint_rect_ = WebRect(); + else + paint_rect_ = WebRect(left, top, right - left, bottom - top); + if (paint_rect_.isEmpty()) + continue; + WebRect rect(paint_rect_); + paint_rect_ = WebRect(); + PaintRect(rect); + } + CHECK(paint_rect_.isEmpty()); +} + +void WebKitTestRunner::DisplayRepaintMask() { + GetCanvas()->drawARGB(167, 0, 0, 0); +} + } // namespace content diff --git a/content/shell/webkit_test_runner.h b/content/shell/webkit_test_runner.h index 539ed09..eb2584f 100644 --- a/content/shell/webkit_test_runner.h +++ b/content/shell/webkit_test_runner.h @@ -5,12 +5,20 @@ #ifndef CONTENT_SHELL_WEBKIT_TEST_RUNNER_H_ #define CONTENT_SHELL_WEBKIT_TEST_RUNNER_H_ +#include "base/memory/scoped_ptr.h" #include "content/public/renderer/render_view_observer.h" +#include "content/public/renderer/render_view_observer_tracker.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" + +namespace skia { +class PlatformCanvas; +} namespace content { // This is the renderer side of the webkit test runner. -class WebKitTestRunner : public RenderViewObserver { +class WebKitTestRunner : public RenderViewObserver, + public RenderViewObserverTracker<WebKitTestRunner> { public: explicit WebKitTestRunner(RenderView* render_view); virtual ~WebKitTestRunner(); @@ -19,12 +27,29 @@ class WebKitTestRunner : public RenderViewObserver { virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE; virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE; + virtual void DidInvalidateRect(const WebKit::WebRect& rect) OVERRIDE; + virtual void DidScrollRect(int dx, + int dy, + const WebKit::WebRect& rect) OVERRIDE; + virtual void DidRequestScheduleComposite() OVERRIDE; + virtual void DidRequestScheduleAnimation() OVERRIDE; + + void Display(); private: // Message handlers. void OnCaptureTextDump(bool as_text, bool printing, bool recursive); void OnCaptureImageDump(const std::string& expected_pixel_hash); + skia::PlatformCanvas* GetCanvas(); + void UpdatePaintRect(const WebKit::WebRect& rect); + void PaintRect(const WebKit::WebRect& rect); + void PaintInvalidatedRegion(); + void DisplayRepaintMask(); + + scoped_ptr<skia::PlatformCanvas> canvas_; + WebKit::WebRect paint_rect_; + DISALLOW_COPY_AND_ASSIGN(WebKitTestRunner); }; diff --git a/content/shell/webkit_test_runner.js b/content/shell/webkit_test_runner.js index 8865ec9..2891bf5 100644 --- a/content/shell/webkit_test_runner.js +++ b/content/shell/webkit_test_runner.js @@ -9,6 +9,7 @@ var eventSender = eventSender || {}; var textInputController = textInputController || {}; (function() { + native function Display(); native function GetWorkerThreadCount(); native function NotifyDone(); native function OverridePreference(); @@ -52,6 +53,7 @@ var textInputController = textInputController || {}; "setShouldStayOnPageAfterHandlingBeforeUnload", {value: SetShouldStayOnPageAfterHandlingBeforeUnload}); Object.defineProperty(this, "waitUntilDone", {value: SetWaitUntilDone}); + Object.defineProperty(this, "display", {value: Display}); } TestRunner.prototype = DefaultHandler("testRunner"); testRunner = new TestRunner(); diff --git a/content/shell/webkit_test_runner_bindings.cc b/content/shell/webkit_test_runner_bindings.cc index 6d1eb6f..15235357 100644 --- a/content/shell/webkit_test_runner_bindings.cc +++ b/content/shell/webkit_test_runner_bindings.cc @@ -7,6 +7,7 @@ #include "base/string_piece.h" #include "content/public/renderer/render_view.h" #include "content/shell/shell_messages.h" +#include "content/shell/webkit_test_runner.h" #include "grit/shell_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" @@ -42,6 +43,17 @@ RenderView* GetCurrentRenderView() { return render_view; } +v8::Handle<v8::Value> Display(const v8::Arguments& args) { + RenderView* view = GetCurrentRenderView(); + if (!view) + return v8::Undefined(); + WebKitTestRunner* runner = WebKitTestRunner::Get(view); + if (!runner) + return v8::Undefined(); + runner->Display(); + return v8::Undefined(); +} + v8::Handle<v8::Value> NotifyDone(const v8::Arguments& args) { RenderView* view = GetCurrentRenderView(); if (!view) @@ -147,6 +159,8 @@ WebKitTestRunnerBindings::~WebKitTestRunnerBindings() { v8::Handle<v8::FunctionTemplate> WebKitTestRunnerBindings::GetNativeFunction(v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("Display"))) + return v8::FunctionTemplate::New(Display); if (name->Equals(v8::String::New("NotifyDone"))) return v8::FunctionTemplate::New(NotifyDone); if (name->Equals(v8::String::New("SetDumpAsText"))) |