render_widget_compositor.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/string_number_conversions.h" 13#include "base/synchronization/lock.h" 14#include "base/time.h" 15#include "cc/base/switches.h" 16#include "cc/base/thread_impl.h" 17#include "cc/debug/layer_tree_debug_state.h" 18#include "cc/layers/layer.h" 19#include "cc/trees/layer_tree_host.h" 20#include "content/common/gpu/client/context_provider_command_buffer.h" 21#include "content/public/common/content_switches.h" 22#include "content/renderer/gpu/input_handler_manager.h" 23#include "content/renderer/render_thread_impl.h" 24#include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h" 25#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h" 26#include "ui/gl/gl_switches.h" 27#include "webkit/renderer/compositor_bindings/web_layer_impl.h" 28 29namespace cc { 30class Layer; 31} 32 33using WebKit::WebFloatPoint; 34using WebKit::WebSize; 35using WebKit::WebRect; 36 37namespace content { 38namespace { 39 40bool GetSwitchValueAsInt( 41 const CommandLine& command_line, 42 const std::string& switch_string, 43 int min_value, 44 int max_value, 45 int* result) { 46 std::string string_value = command_line.GetSwitchValueASCII(switch_string); 47 int int_value; 48 if (base::StringToInt(string_value, &int_value) && 49 int_value >= min_value && int_value <= max_value) { 50 *result = int_value; 51 return true; 52 } else { 53 LOG(WARNING) << "Failed to parse switch " << switch_string << ": " << 54 string_value; 55 return false; 56 } 57} 58 59bool GetSwitchValueAsFloat( 60 const CommandLine& command_line, 61 const std::string& switch_string, 62 float min_value, 63 float max_value, 64 float* result) { 65 std::string string_value = command_line.GetSwitchValueASCII(switch_string); 66 double double_value; 67 if (base::StringToDouble(string_value, &double_value) && 68 double_value >= min_value && double_value <= max_value) { 69 *result = static_cast<float>(double_value); 70 return true; 71 } else { 72 LOG(WARNING) << "Failed to parse switch " << switch_string << ": " << 73 string_value; 74 return false; 75 } 76} 77 78 79} // namespace 80 81// static 82scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( 83 RenderWidget* widget) { 84 scoped_ptr<RenderWidgetCompositor> compositor( 85 new RenderWidgetCompositor(widget)); 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.render_parent_drives_begin_frame_ = 98 cmd->HasSwitch(switches::kEnableVsyncNotification); 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.right_aligned_scheduling_enabled = 138 cmd->HasSwitch(cc::switches::kEnableRightAlignedScheduling); 139 settings.impl_side_painting = cc::switches::IsImplSidePaintingEnabled(); 140 settings.use_color_estimator = 141 !cmd->HasSwitch(cc::switches::kDisableColorEstimator); 142 143 settings.calculate_top_controls_position = 144 cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation); 145 if (cmd->HasSwitch(cc::switches::kTopControlsHeight)) { 146 std::string controls_height_str = 147 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHeight); 148 double controls_height; 149 if (base::StringToDouble(controls_height_str, &controls_height) && 150 controls_height > 0) 151 settings.top_controls_height = controls_height; 152 } 153 154 settings.compositor_frame_message = 155 cmd->HasSwitch(cc::switches::kEnableCompositorFrameMessage) || 156 cmd->HasSwitch(cc::switches::kCompositeToMailbox) || 157 cmd->HasSwitch(switches::kEnableSoftwareCompositingGLAdapter); 158 159 if (settings.calculate_top_controls_position && 160 (settings.top_controls_height <= 0 || 161 !settings.compositor_frame_message)) { 162 DCHECK(false) << "Top controls repositioning enabled without valid height " 163 "or compositor_frame_message set."; 164 settings.calculate_top_controls_position = false; 165 } 166 167 if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) { 168 std::string top_threshold_str = 169 cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold); 170 double show_threshold; 171 if (base::StringToDouble(top_threshold_str, &show_threshold) && 172 show_threshold >= 0.f && show_threshold <= 1.f) 173 settings.top_controls_show_threshold = show_threshold; 174 } 175 176 if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) { 177 std::string top_threshold_str = 178 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold); 179 double hide_threshold; 180 if (base::StringToDouble(top_threshold_str, &hide_threshold) && 181 hide_threshold >= 0.f && hide_threshold <= 1.f) 182 settings.top_controls_hide_threshold = hide_threshold; 183 } 184 185 settings.partial_swap_enabled = widget->AllowPartialSwap() && 186 cmd->HasSwitch(cc::switches::kEnablePartialSwap); 187 settings.background_color_instead_of_checkerboard = 188 cmd->HasSwitch(cc::switches::kBackgroundColorInsteadOfCheckerboard); 189 settings.show_overdraw_in_tracing = 190 cmd->HasSwitch(cc::switches::kTraceOverdraw); 191 settings.use_pinch_virtual_viewport = 192 cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport); 193 194 // These flags should be mirrored by UI versions in ui/compositor/. 195 settings.initial_debug_state.show_debug_borders = 196 cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders); 197 settings.initial_debug_state.show_fps_counter = 198 cmd->HasSwitch(cc::switches::kShowFPSCounter); 199 settings.initial_debug_state.show_paint_rects = 200 cmd->HasSwitch(switches::kShowPaintRects); 201 settings.initial_debug_state.show_platform_layer_tree = 202 cmd->HasSwitch(cc::switches::kShowCompositedLayerTree); 203 settings.initial_debug_state.show_property_changed_rects = 204 cmd->HasSwitch(cc::switches::kShowPropertyChangedRects); 205 settings.initial_debug_state.show_surface_damage_rects = 206 cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects); 207 settings.initial_debug_state.show_screen_space_rects = 208 cmd->HasSwitch(cc::switches::kShowScreenSpaceRects); 209 settings.initial_debug_state.show_replica_screen_space_rects = 210 cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects); 211 settings.initial_debug_state.show_occluding_rects = 212 cmd->HasSwitch(cc::switches::kShowOccludingRects); 213 settings.initial_debug_state.show_non_occluding_rects = 214 cmd->HasSwitch(cc::switches::kShowNonOccludingRects); 215 216 settings.initial_debug_state.SetRecordRenderingStats( 217 cmd->HasSwitch(switches::kEnableGpuBenchmarking)); 218 219 if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) { 220 const int kMinSlowDownScaleFactor = 0; 221 const int kMaxSlowDownScaleFactor = INT_MAX; 222 GetSwitchValueAsInt( 223 *cmd, 224 cc::switches::kSlowDownRasterScaleFactor, 225 kMinSlowDownScaleFactor, 226 kMaxSlowDownScaleFactor, 227 &settings.initial_debug_state.slow_down_raster_scale_factor); 228 } 229 230 if (cmd->HasSwitch(cc::switches::kNumRasterThreads)) { 231 const int kMinRasterThreads = 1; 232 const int kMaxRasterThreads = 64; 233 int num_raster_threads; 234 if (GetSwitchValueAsInt(*cmd, cc::switches::kNumRasterThreads, 235 kMinRasterThreads, kMaxRasterThreads, 236 &num_raster_threads)) 237 settings.num_raster_threads = num_raster_threads; 238 } 239 240 if (cmd->HasSwitch(cc::switches::kLowResolutionContentsScaleFactor)) { 241 const int kMinScaleFactor = settings.minimum_contents_scale; 242 const int kMaxScaleFactor = 1; 243 GetSwitchValueAsFloat(*cmd, 244 cc::switches::kLowResolutionContentsScaleFactor, 245 kMinScaleFactor, kMaxScaleFactor, 246 &settings.low_res_contents_scale_factor); 247 } 248 249 if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) { 250 int max_tiles_for_interest_area; 251 if (GetSwitchValueAsInt(*cmd, 252 cc::switches::kMaxTilesForInterestArea, 253 1, std::numeric_limits<int>::max(), 254 &max_tiles_for_interest_area)) 255 settings.max_tiles_for_interest_area = max_tiles_for_interest_area; 256 } 257 258 if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) { 259 int max_unused_resource_memory_percentage; 260 if (GetSwitchValueAsInt( 261 *cmd, 262 cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 263 0, 100, 264 &max_unused_resource_memory_percentage)) { 265 settings.max_unused_resource_memory_percentage = 266 max_unused_resource_memory_percentage; 267 } 268 } 269 270 settings.strict_layer_property_change_checking = 271 cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking); 272 273 settings.use_map_image = cmd->HasSwitch(cc::switches::kUseMapImage); 274 275#if defined(OS_ANDROID) 276 // TODO(danakj): Move these to the android code. 277 settings.can_use_lcd_text = false; 278 settings.max_partial_texture_updates = 0; 279 settings.use_linear_fade_scrollbar_animator = true; 280 settings.solid_color_scrollbars = true; 281 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128); 282 settings.solid_color_scrollbar_thickness_dip = 3; 283 settings.highp_threshold_min = 2048; 284#endif 285 286 if (!compositor->initialize(settings)) 287 return scoped_ptr<RenderWidgetCompositor>(); 288 289 return compositor.Pass(); 290} 291 292RenderWidgetCompositor::RenderWidgetCompositor(RenderWidget* widget) 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 339skia::RefPtr<SkPicture> RenderWidgetCompositor::CapturePicture() { 340 return layer_tree_host_->CapturePicture(); 341} 342 343void RenderWidgetCompositor::UpdateTopControlsState( 344 cc::TopControlsState constraints, 345 cc::TopControlsState current, 346 bool animate) { 347 layer_tree_host_->UpdateTopControlsState(constraints, 348 current, 349 animate); 350} 351 352void RenderWidgetCompositor::SetOverdrawBottomHeight( 353 float overdraw_bottom_height) { 354 layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height); 355} 356 357void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) { 358 layer_tree_host_->SetNeedsRedrawRect(damage_rect); 359} 360 361void RenderWidgetCompositor::SetLatencyInfo( 362 const ui::LatencyInfo& latency_info) { 363 layer_tree_host_->SetLatencyInfo(latency_info); 364} 365 366bool RenderWidgetCompositor::initialize(cc::LayerTreeSettings settings) { 367 scoped_ptr<cc::Thread> impl_thread; 368 scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy = 369 RenderThreadImpl::current()->compositor_message_loop_proxy(); 370 threaded_ = !!compositor_message_loop_proxy; 371 if (threaded_) { 372 impl_thread = cc::ThreadImpl::CreateForDifferentThread( 373 compositor_message_loop_proxy); 374 } 375 layer_tree_host_ = cc::LayerTreeHost::Create(this, 376 settings, 377 impl_thread.Pass()); 378 return layer_tree_host_; 379} 380 381void RenderWidgetCompositor::setSurfaceReady() { 382 layer_tree_host_->SetLayerTreeHostClientReady(); 383} 384 385void RenderWidgetCompositor::setRootLayer(const WebKit::WebLayer& layer) { 386 layer_tree_host_->SetRootLayer( 387 static_cast<const webkit::WebLayerImpl*>(&layer)->layer()); 388} 389 390void RenderWidgetCompositor::clearRootLayer() { 391 layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>()); 392} 393 394void RenderWidgetCompositor::setViewportSize( 395 const WebSize&, 396 const WebSize& device_viewport_size) { 397 layer_tree_host_->SetViewportSize(device_viewport_size); 398} 399 400WebSize RenderWidgetCompositor::layoutViewportSize() const { 401 return layer_tree_host_->device_viewport_size(); 402} 403 404WebSize RenderWidgetCompositor::deviceViewportSize() const { 405 return layer_tree_host_->device_viewport_size(); 406} 407 408WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom( 409 const WebFloatPoint& point) const { 410 return point; 411} 412 413void RenderWidgetCompositor::setDeviceScaleFactor(float device_scale) { 414 layer_tree_host_->SetDeviceScaleFactor(device_scale); 415} 416 417float RenderWidgetCompositor::deviceScaleFactor() const { 418 return layer_tree_host_->device_scale_factor(); 419} 420 421void RenderWidgetCompositor::setBackgroundColor(WebKit::WebColor color) { 422 layer_tree_host_->set_background_color(color); 423} 424 425void RenderWidgetCompositor::setHasTransparentBackground(bool transparent) { 426 layer_tree_host_->set_has_transparent_background(transparent); 427} 428 429void RenderWidgetCompositor::setVisible(bool visible) { 430 layer_tree_host_->SetVisible(visible); 431} 432 433void RenderWidgetCompositor::setPageScaleFactorAndLimits( 434 float page_scale_factor, float minimum, float maximum) { 435 layer_tree_host_->SetPageScaleFactorAndLimits( 436 page_scale_factor, minimum, maximum); 437} 438 439void RenderWidgetCompositor::startPageScaleAnimation( 440 const WebKit::WebPoint& destination, 441 bool use_anchor, 442 float new_page_scale, 443 double duration_sec) { 444 base::TimeDelta duration = base::TimeDelta::FromMicroseconds( 445 duration_sec * base::Time::kMicrosecondsPerSecond); 446 layer_tree_host_->StartPageScaleAnimation( 447 gfx::Vector2d(destination.x, destination.y), 448 use_anchor, 449 new_page_scale, 450 duration); 451} 452 453void RenderWidgetCompositor::setNeedsAnimate() { 454 layer_tree_host_->SetNeedsAnimate(); 455} 456 457void RenderWidgetCompositor::setNeedsRedraw() { 458 if (threaded_) 459 layer_tree_host_->SetNeedsAnimate(); 460 else 461 widget_->scheduleAnimation(); 462} 463 464bool RenderWidgetCompositor::commitRequested() const { 465 return layer_tree_host_->CommitRequested(); 466} 467 468void RenderWidgetCompositor::didStopFlinging() { 469 layer_tree_host_->DidStopFlinging(); 470} 471 472void RenderWidgetCompositor::registerForAnimations(WebKit::WebLayer* layer) { 473 cc::Layer* cc_layer = static_cast<webkit::WebLayerImpl*>(layer)->layer(); 474 cc_layer->layer_animation_controller()->SetAnimationRegistrar( 475 layer_tree_host_->animation_registrar()); 476} 477 478bool RenderWidgetCompositor::compositeAndReadback( 479 void *pixels, const WebRect& rect_in_device_viewport) { 480 return layer_tree_host_->CompositeAndReadback(pixels, 481 rect_in_device_viewport); 482} 483 484void RenderWidgetCompositor::finishAllRendering() { 485 layer_tree_host_->FinishAllRendering(); 486} 487 488void RenderWidgetCompositor::setDeferCommits(bool defer_commits) { 489 layer_tree_host_->SetDeferCommits(defer_commits); 490} 491 492void RenderWidgetCompositor::setShowFPSCounter(bool show) { 493 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 494 debug_state.show_fps_counter = show; 495 layer_tree_host_->SetDebugState(debug_state); 496} 497 498void RenderWidgetCompositor::setShowPaintRects(bool show) { 499 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 500 debug_state.show_paint_rects = show; 501 layer_tree_host_->SetDebugState(debug_state); 502} 503 504void RenderWidgetCompositor::setShowDebugBorders(bool show) { 505 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 506 debug_state.show_debug_borders = show; 507 layer_tree_host_->SetDebugState(debug_state); 508} 509 510void RenderWidgetCompositor::setContinuousPaintingEnabled(bool enabled) { 511 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); 512 debug_state.continuous_painting = enabled; 513 layer_tree_host_->SetDebugState(debug_state); 514} 515 516void RenderWidgetCompositor::WillBeginFrame() { 517 widget_->InstrumentWillBeginFrame(); 518 widget_->willBeginCompositorFrame(); 519} 520 521void RenderWidgetCompositor::DidBeginFrame() { 522 widget_->InstrumentDidBeginFrame(); 523} 524 525void RenderWidgetCompositor::Animate(double frame_begin_time) { 526 widget_->webwidget()->animate(frame_begin_time); 527} 528 529void RenderWidgetCompositor::Layout() { 530 widget_->webwidget()->layout(); 531} 532 533void RenderWidgetCompositor::ApplyScrollAndScale(gfx::Vector2d scroll_delta, 534 float page_scale) { 535 widget_->webwidget()->applyScrollAndScale(scroll_delta, page_scale); 536} 537 538scoped_ptr<cc::OutputSurface> RenderWidgetCompositor::CreateOutputSurface() { 539 return widget_->CreateOutputSurface(); 540} 541 542void RenderWidgetCompositor::DidInitializeOutputSurface(bool success) { 543 if (!success) 544 widget_->webwidget()->didExitCompositingMode(); 545} 546 547void RenderWidgetCompositor::WillCommit() { 548 widget_->InstrumentWillComposite(); 549} 550 551void RenderWidgetCompositor::DidCommit() { 552 widget_->DidCommitCompositorFrame(); 553 widget_->didBecomeReadyForAdditionalInput(); 554} 555 556void RenderWidgetCompositor::DidCommitAndDrawFrame() { 557 widget_->didCommitAndDrawCompositorFrame(); 558} 559 560void RenderWidgetCompositor::DidCompleteSwapBuffers() { 561 widget_->didCompleteSwapBuffers(); 562} 563 564void RenderWidgetCompositor::ScheduleComposite() { 565 if (!suppress_schedule_composite_) 566 widget_->scheduleComposite(); 567} 568 569scoped_refptr<cc::ContextProvider> 570RenderWidgetCompositor::OffscreenContextProviderForMainThread() { 571 return RenderThreadImpl::current()->OffscreenContextProviderForMainThread(); 572} 573 574scoped_refptr<cc::ContextProvider> 575RenderWidgetCompositor::OffscreenContextProviderForCompositorThread() { 576 return RenderThreadImpl::current()-> 577 OffscreenContextProviderForCompositorThread(); 578} 579 580} // namespace content 581