#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"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "cc/base/switches.h"
+#include "cc/blink/web_external_bitmap_impl.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/resources/raster_worker_pool.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/appcache/appcache_frontend_impl.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_process_observer.h"
#include "content/public/renderer/render_view_visitor.h"
-#include "content/renderer/compositor_bindings/web_external_bitmap_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/devtools/devtools_agent_filter.h"
#include "content/renderer/dom_storage/dom_storage_dispatcher.h"
#include "content/renderer/dom_storage/webstoragearea_impl.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
-#include "content/renderer/gamepad_shared_memory_reader.h"
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/gpu_benchmarking_extension.h"
#include "content/renderer/input/input_event_filter.h"
#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"
-#include "grit/content_resources.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_forwarding_message_filter.h"
#include "ipc/ipc_platform_file.h"
#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"
namespace {
const int64 kInitialIdleHandlerDelayMs = 1000;
-const int64 kShortIdleHandlerDelayMs = 1000;
const int64 kLongIdleHandlerDelayMs = 30*1000;
-const int kIdleCPUUsageThresholdInPercents = 3;
-const int kMinRasterThreads = 1;
-const int kMaxRasterThreads = 64;
// Maximum allocation size allowed for image scaling filters that
// require pre-scaling. Skia will fallback to a filter that doesn't
return attributes;
}
+void DeletedGpuMemoryBuffer(ThreadSafeSender* sender,
+ gfx::GpuMemoryBufferType type,
+ const gfx::GpuMemoryBufferId& id) {
+ TRACE_EVENT0("renderer", "RenderThreadImpl::DeletedGpuMemoryBuffer");
+ sender->Send(new ChildProcessHostMsg_DeletedGpuMemoryBuffer(type, id));
+}
+
} // namespace
// For measuring memory usage after each task. Behind a command line flag.
}
virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
+ LOCAL_HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
}
private:
is_impl_side_painting_enabled_ =
command_line.HasSwitch(switches::kEnableImplSidePainting);
- WebLayerImpl::SetImplSidePaintingEnabled(is_impl_side_painting_enabled_);
+ cc_blink::WebLayerImpl::SetImplSidePaintingEnabled(
+ is_impl_side_painting_enabled_);
is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy) &&
!command_line.HasSwitch(switches::kDisableZeroCopy);
is_distance_field_text_enabled_ = false;
}
- is_low_res_tiling_enabled_ = true;
- if (command_line.HasSwitch(switches::kDisableLowResTiling) &&
- !command_line.HasSwitch(switches::kEnableLowResTiling)) {
- is_low_res_tiling_enabled_ = false;
- }
-
// Note that under Linux, the media library will normally already have
// been initialized by the Zygote before this instance became a Renderer.
base::FilePath media_path;
// it doesn't have to be the same thread RenderThreadImpl is created on.
allocate_gpu_memory_buffer_thread_checker_.DetachFromThread();
- if (command_line.HasSwitch(switches::kNumRasterThreads)) {
- int num_raster_threads;
+ if (is_impl_side_painting_enabled_) {
+ int num_raster_threads = 0;
std::string string_value =
command_line.GetSwitchValueASCII(switches::kNumRasterThreads);
- if (base::StringToInt(string_value, &num_raster_threads) &&
- num_raster_threads >= kMinRasterThreads &&
- num_raster_threads <= kMaxRasterThreads) {
- cc::RasterWorkerPool::SetNumRasterThreads(num_raster_threads);
- } else {
- LOG(WARNING) << "Failed to parse switch " <<
- switches::kNumRasterThreads << ": " << string_value;
- }
+ bool parsed_num_raster_threads =
+ base::StringToInt(string_value, &num_raster_threads);
+ DCHECK(parsed_num_raster_threads) << string_value;
+ DCHECK_GT(num_raster_threads, 0);
+ cc::RasterWorkerPool::SetNumRasterThreads(num_raster_threads);
}
service_registry()->AddService<RenderFrameSetup>(
RemoveFilter(audio_input_message_filter_.get());
audio_input_message_filter_ = NULL;
- RemoveFilter(audio_message_filter_.get());
- audio_message_filter_ = NULL;
-
#if defined(ENABLE_WEBRTC)
RTCPeerConnectionHandler::DestructAllHandlers();
}
media_thread_.reset();
+
+ // AudioMessageFilter may be accessed on |media_thread_|, so shutdown after.
+ RemoveFilter(audio_message_filter_.get());
+ audio_message_filter_ = NULL;
+
compositor_thread_.reset();
input_handler_manager_.reset();
if (input_event_filter_.get()) {
// hold pointers to V8 objects (e.g., via pending requests).
main_thread_indexed_db_dispatcher_.reset();
+ main_thread_compositor_task_runner_ = NULL;
+
if (webkit_platform_support_)
blink::shutdown();
webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
blink::initialize(webkit_platform_support_.get());
+ main_thread_compositor_task_runner_ = base::MessageLoopProxy::current();
v8::Isolate* isolate = blink::mainThreadIsolate();
#endif
if (!input_handler_manager_client) {
input_event_filter_ =
- new InputEventFilter(this, compositor_message_loop_proxy_);
+ new InputEventFilter(this,
+ main_thread_compositor_task_runner_,
+ compositor_message_loop_proxy_);
AddFilter(input_event_filter_.get());
input_handler_manager_client = input_event_filter_.get();
}
CompositorOutputSurface::CreateFilter(output_surface_loop.get());
AddFilter(compositor_output_surface_filter_.get());
- gamepad_shared_memory_reader_.reset(
- new GamepadSharedMemoryReader(webkit_platform_support_.get()));
- AddObserver(gamepad_shared_memory_reader_.get());
-
RenderThreadImpl::RegisterSchemes();
EnableBlinkPlatformLogChannels(
SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
if (!media::IsMediaLibraryInitialized()) {
- WebRuntimeFeatures::enableMediaPlayer(false);
WebRuntimeFeatures::enableWebAudio(false);
}
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
ScheduleIdleHandler(kLongIdleHandlerDelayMs);
- SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
+ cc_blink::SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
// Limit use of the scaled image cache to when deferred image decoding is
// enabled.
GetContentClient()->renderer()->
RunIdleHandlerWhenWidgetsHidden();
if (run_in_foreground_tab) {
- IdleHandlerInForegroundTab();
+ if (idle_notifications_to_skip_ > 0) {
+ --idle_notifications_to_skip_;
+ } else {
+ base::allocator::ReleaseFreeMemory();
+ base::DiscardableMemory::ReduceMemoryUsage();
+ }
+ ScheduleIdleHandler(kLongIdleHandlerDelayMs);
return;
}
continue_timer = true;
}
- // Schedule next invocation.
+ // Schedule next invocation. When the tab is originally hidden, an invocation
+ // is scheduled for kInitialIdleHandlerDelayMs in
+ // RenderThreadImpl::WidgetHidden in order to race to a minimal heap.
+ // After that, idle calls can be much less frequent, so run at a maximum of
+ // once every kLongIdleHandlerDelayMs.
// Dampen the delay using the algorithm (if delay is in seconds):
// delay = delay + 1 / (delay + 2)
// Using floor(delay) has a dampening effect such as:
- // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
+ // 30s, 30, 30, 31, 31, 31, 31, 32, 32, ...
// If the delay is in milliseconds, the above formula is equivalent to:
// delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
// which is equivalent to
// delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
- // Note that idle_notification_delay_in_ms_ would be reset to
- // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden.
if (continue_timer) {
- ScheduleIdleHandler(idle_notification_delay_in_ms_ +
- 1000000 / (idle_notification_delay_in_ms_ + 2000));
+ ScheduleIdleHandler(
+ std::max(kLongIdleHandlerDelayMs,
+ idle_notification_delay_in_ms_ +
+ 1000000 / (idle_notification_delay_in_ms_ + 2000)));
} else {
idle_timer_.Stop();
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
}
-void RenderThreadImpl::IdleHandlerInForegroundTab() {
- // Increase the delay in the same way as in IdleHandler,
- // but make it periodic by reseting it once it is too big.
- int64 new_delay_ms = idle_notification_delay_in_ms_ +
- 1000000 / (idle_notification_delay_in_ms_ + 2000);
- if (new_delay_ms >= kLongIdleHandlerDelayMs)
- new_delay_ms = kShortIdleHandlerDelayMs;
-
- if (idle_notifications_to_skip_ > 0) {
- idle_notifications_to_skip_--;
- } else {
- int cpu_usage = 0;
- Send(new ViewHostMsg_GetCPUUsage(&cpu_usage));
- // Idle notification hint roughly specifies the expected duration of the
- // idle pause. We set it proportional to the idle timer delay.
- int idle_hint = static_cast<int>(new_delay_ms / 10);
- if (cpu_usage < kIdleCPUUsageThresholdInPercents) {
- base::allocator::ReleaseFreeMemory();
-
- bool finished_idle_work = true;
- if (blink::mainThreadIsolate() &&
- !blink::mainThreadIsolate()->IdleNotification(idle_hint)) {
- finished_idle_work = false;
- }
- if (!base::DiscardableMemory::ReduceMemoryUsage())
- finished_idle_work = false;
-
- // V8 finished collecting garbage and discardable memory system has no
- // more idle work left.
- if (finished_idle_work)
- new_delay_ms = kLongIdleHandlerDelayMs;
- }
- }
- ScheduleIdleHandler(new_delay_ms);
-}
-
int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
return idle_notification_delay_in_ms_;
}
scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories;
- scoped_refptr<base::MessageLoopProxy> media_loop_proxy =
- GetMediaThreadMessageLoopProxy();
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner =
+ GetMediaThreadTaskRunner();
if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
- if (!gpu_va_context_provider_ ||
+ if (!gpu_va_context_provider_.get() ||
gpu_va_context_provider_->DestroyedOnMainThread()) {
- if (!gpu_channel_host) {
+ if (!gpu_channel_host.get()) {
gpu_channel_host = EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
}
"GPU-VideoAccelerator-Offscreen");
}
}
- if (gpu_va_context_provider_) {
+ if (gpu_va_context_provider_.get()) {
gpu_factories = RendererGpuVideoAcceleratorFactories::Create(
- gpu_channel_host, media_loop_proxy, gpu_va_context_provider_);
+ gpu_channel_host.get(), media_task_runner, gpu_va_context_provider_);
}
return gpu_factories;
}
scoped_refptr<webkit::gpu::ContextProviderWebContext>
RenderThreadImpl::SharedMainThreadContextProvider() {
DCHECK(IsMainThread());
- if (!shared_main_thread_contexts_ ||
+ if (!shared_main_thread_contexts_.get() ||
shared_main_thread_contexts_->DestroyedOnMainThread()) {
shared_main_thread_contexts_ = NULL;
#if defined(OS_ANDROID)
GetOffscreenAttribs(), "Offscreen-MainThread");
}
#endif
- if (!shared_main_thread_contexts_) {
+ if (!shared_main_thread_contexts_.get()) {
shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
CreateOffscreenContext3d(), "Offscreen-MainThread");
}
+ if (shared_main_thread_contexts_.get() &&
+ !shared_main_thread_contexts_->BindToCurrentThread())
+ shared_main_thread_contexts_ = NULL;
}
- if (shared_main_thread_contexts_ &&
- !shared_main_thread_contexts_->BindToCurrentThread())
- shared_main_thread_contexts_ = NULL;
return shared_main_thread_contexts_;
}
size_t height,
unsigned internalformat,
unsigned usage) {
+ TRACE_EVENT0("renderer", "RenderThreadImpl::AllocateGpuMemoryBuffer");
+
DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread());
if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
if (!success)
return scoped_ptr<gfx::GpuMemoryBuffer>();
- return GpuMemoryBufferImpl::CreateFromHandle(
- handle, gfx::Size(width, height), internalformat)
- .PassAs<gfx::GpuMemoryBuffer>();
-}
-
-void RenderThreadImpl::DeleteGpuMemoryBuffer(
- scoped_ptr<gfx::GpuMemoryBuffer> buffer) {
- gfx::GpuMemoryBufferHandle handle(buffer->GetHandle());
-
- IPC::Message* message = new ChildProcessHostMsg_DeletedGpuMemoryBuffer(
- handle.type, handle.global_id);
+ scoped_ptr<GpuMemoryBufferImpl> buffer(GpuMemoryBufferImpl::CreateFromHandle(
+ handle,
+ gfx::Size(width, height),
+ internalformat,
+ base::Bind(&DeletedGpuMemoryBuffer,
+ make_scoped_refptr(thread_safe_sender()),
+ handle.type,
+ handle.global_id)));
+ if (!buffer) {
+ thread_safe_sender()->Send(new ChildProcessHostMsg_DeletedGpuMemoryBuffer(
+ handle.type, handle.global_id));
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+ }
- // Allow calling this from the compositor thread.
- thread_safe_sender()->Send(message);
+ return buffer.PassAs<gfx::GpuMemoryBuffer>();
}
void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
// TODO(port): removed from render_messages_internal.h;
// is there a new non-windows message I should add here?
IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
- IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
IPC_MESSAGE_HANDLER(ViewMsg_NetworkTypeChanged, OnNetworkTypeChanged)
IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData)
IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateNewSharedWorker)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
#endif
+#if defined(ENABLE_PLUGINS)
+ IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
return gpu_channel_.get();
}
+#if defined(ENABLE_PLUGINS)
void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
EnsureWebKitInitialized();
// The call below will cause a GetPlugins call with refresh=true, but at this
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
}
+#endif
void RenderThreadImpl::OnNetworkTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) {
return file_thread_->message_loop_proxy();
}
-scoped_refptr<base::MessageLoopProxy>
-RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
+scoped_refptr<base::SingleThreadTaskRunner>
+RenderThreadImpl::GetMediaThreadTaskRunner() {
DCHECK(message_loop() == base::MessageLoop::current());
if (!media_thread_) {
media_thread_.reset(new base::Thread("Media"));
return media_thread_->message_loop_proxy();
}
-void RenderThreadImpl::SetFlingCurveParameters(
- const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen) {
- webkit_platform_support_->SetFlingCurveParameters(new_touchpad,
- new_touchscreen);
-
-}
-
void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
- gamepad_shared_memory_reader_->SampleGamepads(*data);
-}
-
-void RenderThreadImpl::SetGamepadListener(blink::WebGamepadListener* listener) {
- gamepad_shared_memory_reader_->SetGamepadListener(listener);
+ webkit_platform_support_->sampleGamepads(*data);
}
void RenderThreadImpl::WidgetCreated() {