render_widget_compositor.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/renderer/gpu/render_widget_compositor.h" 6 7#include <limits> 8#include <string> 9 10#include "base/command_line.h" 11#include "base/logging.h" 12#include "base/strings/string_number_conversions.h" 13#include "base/synchronization/lock.h" 14#include "base/time/time.h" 15#include "cc/base/switches.h" 16#include "cc/debug/layer_tree_debug_state.h" 17#include "cc/layers/layer.h" 18#include "cc/trees/layer_tree_host.h" 19#include "content/common/gpu/client/context_provider_command_buffer.h" 20#include "content/public/common/content_switches.h" 21#include "content/renderer/gpu/input_handler_manager.h" 22#include "content/renderer/render_thread_impl.h" 23#include "third_party/WebKit/public/platform/WebSize.h" 24#include "third_party/WebKit/public/web/WebWidget.h" 25#include "ui/gl/gl_switches.h" 26#include "webkit/renderer/compositor_bindings/web_layer_impl.h" 27 28namespace cc { 29class Layer; 30} 31 32using WebKit::WebFloatPoint; 33using WebKit::WebSize; 34using WebKit::WebRect; 35 36namespace content { 37namespace { 38 39bool GetSwitchValueAsInt( 40 const CommandLine& command_line, 41 const std::string& switch_string, 42 int min_value, 43 int max_value, 44 int* result) { 45 std::string string_value = command_line.GetSwitchValueASCII(switch_string); 46 int int_value; 47 if (base::StringToInt(string_value, &int_value) && 48 int_value >= min_value && int_value <= max_value) { 49 *result = int_value; 50 return true; 51 } else { 52 LOG(WARNING) << "Failed to parse switch " << switch_string << ": " << 53 string_value; 54 return false; 55 } 56} 57 58bool GetSwitchValueAsFloat( 59 const CommandLine& command_line, 60 const std::string& switch_string, 61 float min_value, 62 float max_value, 63 float* result) { 64 std::string string_value = command_line.GetSwitchValueASCII(switch_string); 65 double double_value; 66 if (base::StringToDouble(string_value, &double_value) && 67 double_value >= min_value && double_value <= max_value) { 68 *result = static_cast<float>(double_value); 69 return true; 70 } else { 71 LOG(WARNING) << "Failed to parse switch " << switch_string << ": " << 72 string_value; 73 return false; 74 } 75} 76 77 78} // namespace 79 80// static 81scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( 82 RenderWidget* widget, 83 bool threaded) { 84 scoped_ptr<RenderWidgetCompositor> compositor( 85 new RenderWidgetCompositor(widget, threaded)); 86 87 CommandLine* cmd = CommandLine::ForCurrentProcess(); 88 89 cc::LayerTreeSettings settings; 90 91 // For web contents, layer transforms should scale up the contents of layers 92 // to keep content always crisp when possible. 93 settings.layer_transforms_should_scale_layer_contents = true; 94 95 settings.throttle_frame_production = 96 !cmd->HasSwitch(switches::kDisableGpuVsync); 97 settings.begin_frame_scheduling_enabled = 98 cmd->HasSwitch(switches::kEnableBeginFrameScheduling); 99 settings.using_synchronous_renderer_compositor = 100 widget->UsingSynchronousRendererCompositor(); 101 settings.per_tile_painting_enabled = 102 cmd->HasSwitch(cc::switches::kEnablePerTilePainting); 103 settings.accelerated_animation_enabled = 104 !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation); 105 settings.force_direct_layer_drawing = 106 cmd->HasSwitch(cc::switches::kForceDirectLayerDrawing); 107 108 int default_tile_width = settings.default_tile_size.width(); 109 if (cmd->HasSwitch(switches::kDefaultTileWidth)) { 110 GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1, 111 std::numeric_limits<int>::max(), &default_tile_width); 112 } 113 int default_tile_height = settings.default_tile_size.height(); 114 if (cmd->HasSwitch(switches::kDefaultTileHeight)) { 115 GetSwitchValueAsInt(*cmd, switches::kDefaultTileHeight, 1, 116 std::numeric_limits<int>::max(), &default_tile_height); 117 } 118 settings.default_tile_size = gfx::Size(default_tile_width, 119 default_tile_height); 120 121 int max_untiled_layer_width = settings.max_untiled_layer_size.width(); 122 if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) { 123 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1, 124 std::numeric_limits<int>::max(), 125 &max_untiled_layer_width); 126 } 127 int max_untiled_layer_height = settings.max_untiled_layer_size.height(); 128 if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) { 129 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1, 130 std::numeric_limits<int>::max(), 131 &max_untiled_layer_height); 132 } 133 134 settings.max_untiled_layer_size = gfx::Size(max_untiled_layer_width, 135 max_untiled_layer_height); 136 137 settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled(); 138 139 settings.calculate_top_controls_position = 140 cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation); 141 if (cmd->HasSwitch(cc::switches::kTopControlsHeight)) { 142 std::string controls_height_str = 143 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHeight); 144 double controls_height; 145 if (base::StringToDouble(controls_height_str, &controls_height) && 146 controls_height > 0) 147 settings.top_controls_height = controls_height; 148 } 149 150 if (settings.calculate_top_controls_position && 151 settings.top_controls_height <= 0) { 152 DCHECK(false) 153 << "Top controls repositioning enabled without valid height set."; 154 settings.calculate_top_controls_position = false; 155 } 156 157 if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) { 158 std::string top_threshold_str = 159 cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold); 160 double show_threshold; 161 if (base::StringToDouble(top_threshold_str, &show_threshold) && 162 show_threshold >= 0.f && show_threshold <= 1.f) 163 settings.top_controls_show_threshold = show_threshold; 164 } 165 166 if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) { 167 std::string top_threshold_str = 168 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold); 169 double hide_threshold; 170 if (base::StringToDouble(top_threshold_str, &hide_threshold) && 171 hide_threshold >= 0.f && hide_threshold <= 1.f) 172 settings.top_controls_hide_threshold = hide_threshold; 173 } 174 175 settings.partial_swap_enabled = widget->AllowPartialSwap() && 176 cmd->HasSwitch(cc::switches::kEnablePartialSwap); 177 settings.background_color_instead_of_checkerboard = 178 cmd->HasSwitch(cc::switches::kBackgroundColorInsteadOfCheckerboard); 179 settings.show_overdraw_in_tracing = 180 cmd->HasSwitch(cc::switches::kTraceOverdraw); 181 settings.use_pinch_virtual_viewport = 182 cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport); 183 settings.allow_antialiasing &= 184 !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); 185 186 // These flags should be mirrored by UI versions in ui/compositor/. 187 settings.initial_debug_state.show_debug_borders = 188 cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders); 189 settings.initial_debug_state.show_fps_counter = 190 cmd->HasSwitch(cc::switches::kShowFPSCounter); 191 settings.initial_debug_state.show_paint_rects = 192 cmd->HasSwitch(switches::kShowPaintRects); 193 settings.initial_debug_state.show_property_changed_rects = 194 cmd->HasSwitch(cc::switches::kShowPropertyChangedRects); 195 settings.initial_debug_state.show_surface_damage_rects = 196 cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects); 197 settings.initial_debug_state.show_screen_space_rects = 198 cmd->HasSwitch(cc::switches::kShowScreenSpaceRects); 199 settings.initial_debug_state.show_replica_screen_space_rects = 200 cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects); 201 settings.initial_debug_state.show_occluding_rects = 202 cmd->HasSwitch(cc::switches::kShowOccludingRects); 203 settings.initial_debug_state.show_non_occluding_rects = 204 cmd->HasSwitch(cc::switches::kShowNonOccludingRects); 205 206 settings.initial_debug_state.SetRecordRenderingStats( 207 cmd->HasSwitch(switches::kEnableGpuBenchmarking)); 208 209 if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) { 210 const int kMinSlowDownScaleFactor = 0; 211 const int kMaxSlowDownScaleFactor = INT_MAX; 212 GetSwitchValueAsInt( 213 *cmd, 214 cc::switches::kSlowDownRasterScaleFactor, 215 kMinSlowDownScaleFactor, 216 kMaxSlowDownScaleFactor, 217 &settings.initial_debug_state.slow_down_raster_scale_factor); 218 } 219 220 if (cmd->HasSwitch(cc::switches::kNumRasterThreads)) { 221 const int kMinRasterThreads = 1; 222 const int kMaxRasterThreads = 64; 223 int num_raster_threads; 224 if (GetSwitchValueAsInt(*cmd, cc::switches::kNumRasterThreads, 225 kMinRasterThreads, kMaxRasterThreads, 226 &num_raster_threads)) 227 settings.num_raster_threads = num_raster_threads; 228 } 229 230 if (cmd->HasSwitch(cc::switches::kLowResolutionContentsScaleFactor)) { 231 const int kMinScaleFactor = settings.minimum_contents_scale; 232 const int kMaxScaleFactor = 1; 233 GetSwitchValueAsFloat(*cmd, 234 cc::switches::kLowResolutionContentsScaleFactor, 235 kMinScaleFactor, kMaxScaleFactor, 236 &settings.low_res_contents_scale_factor); 237 } 238 239 if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) { 240 int max_tiles_for_interest_area; 241 if (GetSwitchValueAsInt(*cmd, 242 cc::switches::kMaxTilesForInterestArea, 243 1, std::numeric_limits<int>::max(), 244 &max_tiles_for_interest_area)) 245 settings.max_tiles_for_interest_area = max_tiles_for_interest_area; 246 } 247 248 if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) { 249 int max_unused_resource_memory_percentage; 250 if (GetSwitchValueAsInt( 251 *cmd, 252 cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 253 0, 100, 254 &max_unused_resource_memory_percentage)) { 255 settings.max_unused_resource_memory_percentage = 256 max_unused_resource_memory_percentage; 257 } 258 } 259 260 settings.strict_layer_property_change_checking = 261 cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking); 262 263 settings.use_map_image = cmd->HasSwitch(cc::switches::kUseMapImage); 264 265#if defined(OS_ANDROID) 266 // TODO(danakj): Move these to the android code. 267 settings.can_use_lcd_text = false; 268 settings.max_partial_texture_updates = 0; 269 settings.use_linear_fade_scrollbar_animator = true; 270 settings.solid_color_scrollbars = true; 271 settings.solid_color_scrollbar_color = 272 cmd->HasSwitch(switches::kHideScrollbars) 273 ? SK_ColorTRANSPARENT 274 : SkColorSetARGB(128, 128, 128, 128); 275 settings.solid_color_scrollbar_thickness_dip = 3; 276 settings.highp_threshold_min = 2048; 277 // Android WebView handles root layer flings itself. 278 settings.ignore_root_layer_flings = 279 widget->UsingSynchronousRendererCompositor(); 280#elif !defined(OS_MACOSX) 281 if (cmd->HasSwitch(switches::kEnableOverlayScrollbars)) { 282 settings.use_linear_fade_scrollbar_animator = true; 283 settings.solid_color_scrollbars = true; 284 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128); 285 settings.solid_color_scrollbar_thickness_dip = 3; 286 } 287#endif 288 289 if (!compositor->initialize(settings)) 290 return scoped_ptr<RenderWidgetCompositor>(); 291 292 return compositor.Pass(); 293} 294 295RenderWidgetCompositor::RenderWidgetCompositor(RenderWidget* widget, 296 bool threaded) 297 : threaded_(threaded), 298 suppress_schedule_composite_(false), 299 widget_(widget) { 300} 301 302RenderWidgetCompositor::~RenderWidgetCompositor() {} 303 304const base::WeakPtr<cc::InputHandler>& 305RenderWidgetCompositor::GetInputHandler() { 306 return layer_tree_host_->GetInputHandler(); 307} 308 309void RenderWidgetCompositor::SetSuppressScheduleComposite(bool suppress) { 310 if (suppress_schedule_composite_ == suppress) 311 return; 312 313 if (suppress) 314 TRACE_EVENT_ASYNC_BEGIN0("gpu", 315 "RenderWidgetCompositor::SetSuppressScheduleComposite", this); 316 else 317 TRACE_EVENT_ASYNC_END0("gpu", 318 "RenderWidgetCompositor::SetSuppressScheduleComposite", this); 319 suppress_schedule_composite_ = suppress; 320} 321 322void RenderWidgetCompositor::Animate(base::TimeTicks time) { 323 layer_tree_host_->UpdateClientAnimations(time); 324} 325 326void RenderWidgetCompositor::Composite(base::TimeTicks frame_begin_time) { 327 layer_tree_host_->Composite(frame_begin_time); 328} 329 330void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() { 331 layer_tree_host_->SetNeedsDisplayOnAllLayers(); 332} 333 334void RenderWidgetCompositor::SetRasterizeOnlyVisibleContent() { 335 cc::LayerTreeDebugState current = layer_tree_host_->debug_state(); 336 current.rasterize_only_visible_content = true; 337 layer_tree_host_->SetDebugState(current); 338} 339 340void RenderWidgetCompositor::GetRenderingStats(cc::RenderingStats* stats) { 341 layer_tree_host_->CollectRenderingStats(stats); 342} 343 344void RenderWidgetCompositor::UpdateTopControlsState( 345 cc::TopControlsState constraints, 346 cc::TopControlsState current, 347 bool animate) { 348 layer_tree_host_->UpdateTopControlsState(constraints, 349 current, 350 animate); 351} 352 353void RenderWidgetCompositor::SetOverdrawBottomHeight( 354 float overdraw_bottom_height) { 355 layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height); 356} 357 358void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) { 359 layer_tree_host_->SetNeedsRedrawRect(damage_rect); 360} 361 362void RenderWidgetCompositor::SetLatencyInfo( 363 const ui::LatencyInfo& latency_info) { 364 layer_tree_host_->SetLatencyInfo(latency_info); 365} 366 367int RenderWidgetCompositor::GetLayerTreeId() const { 368 return layer_tree_host_->id(); 369} 370 371void RenderWidgetCompositor::NotifyInputThrottledUntilCommit() { 372 layer_tree_host_->NotifyInputThrottledUntilCommit(); 373} 374 375const cc::Layer* RenderWidgetCompositor::GetRootLayer() const { 376 return layer_tree_host_->root_layer(); 377} 378 379bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) { 380 scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy = 381 RenderThreadImpl::current()->compositor_message_loop_proxy(); 382 layer_tree_host_ = cc::LayerTreeHost::Create(this, 383 settings, 384 compositor_message_loop_proxy); 385 return layer_tree_host_; 386} 387 388void RenderWidgetCompositor::setSurfaceReady() { 389 layer_tree_host_->SetLayerTreeHostClientReady(); 390} 391 392void RenderWidgetCompositor::setRootLayer(const WebKit::WebLayer& layer) { 393 layer_tree_host_->SetRootLayer( 394 static_cast<const webkit::WebLayerImpl*>(&layer)->layer()); 395} 396 397void RenderWidgetCompositor::clearRootLayer() { 398 layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>()); 399} 400 401void RenderWidgetCompositor::setViewportSize( 402 const WebSize&, 403 const WebSize& device_viewport_size) { 404 layer_tree_host_->SetViewportSize(device_viewport_size); 405} 406 407WebSize RenderWidgetCompositor::layoutViewportSize() const { 408 return layer_tree_host_->device_viewport_size(); 409} 410 411WebSize RenderWidgetCompositor::deviceViewportSize() const { 412 return layer_tree_host_->device_viewport_size(); 413} 414 415WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom( 416 const WebFloatPoint& point) const { 417 return point; 418} 419 420void RenderWidgetCompositor::setDeviceScaleFactor(float device_scale) { 421 layer_tree_host_->SetDeviceScaleFactor(device_scale); 422} 423 424float RenderWidgetCompositor::deviceScaleFactor() const { 425 return layer_tree_host_->device_scale_factor(); 426} 427 428void RenderWidgetCompositor::setBackgroundColor(WebKit::WebColor color) { 429 layer_tree_host_->set_background_color(color); 430} 431 432void RenderWidgetCompositor::setHasTransparentBackground(bool transparent) { 433 layer_tree_host_->set_has_transparent_background(transparent); 434} 435 436void RenderWidgetCompositor::setVisible(bool visible) { 437 layer_tree_host_->SetVisible(visible); 438} 439 440void RenderWidgetCompositor::setPageScaleFactorAndLimits( 441 float page_scale_factor, float minimum, float maximum) { 442 layer_tree_host_->SetPageScaleFactorAndLimits( 443 page_scale_factor, minimum, maximum); 444} 445 446void RenderWidgetCompositor::startPageScaleAnimation( 447 const WebKit::WebPoint& destination, 448 bool use_anchor, 449 float new_page_scale, 450 double duration_sec) { 451 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( 452 duration_sec * base::Time::kMicrosecondsPerSecond); 453 layer_tree_host_->StartPageScaleAnimation( 454 gfx::Vector2d(destination.x, destination.y), 455 use_anchor, 456 new_page_scale, 457 duration); 458} 459 460void RenderWidgetCompositor::setNeedsAnimate() { 461 layer_tree_host_->SetNeedsAnimate(); 462} 463 464void RenderWidgetCompositor::setNeedsRedraw() { 465 if (threaded_) 466 layer_tree_host_->SetNeedsAnimate(); 467 else 468 widget_->scheduleAnimation(); 469} 470 471bool RenderWidgetCompositor::commitRequested() const { 472 return layer_tree_host_->CommitRequested(); 473} 474 475void RenderWidgetCompositor::didStopFlinging() { 476 layer_tree_host_->DidStopFlinging(); 477} 478 479void RenderWidgetCompositor::registerForAnimations(WebKit::WebLayer* layer) { 480 cc::Layer* cc_layer = static_cast<webkit::WebLayerImpl*>(layer)->layer(); 481 cc_layer->layer_animation_controller()->SetAnimationRegistrar( 482 layer_tree_host_->animation_registrar()); 483} 484 485bool RenderWidgetCompositor::compositeAndReadback( 486 void *pixels, const WebRect& rect_in_device_viewport) { 487 return layer_tree_host_->CompositeAndReadback(pixels, 488 rect_in_device_viewport); 489} 490 491void RenderWidgetCompositor::finishAllRendering() { 492 layer_tree_host_->FinishAllRendering(); 493} 494 495void RenderWidgetCompositor::setDeferCommits(bool defer_commits) { 496 layer_tree_host_->SetDeferCommits(defer_commits); 497} 498 499void RenderWidgetCompositor::setShowFPSCounter(bool show) { 500 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 501 debug_state.show_fps_counter = show; 502 layer_tree_host_->SetDebugState(debug_state); 503} 504 505void RenderWidgetCompositor::setShowPaintRects(bool show) { 506 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 507 debug_state.show_paint_rects = show; 508 layer_tree_host_->SetDebugState(debug_state); 509} 510 511void RenderWidgetCompositor::setShowDebugBorders(bool show) { 512 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 513 debug_state.show_debug_borders = show; 514 layer_tree_host_->SetDebugState(debug_state); 515} 516 517void RenderWidgetCompositor::setContinuousPaintingEnabled(bool enabled) { 518 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 519 debug_state.continuous_painting = enabled; 520 layer_tree_host_->SetDebugState(debug_state); 521} 522 523void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) { 524 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 525 debug_state.show_touch_event_handler_rects = show; 526 debug_state.show_wheel_event_handler_rects = show; 527 debug_state.show_non_fast_scrollable_rects = show; 528 layer_tree_host_->SetDebugState(debug_state); 529} 530 531void RenderWidgetCompositor::WillBeginFrame() { 532 widget_->InstrumentWillBeginFrame(); 533 widget_->willBeginCompositorFrame(); 534} 535 536void RenderWidgetCompositor::DidBeginFrame() { 537 widget_->InstrumentDidBeginFrame(); 538} 539 540void RenderWidgetCompositor::Animate(double frame_begin_time) { 541 widget_->webwidget()->animate(frame_begin_time); 542} 543 544void RenderWidgetCompositor::Layout() { 545 widget_->webwidget()->layout(); 546} 547 548void RenderWidgetCompositor::ApplyScrollAndScale(gfx::Vector2d scroll_delta, 549 float page_scale) { 550 widget_->webwidget()->applyScrollAndScale(scroll_delta, page_scale); 551} 552 553scoped_ptr<cc::OutputSurface> RenderWidgetCompositor::CreateOutputSurface( 554 bool fallback) { 555 return widget_->CreateOutputSurface(fallback); 556} 557 558void RenderWidgetCompositor::DidInitializeOutputSurface(bool success) { 559 if (!success) 560 widget_->webwidget()->didExitCompositingMode(); 561} 562 563void RenderWidgetCompositor::WillCommit() { 564 widget_->InstrumentWillComposite(); 565} 566 567void RenderWidgetCompositor::DidCommit() { 568 widget_->DidCommitCompositorFrame(); 569 widget_->didBecomeReadyForAdditionalInput(); 570} 571 572void RenderWidgetCompositor::DidCommitAndDrawFrame() { 573 widget_->didCommitAndDrawCompositorFrame(); 574} 575 576void RenderWidgetCompositor::DidCompleteSwapBuffers() { 577 widget_->didCompleteSwapBuffers(); 578} 579 580void RenderWidgetCompositor::ScheduleComposite() { 581 if (!suppress_schedule_composite_) 582 widget_->scheduleComposite(); 583} 584 585scoped_refptr<cc::ContextProvider> 586RenderWidgetCompositor::OffscreenContextProviderForMainThread() { 587 return RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); 588} 589 590scoped_refptr<cc::ContextProvider> 591RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() { 592 return RenderThreadImpl::current()-> 593 OffscreenContextProviderForCompositorThread(); 594} 595 596} // namespace content 597