render_widget_compositor.cc revision a3f7b4e666c476898878fa745f637129375cd889
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 // Android WebView does not support forced draw and this is to prevent 109 // crashes. Adding support for forced draw is tracked in crbug.com/250909. 110 settings.timeout_and_draw_when_animation_checkerboards = 111 !widget->UsingSynchronousRendererCompositor(); 112 113 int default_tile_width = settings.default_tile_size.width(); 114 if (cmd->HasSwitch(switches::kDefaultTileWidth)) { 115 GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1, 116 std::numeric_limits<int>::max(), &default_tile_width); 117 } 118 int default_tile_height = settings.default_tile_size.height(); 119 if (cmd->HasSwitch(switches::kDefaultTileHeight)) { 120 GetSwitchValueAsInt(*cmd, switches::kDefaultTileHeight, 1, 121 std::numeric_limits<int>::max(), &default_tile_height); 122 } 123 settings.default_tile_size = gfx::Size(default_tile_width, 124 default_tile_height); 125 126 int max_untiled_layer_width = settings.max_untiled_layer_size.width(); 127 if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) { 128 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1, 129 std::numeric_limits<int>::max(), 130 &max_untiled_layer_width); 131 } 132 int max_untiled_layer_height = settings.max_untiled_layer_size.height(); 133 if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) { 134 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1, 135 std::numeric_limits<int>::max(), 136 &max_untiled_layer_height); 137 } 138 139 settings.max_untiled_layer_size = gfx::Size(max_untiled_layer_width, 140 max_untiled_layer_height); 141 142 settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled(); 143 144 settings.calculate_top_controls_position = 145 cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation); 146 if (cmd->HasSwitch(cc::switches::kTopControlsHeight)) { 147 std::string controls_height_str = 148 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHeight); 149 double controls_height; 150 if (base::StringToDouble(controls_height_str, &controls_height) && 151 controls_height > 0) 152 settings.top_controls_height = controls_height; 153 } 154 155 if (settings.calculate_top_controls_position && 156 settings.top_controls_height <= 0) { 157 DCHECK(false) 158 << "Top controls repositioning enabled without valid height set."; 159 settings.calculate_top_controls_position = false; 160 } 161 162 if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) { 163 std::string top_threshold_str = 164 cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold); 165 double show_threshold; 166 if (base::StringToDouble(top_threshold_str, &show_threshold) && 167 show_threshold >= 0.f && show_threshold <= 1.f) 168 settings.top_controls_show_threshold = show_threshold; 169 } 170 171 if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) { 172 std::string top_threshold_str = 173 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold); 174 double hide_threshold; 175 if (base::StringToDouble(top_threshold_str, &hide_threshold) && 176 hide_threshold >= 0.f && hide_threshold <= 1.f) 177 settings.top_controls_hide_threshold = hide_threshold; 178 } 179 180 settings.partial_swap_enabled = widget->AllowPartialSwap() && 181 cmd->HasSwitch(cc::switches::kEnablePartialSwap); 182 settings.background_color_instead_of_checkerboard = 183 cmd->HasSwitch(cc::switches::kBackgroundColorInsteadOfCheckerboard); 184 settings.show_overdraw_in_tracing = 185 cmd->HasSwitch(cc::switches::kTraceOverdraw); 186 settings.use_pinch_virtual_viewport = 187 cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport); 188 settings.allow_antialiasing &= 189 !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); 190 191 // These flags should be mirrored by UI versions in ui/compositor/. 192 settings.initial_debug_state.show_debug_borders = 193 cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders); 194 settings.initial_debug_state.show_fps_counter = 195 cmd->HasSwitch(cc::switches::kShowFPSCounter); 196 settings.initial_debug_state.show_paint_rects = 197 cmd->HasSwitch(switches::kShowPaintRects); 198 settings.initial_debug_state.show_property_changed_rects = 199 cmd->HasSwitch(cc::switches::kShowPropertyChangedRects); 200 settings.initial_debug_state.show_surface_damage_rects = 201 cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects); 202 settings.initial_debug_state.show_screen_space_rects = 203 cmd->HasSwitch(cc::switches::kShowScreenSpaceRects); 204 settings.initial_debug_state.show_replica_screen_space_rects = 205 cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects); 206 settings.initial_debug_state.show_occluding_rects = 207 cmd->HasSwitch(cc::switches::kShowOccludingRects); 208 settings.initial_debug_state.show_non_occluding_rects = 209 cmd->HasSwitch(cc::switches::kShowNonOccludingRects); 210 211 settings.initial_debug_state.SetRecordRenderingStats( 212 cmd->HasSwitch(switches::kEnableGpuBenchmarking)); 213 214 if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) { 215 const int kMinSlowDownScaleFactor = 0; 216 const int kMaxSlowDownScaleFactor = INT_MAX; 217 GetSwitchValueAsInt( 218 *cmd, 219 cc::switches::kSlowDownRasterScaleFactor, 220 kMinSlowDownScaleFactor, 221 kMaxSlowDownScaleFactor, 222 &settings.initial_debug_state.slow_down_raster_scale_factor); 223 } 224 225 if (cmd->HasSwitch(cc::switches::kNumRasterThreads)) { 226 const int kMinRasterThreads = 1; 227 const int kMaxRasterThreads = 64; 228 int num_raster_threads; 229 if (GetSwitchValueAsInt(*cmd, cc::switches::kNumRasterThreads, 230 kMinRasterThreads, kMaxRasterThreads, 231 &num_raster_threads)) 232 settings.num_raster_threads = num_raster_threads; 233 } 234 235 if (cmd->HasSwitch(cc::switches::kLowResolutionContentsScaleFactor)) { 236 const int kMinScaleFactor = settings.minimum_contents_scale; 237 const int kMaxScaleFactor = 1; 238 GetSwitchValueAsFloat(*cmd, 239 cc::switches::kLowResolutionContentsScaleFactor, 240 kMinScaleFactor, kMaxScaleFactor, 241 &settings.low_res_contents_scale_factor); 242 } 243 244 if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) { 245 int max_tiles_for_interest_area; 246 if (GetSwitchValueAsInt(*cmd, 247 cc::switches::kMaxTilesForInterestArea, 248 1, std::numeric_limits<int>::max(), 249 &max_tiles_for_interest_area)) 250 settings.max_tiles_for_interest_area = max_tiles_for_interest_area; 251 } 252 253 if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) { 254 int max_unused_resource_memory_percentage; 255 if (GetSwitchValueAsInt( 256 *cmd, 257 cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 258 0, 100, 259 &max_unused_resource_memory_percentage)) { 260 settings.max_unused_resource_memory_percentage = 261 max_unused_resource_memory_percentage; 262 } 263 } 264 265 settings.strict_layer_property_change_checking = 266 cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking); 267 268 settings.use_map_image = cmd->HasSwitch(cc::switches::kUseMapImage); 269 270#if defined(OS_ANDROID) 271 // TODO(danakj): Move these to the android code. 272 settings.can_use_lcd_text = false; 273 settings.max_partial_texture_updates = 0; 274 settings.use_linear_fade_scrollbar_animator = true; 275 settings.solid_color_scrollbars = true; 276 settings.solid_color_scrollbar_color = 277 cmd->HasSwitch(switches::kHideScrollbars) 278 ? SK_ColorTRANSPARENT 279 : SkColorSetARGB(128, 128, 128, 128); 280 settings.solid_color_scrollbar_thickness_dip = 3; 281 settings.highp_threshold_min = 2048; 282#endif 283 284 if (!compositor->initialize(settings)) 285 return scoped_ptr<RenderWidgetCompositor>(); 286 287 return compositor.Pass(); 288} 289 290RenderWidgetCompositor::RenderWidgetCompositor(RenderWidget* widget, 291 bool threaded) 292 : threaded_(threaded), 293 suppress_schedule_composite_(false), 294 widget_(widget) { 295} 296 297RenderWidgetCompositor::~RenderWidgetCompositor() {} 298 299const base::WeakPtr<cc::InputHandler>& 300RenderWidgetCompositor::GetInputHandler() { 301 return layer_tree_host_->GetInputHandler(); 302} 303 304void RenderWidgetCompositor::SetSuppressScheduleComposite(bool suppress) { 305 if (suppress_schedule_composite_ == suppress) 306 return; 307 308 if (suppress) 309 TRACE_EVENT_ASYNC_BEGIN0("gpu", 310 "RenderWidgetCompositor::SetSuppressScheduleComposite", this); 311 else 312 TRACE_EVENT_ASYNC_END0("gpu", 313 "RenderWidgetCompositor::SetSuppressScheduleComposite", this); 314 suppress_schedule_composite_ = suppress; 315} 316 317void RenderWidgetCompositor::Animate(base::TimeTicks time) { 318 layer_tree_host_->UpdateClientAnimations(time); 319} 320 321void RenderWidgetCompositor::Composite(base::TimeTicks frame_begin_time) { 322 layer_tree_host_->Composite(frame_begin_time); 323} 324 325void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() { 326 layer_tree_host_->SetNeedsDisplayOnAllLayers(); 327} 328 329void RenderWidgetCompositor::SetRasterizeOnlyVisibleContent() { 330 cc::LayerTreeDebugState current = layer_tree_host_->debug_state(); 331 current.rasterize_only_visible_content = true; 332 layer_tree_host_->SetDebugState(current); 333} 334 335void RenderWidgetCompositor::GetRenderingStats(cc::RenderingStats* stats) { 336 layer_tree_host_->CollectRenderingStats(stats); 337} 338 339void RenderWidgetCompositor::UpdateTopControlsState( 340 cc::TopControlsState constraints, 341 cc::TopControlsState current, 342 bool animate) { 343 layer_tree_host_->UpdateTopControlsState(constraints, 344 current, 345 animate); 346} 347 348void RenderWidgetCompositor::SetOverdrawBottomHeight( 349 float overdraw_bottom_height) { 350 layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height); 351} 352 353void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) { 354 layer_tree_host_->SetNeedsRedrawRect(damage_rect); 355} 356 357void RenderWidgetCompositor::SetLatencyInfo( 358 const ui::LatencyInfo& latency_info) { 359 layer_tree_host_->SetLatencyInfo(latency_info); 360} 361 362int RenderWidgetCompositor::GetLayerTreeId() const { 363 return layer_tree_host_->id(); 364} 365 366bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) { 367 scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy = 368 RenderThreadImpl::current()->compositor_message_loop_proxy(); 369 layer_tree_host_ = cc::LayerTreeHost::Create(this, 370 settings, 371 compositor_message_loop_proxy); 372 return layer_tree_host_; 373} 374 375void RenderWidgetCompositor::setSurfaceReady() { 376 layer_tree_host_->SetLayerTreeHostClientReady(); 377} 378 379void RenderWidgetCompositor::setRootLayer(const WebKit::WebLayer& layer) { 380 layer_tree_host_->SetRootLayer( 381 static_cast<const webkit::WebLayerImpl*>(&layer)->layer()); 382} 383 384void RenderWidgetCompositor::clearRootLayer() { 385 layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>()); 386} 387 388void RenderWidgetCompositor::setViewportSize( 389 const WebSize&, 390 const WebSize& device_viewport_size) { 391 layer_tree_host_->SetViewportSize(device_viewport_size); 392} 393 394WebSize RenderWidgetCompositor::layoutViewportSize() const { 395 return layer_tree_host_->device_viewport_size(); 396} 397 398WebSize RenderWidgetCompositor::deviceViewportSize() const { 399 return layer_tree_host_->device_viewport_size(); 400} 401 402WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom( 403 const WebFloatPoint& point) const { 404 return point; 405} 406 407void RenderWidgetCompositor::setDeviceScaleFactor(float device_scale) { 408 layer_tree_host_->SetDeviceScaleFactor(device_scale); 409} 410 411float RenderWidgetCompositor::deviceScaleFactor() const { 412 return layer_tree_host_->device_scale_factor(); 413} 414 415void RenderWidgetCompositor::setBackgroundColor(WebKit::WebColor color) { 416 layer_tree_host_->set_background_color(color); 417} 418 419void RenderWidgetCompositor::setHasTransparentBackground(bool transparent) { 420 layer_tree_host_->set_has_transparent_background(transparent); 421} 422 423void RenderWidgetCompositor::setVisible(bool visible) { 424 layer_tree_host_->SetVisible(visible); 425} 426 427void RenderWidgetCompositor::setPageScaleFactorAndLimits( 428 float page_scale_factor, float minimum, float maximum) { 429 layer_tree_host_->SetPageScaleFactorAndLimits( 430 page_scale_factor, minimum, maximum); 431} 432 433void RenderWidgetCompositor::startPageScaleAnimation( 434 const WebKit::WebPoint& destination, 435 bool use_anchor, 436 float new_page_scale, 437 double duration_sec) { 438 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( 439 duration_sec * base::Time::kMicrosecondsPerSecond); 440 layer_tree_host_->StartPageScaleAnimation( 441 gfx::Vector2d(destination.x, destination.y), 442 use_anchor, 443 new_page_scale, 444 duration); 445} 446 447void RenderWidgetCompositor::setNeedsAnimate() { 448 layer_tree_host_->SetNeedsAnimate(); 449} 450 451void RenderWidgetCompositor::setNeedsRedraw() { 452 if (threaded_) 453 layer_tree_host_->SetNeedsAnimate(); 454 else 455 widget_->scheduleAnimation(); 456} 457 458bool RenderWidgetCompositor::commitRequested() const { 459 return layer_tree_host_->CommitRequested(); 460} 461 462void RenderWidgetCompositor::didStopFlinging() { 463 layer_tree_host_->DidStopFlinging(); 464} 465 466void RenderWidgetCompositor::registerForAnimations(WebKit::WebLayer* layer) { 467 cc::Layer* cc_layer = static_cast<webkit::WebLayerImpl*>(layer)->layer(); 468 cc_layer->layer_animation_controller()->SetAnimationRegistrar( 469 layer_tree_host_->animation_registrar()); 470} 471 472bool RenderWidgetCompositor::compositeAndReadback( 473 void *pixels, const WebRect& rect_in_device_viewport) { 474 return layer_tree_host_->CompositeAndReadback(pixels, 475 rect_in_device_viewport); 476} 477 478void RenderWidgetCompositor::finishAllRendering() { 479 layer_tree_host_->FinishAllRendering(); 480} 481 482void RenderWidgetCompositor::setDeferCommits(bool defer_commits) { 483 layer_tree_host_->SetDeferCommits(defer_commits); 484} 485 486void RenderWidgetCompositor::setShowFPSCounter(bool show) { 487 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 488 debug_state.show_fps_counter = show; 489 layer_tree_host_->SetDebugState(debug_state); 490} 491 492void RenderWidgetCompositor::setShowPaintRects(bool show) { 493 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 494 debug_state.show_paint_rects = show; 495 layer_tree_host_->SetDebugState(debug_state); 496} 497 498void RenderWidgetCompositor::setShowDebugBorders(bool show) { 499 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 500 debug_state.show_debug_borders = show; 501 layer_tree_host_->SetDebugState(debug_state); 502} 503 504void RenderWidgetCompositor::setContinuousPaintingEnabled(bool enabled) { 505 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 506 debug_state.continuous_painting = enabled; 507 layer_tree_host_->SetDebugState(debug_state); 508} 509 510void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) { 511 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 512 debug_state.show_touch_event_handler_rects = show; 513 debug_state.show_wheel_event_handler_rects = show; 514 debug_state.show_non_fast_scrollable_rects = show; 515 layer_tree_host_->SetDebugState(debug_state); 516} 517 518void RenderWidgetCompositor::WillBeginFrame() { 519 widget_->InstrumentWillBeginFrame(); 520 widget_->willBeginCompositorFrame(); 521} 522 523void RenderWidgetCompositor::DidBeginFrame() { 524 widget_->InstrumentDidBeginFrame(); 525} 526 527void RenderWidgetCompositor::Animate(double frame_begin_time) { 528 widget_->webwidget()->animate(frame_begin_time); 529} 530 531void RenderWidgetCompositor::Layout() { 532 widget_->webwidget()->layout(); 533} 534 535void RenderWidgetCompositor::ApplyScrollAndScale(gfx::Vector2d scroll_delta, 536 float page_scale) { 537 widget_->webwidget()->applyScrollAndScale(scroll_delta, page_scale); 538} 539 540scoped_ptr<cc::OutputSurface> RenderWidgetCompositor::CreateOutputSurface() { 541 return widget_->CreateOutputSurface(); 542} 543 544void RenderWidgetCompositor::DidInitializeOutputSurface(bool success) { 545 if (!success) 546 widget_->webwidget()->didExitCompositingMode(); 547} 548 549void RenderWidgetCompositor::WillCommit() { 550 widget_->InstrumentWillComposite(); 551} 552 553void RenderWidgetCompositor::DidCommit() { 554 widget_->DidCommitCompositorFrame(); 555 widget_->didBecomeReadyForAdditionalInput(); 556} 557 558void RenderWidgetCompositor::DidCommitAndDrawFrame() { 559 widget_->didCommitAndDrawCompositorFrame(); 560} 561 562void RenderWidgetCompositor::DidCompleteSwapBuffers() { 563 widget_->didCompleteSwapBuffers(); 564} 565 566void RenderWidgetCompositor::ScheduleComposite() { 567 if (!suppress_schedule_composite_) 568 widget_->scheduleComposite(); 569} 570 571scoped_refptr<cc::ContextProvider> 572RenderWidgetCompositor::OffscreenContextProviderForMainThread() { 573 return RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); 574} 575 576scoped_refptr<cc::ContextProvider> 577RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() { 578 return RenderThreadImpl::current()-> 579 OffscreenContextProviderForCompositorThread(); 580} 581 582} // namespace content 583