diff options
author | skyostil <skyostil@chromium.org> | 2014-09-09 03:12:07 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-09 10:13:42 +0000 |
commit | 457b0a1c94129337a08d0efcc3fd016205a981b4 (patch) | |
tree | 1758efc6b74efd121bf0af4766c94de55537cd7f /content | |
parent | 6b767135e631b94cd096c78f6622be28a4af277e (diff) | |
download | chromium_src-457b0a1c94129337a08d0efcc3fd016205a981b4.zip chromium_src-457b0a1c94129337a08d0efcc3fd016205a981b4.tar.gz chromium_src-457b0a1c94129337a08d0efcc3fd016205a981b4.tar.bz2 |
Forward input tasks to the Blink scheduler
Instead of posting input tasks directly to the main thread
message loop, forward them to the Blink scheduler so they
can be prioritized over other tasks.
BUG=391005
Review URL: https://codereview.chromium.org/363383002
Cr-Commit-Position: refs/heads/master@{#293914}
Diffstat (limited to 'content')
-rw-r--r-- | content/content_renderer.gypi | 1 | ||||
-rw-r--r-- | content/content_tests.gypi | 1 | ||||
-rw-r--r-- | content/renderer/gpu/render_widget_compositor.cc | 18 | ||||
-rw-r--r-- | content/renderer/input/input_event_filter.cc | 16 | ||||
-rw-r--r-- | content/renderer/input/input_event_filter.h | 9 | ||||
-rw-r--r-- | content/renderer/input/input_event_filter_unittest.cc | 6 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.cc | 14 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.h | 10 | ||||
-rw-r--r-- | content/renderer/scheduler_proxy_task_runner.h | 87 | ||||
-rw-r--r-- | content/renderer/scheduler_proxy_task_runner_browsertest.cc | 85 |
10 files changed, 224 insertions, 23 deletions
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 6daf2d9..ee23601 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -358,6 +358,7 @@ 'renderer/sad_plugin.h', 'renderer/savable_resources.cc', 'renderer/savable_resources.h', + 'renderer/scheduler_proxy_task_runner.h', 'renderer/screen_orientation/screen_orientation_dispatcher.cc', 'renderer/screen_orientation/screen_orientation_dispatcher.h', 'renderer/screen_orientation/screen_orientation_observer.cc', diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 1e6b386..835f4fe 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi @@ -1205,6 +1205,7 @@ 'renderer/render_widget_browsertest.cc', 'renderer/resource_fetcher_browsertest.cc', 'renderer/savable_resources_browsertest.cc', + 'renderer/scheduler_proxy_task_runner_browsertest.cc', 'test/accessibility_browser_test_utils.cc', 'test/accessibility_browser_test_utils.h', 'test/content_browser_test_test.cc', diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index a9001f3..d264aaa 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc @@ -522,6 +522,8 @@ bool RenderWidgetCompositor::SendMessageToMicroBenchmark( void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) { scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy; + scoped_refptr<base::SingleThreadTaskRunner> + main_thread_compositor_task_runner(base::MessageLoopProxy::current()); RenderThreadImpl* render_thread = RenderThreadImpl::current(); cc::SharedBitmapManager* shared_bitmap_manager = NULL; // render_thread may be NULL in tests. @@ -529,21 +531,23 @@ void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) { compositor_message_loop_proxy = render_thread->compositor_message_loop_proxy(); shared_bitmap_manager = render_thread->shared_bitmap_manager(); + main_thread_compositor_task_runner = + render_thread->main_thread_compositor_task_runner(); } if (compositor_message_loop_proxy.get()) { - layer_tree_host_ = cc::LayerTreeHost::CreateThreaded( - this, - shared_bitmap_manager, - settings, - base::MessageLoopProxy::current(), - compositor_message_loop_proxy); + layer_tree_host_ = + cc::LayerTreeHost::CreateThreaded(this, + shared_bitmap_manager, + settings, + main_thread_compositor_task_runner, + compositor_message_loop_proxy); } else { layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded( this, this, shared_bitmap_manager, settings, - base::MessageLoopProxy::current()); + main_thread_compositor_task_runner); } DCHECK(layer_tree_host_); } diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc index 5017cb4..d93836a 100644 --- a/content/renderer/input/input_event_filter.cc +++ b/content/renderer/input/input_event_filter.cc @@ -10,6 +10,7 @@ #include "base/debug/trace_event.h" #include "base/location.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/single_thread_task_runner.h" #include "cc/input/input_handler.h" #include "content/common/input/did_overscroll_params.h" #include "content/common/input/web_input_event_traits.h" @@ -41,8 +42,9 @@ namespace content { InputEventFilter::InputEventFilter( IPC::Listener* main_listener, + const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, const scoped_refptr<base::MessageLoopProxy>& target_loop) - : main_loop_(base::MessageLoopProxy::current()), + : main_task_runner_(main_task_runner), main_listener_(main_listener), sender_(NULL), target_loop_(target_loop), @@ -55,7 +57,7 @@ InputEventFilter::InputEventFilter( } void InputEventFilter::SetBoundHandler(const Handler& handler) { - DCHECK(main_loop_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); handler_ = handler; } @@ -148,10 +150,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { "input", "InputEventFilter::ForwardToHandler::ForwardToMainListener", TRACE_EVENT_SCOPE_THREAD); - main_loop_->PostTask( + main_task_runner_->PostTask( FROM_HERE, - base::Bind(&InputEventFilter::ForwardToMainListener, - this, message)); + base::Bind(&InputEventFilter::ForwardToMainListener, this, message)); return; } @@ -183,10 +184,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { TRACE_EVENT_SCOPE_THREAD); IPC::Message new_msg = InputMsg_HandleInputEvent( routing_id, event, latency_info, is_keyboard_shortcut); - main_loop_->PostTask( + main_task_runner_->PostTask( FROM_HERE, - base::Bind(&InputEventFilter::ForwardToMainListener, - this, new_msg)); + base::Bind(&InputEventFilter::ForwardToMainListener, this, new_msg)); return; } diff --git a/content/renderer/input/input_event_filter.h b/content/renderer/input/input_event_filter.h index a80b9f8..0e39592 100644 --- a/content/renderer/input/input_event_filter.h +++ b/content/renderer/input/input_event_filter.h @@ -18,6 +18,7 @@ namespace base { class MessageLoopProxy; +class SingleThreadTaskRunner; } namespace IPC { @@ -38,8 +39,10 @@ namespace content { class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient, public IPC::MessageFilter { public: - InputEventFilter(IPC::Listener* main_listener, - const scoped_refptr<base::MessageLoopProxy>& target_loop); + InputEventFilter( + IPC::Listener* main_listener, + const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, + const scoped_refptr<base::MessageLoopProxy>& target_loop); // The |handler| is invoked on the thread associated with |target_loop| to // handle input events matching the filtered routes. @@ -73,7 +76,7 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient, void SendMessage(scoped_ptr<IPC::Message> message); void SendMessageOnIOThread(scoped_ptr<IPC::Message> message); - scoped_refptr<base::MessageLoopProxy> main_loop_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; IPC::Listener* main_listener_; // The sender_ only gets invoked on the thread corresponding to io_loop_. diff --git a/content/renderer/input/input_event_filter_unittest.cc b/content/renderer/input/input_event_filter_unittest.cc index a234e79..d181a03 100644 --- a/content/renderer/input/input_event_filter_unittest.cc +++ b/content/renderer/input/input_event_filter_unittest.cc @@ -126,9 +126,9 @@ void AddEventsToFilter(IPC::MessageFilter* message_filter, class InputEventFilterTest : public testing::Test { public: virtual void SetUp() OVERRIDE { - filter_ = new InputEventFilter( - &message_recorder_, - message_loop_.message_loop_proxy()); + filter_ = new InputEventFilter(&message_recorder_, + base::MessageLoopProxy::current(), + message_loop_.message_loop_proxy()); filter_->SetBoundHandler( base::Bind(&InputEventRecorder::HandleInputEvent, base::Unretained(&event_recorder_))); diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 357d14e..8eac9af 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -21,6 +21,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/stats_table.h" #include "base/path_service.h" +#include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_tokenizer.h" @@ -91,6 +92,7 @@ #include "content/renderer/render_process_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" +#include "content/renderer/scheduler_proxy_task_runner.h" #include "content/renderer/service_worker/embedded_worker_context_message_filter.h" #include "content/renderer/service_worker/embedded_worker_dispatcher.h" #include "content/renderer/shared_worker/embedded_shared_worker_stub.h" @@ -105,6 +107,7 @@ #include "net/base/net_util.h" #include "skia/ext/event_tracer_impl.h" #include "third_party/WebKit/public/platform/WebString.h" +#include "third_party/WebKit/public/platform/WebThread.h" #include "third_party/WebKit/public/web/WebColorName.h" #include "third_party/WebKit/public/web/WebDatabase.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -645,6 +648,9 @@ void RenderThreadImpl::Shutdown() { // hold pointers to V8 objects (e.g., via pending requests). main_thread_indexed_db_dispatcher_.reset(); + main_thread_compositor_task_runner_ = NULL; + main_thread_input_task_runner_ = NULL; + if (webkit_platform_support_) blink::shutdown(); @@ -827,6 +833,10 @@ void RenderThreadImpl::EnsureWebKitInitialized() { webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl); blink::initialize(webkit_platform_support_.get()); + // TODO(skyostil): Forward compositor tasks to the Blink scheduler. + main_thread_compositor_task_runner_ = base::MessageLoopProxy::current(); + main_thread_input_task_runner_ = make_scoped_refptr( + new SchedulerProxyTaskRunner<&blink::WebSchedulerProxy::postInputTask>()); v8::Isolate* isolate = blink::mainThreadIsolate(); @@ -866,8 +876,8 @@ void RenderThreadImpl::EnsureWebKitInitialized() { } #endif if (!input_handler_manager_client) { - input_event_filter_ = - new InputEventFilter(this, compositor_message_loop_proxy_); + input_event_filter_ = new InputEventFilter( + this, main_thread_input_task_runner_, compositor_message_loop_proxy_); AddFilter(input_event_filter_.get()); input_handler_manager_client = input_event_filter_.get(); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 59a6629..483ace8 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -43,6 +43,7 @@ class WebMediaStreamCenterClient; namespace base { class MessageLoopProxy; +class SingleThreadTaskRunner; class Thread; } @@ -198,6 +199,11 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, return webkit_platform_support_.get(); } + scoped_refptr<base::SingleThreadTaskRunner> + main_thread_compositor_task_runner() const { + return main_thread_compositor_task_runner_; + } + IPC::ForwardingMessageFilter* compositor_output_surface_filter() const { return compositor_output_surface_filter_.get(); } @@ -567,6 +573,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, scoped_ptr<MemoryObserver> memory_observer_; + scoped_refptr<base::SingleThreadTaskRunner> + main_thread_compositor_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> main_thread_input_task_runner_; + // Compositor settings bool is_gpu_rasterization_enabled_; bool is_gpu_rasterization_forced_; diff --git a/content/renderer/scheduler_proxy_task_runner.h b/content/renderer/scheduler_proxy_task_runner.h new file mode 100644 index 0000000..c4ccb2a --- /dev/null +++ b/content/renderer/scheduler_proxy_task_runner.h @@ -0,0 +1,87 @@ +// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_PROXY_TASK_RUNNER_H_ +#define CONTENT_RENDERER_SCHEDULER_PROXY_TASK_RUNNER_H_ + +#include "base/debug/task_annotator.h" +#include "base/pending_task.h" +#include "content/renderer/render_thread_impl.h" +#include "third_party/WebKit/public/platform/WebSchedulerProxy.h" +#include "third_party/WebKit/public/platform/WebTraceLocation.h" + +namespace content { + +// Helper for forwarding posted tasks into different WebSchedulerProxy queues. +template <void (blink::WebSchedulerProxy::*ProxyFunction)( + const blink::WebTraceLocation& location, + blink::WebThread::Task* task)> +class SchedulerProxyTaskRunner : public base::SingleThreadTaskRunner { + public: + SchedulerProxyTaskRunner() + : main_thread_id_(base::PlatformThread::CurrentId()), + scheduler_proxy_(blink::WebSchedulerProxy::create()), + next_sequence_num_(0) {} + + // base::SingleThreadTaskRunner implementation: + virtual bool RunsTasksOnCurrentThread() const OVERRIDE { + return base::PlatformThread::CurrentId() == main_thread_id_; + } + + virtual bool PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) OVERRIDE { + DCHECK(delay == base::TimeDelta()); + base::PendingTask pending_task(from_here, task); + pending_task.sequence_num = ++next_sequence_num_; + task_annotator_.DidQueueTask("SchedulerProxyTaskRunner::PostDelayedTask", + pending_task); + blink::WebTraceLocation location(from_here.function_name(), + from_here.file_name()); + TaskAdapter* task_adapter = new TaskAdapter(&task_annotator_, pending_task); + (scheduler_proxy_.*ProxyFunction)(location, task_adapter); + return true; + } + + virtual bool PostNonNestableDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& task, + base::TimeDelta delay) OVERRIDE { + NOTREACHED(); + return false; + } + + protected: + virtual ~SchedulerProxyTaskRunner() {} + + private: + class TaskAdapter : public blink::WebThread::Task { + public: + explicit TaskAdapter(base::debug::TaskAnnotator* task_annotator, + const base::PendingTask& pending_task) + : task_annotator_(task_annotator), pending_task_(pending_task) {} + virtual ~TaskAdapter() {} + + virtual void run() { + task_annotator_->RunTask("SchedulerProxyTaskRunner::PostDelayedTask", + "SchedulerProxyTaskRunner::RunTask", + pending_task_); + } + + private: + base::debug::TaskAnnotator* task_annotator_; + base::PendingTask pending_task_; + }; + + const base::PlatformThreadId main_thread_id_; + blink::WebSchedulerProxy scheduler_proxy_; + base::debug::TaskAnnotator task_annotator_; + int next_sequence_num_; + + DISALLOW_COPY_AND_ASSIGN(SchedulerProxyTaskRunner); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_SCHEDULER_PROXY_TASK_RUNNER_H_ diff --git a/content/renderer/scheduler_proxy_task_runner_browsertest.cc b/content/renderer/scheduler_proxy_task_runner_browsertest.cc new file mode 100644 index 0000000..d67c54d --- /dev/null +++ b/content/renderer/scheduler_proxy_task_runner_browsertest.cc @@ -0,0 +1,85 @@ +// Copyright 2014 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 "content/public/browser/content_browser_client.h" +#include "content/public/common/content_client.h" +#include "content/public/renderer/content_renderer_client.h" +#include "content/renderer/render_process_impl.h" +#include "content/renderer/render_thread_impl.h" +#include "content/renderer/scheduler_proxy_task_runner.h" +#include "content/test/mock_render_process.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +void TestTask(int value, int* result) { + *result = (*result << 4) | value; +} + +} // namespace + +class DummyListener : public IPC::Listener { + public: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { + return true; + } +}; + +TEST(SchedulerProxyTaskRunnerBrowserTest, TestTaskPosting) { + ContentClient content_client; + ContentBrowserClient content_browser_client; + ContentRendererClient content_renderer_client; + SetContentClient(&content_client); + SetBrowserClientForTesting(&content_browser_client); + SetRendererClientForTesting(&content_renderer_client); + base::MessageLoopForIO message_loop; + + std::string channel_id = + IPC::Channel::GenerateVerifiedChannelID(std::string()); + DummyListener dummy_listener; + scoped_ptr<IPC::Channel> channel( + IPC::Channel::CreateServer(channel_id, &dummy_listener)); + EXPECT_TRUE(channel->Connect()); + + scoped_ptr<MockRenderProcess> mock_process(new MockRenderProcess); + // Owned by mock_process. + RenderThreadImpl* thread = new RenderThreadImpl(channel_id); + thread->EnsureWebKitInitialized(); + + scoped_refptr<base::SingleThreadTaskRunner> input_task_runner = + make_scoped_refptr(new SchedulerProxyTaskRunner< + &blink::WebSchedulerProxy::postInputTask>()); + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = + make_scoped_refptr(new SchedulerProxyTaskRunner< + &blink::WebSchedulerProxy::postCompositorTask>()); + + int input_order = 0; + int compositor_order = 0; + + input_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 1, &input_order)); + compositor_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 1, &compositor_order)); + input_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 2, &input_order)); + compositor_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 2, &compositor_order)); + + input_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 3, &input_order)); + input_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 4, &input_order)); + compositor_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 3, &compositor_order)); + compositor_task_runner->PostTask(FROM_HERE, + base::Bind(&TestTask, 4, &compositor_order)); + + message_loop.RunUntilIdle(); + + EXPECT_EQ(0x1234, input_order); + EXPECT_EQ(0x1234, compositor_order); +} + +} // namespace content |