Fix crash in taking a screenshot of a closed popup
[chromium-blink-merge.git] / content / renderer / gpu / render_widget_compositor.cc
blob611ed022694a8a06df51fc62b6d9de1e088097c0
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.
5 #include "content/renderer/gpu/render_widget_compositor.h"
7 #include <limits>
8 #include <string>
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/profiler/scoped_tracker.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/synchronization/lock.h"
15 #include "base/sys_info.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "cc/base/switches.h"
19 #include "cc/blink/web_layer_impl.h"
20 #include "cc/debug/layer_tree_debug_state.h"
21 #include "cc/debug/micro_benchmark.h"
22 #include "cc/input/layer_selection_bound.h"
23 #include "cc/layers/layer.h"
24 #include "cc/output/begin_frame_args.h"
25 #include "cc/output/copy_output_request.h"
26 #include "cc/output/copy_output_result.h"
27 #include "cc/output/latency_info_swap_promise.h"
28 #include "cc/output/swap_promise.h"
29 #include "cc/resources/single_release_callback.h"
30 #include "cc/scheduler/begin_frame_source.h"
31 #include "cc/trees/latency_info_swap_promise_monitor.h"
32 #include "cc/trees/layer_tree_host.h"
33 #include "content/common/content_switches_internal.h"
34 #include "content/common/gpu/client/context_provider_command_buffer.h"
35 #include "content/public/common/content_switches.h"
36 #include "content/renderer/input/input_handler_manager.h"
37 #include "content/renderer/scheduler/renderer_scheduler.h"
38 #include "gpu/command_buffer/client/gles2_interface.h"
39 #include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h"
40 #include "third_party/WebKit/public/platform/WebSelectionBound.h"
41 #include "third_party/WebKit/public/platform/WebSize.h"
42 #include "third_party/WebKit/public/web/WebKit.h"
43 #include "third_party/WebKit/public/web/WebWidget.h"
44 #include "ui/gfx/frame_time.h"
45 #include "ui/gl/gl_switches.h"
46 #include "ui/native_theme/native_theme_switches.h"
48 #if defined(OS_ANDROID)
49 #include "content/renderer/android/synchronous_compositor_factory.h"
50 #include "ui/gfx/android/device_display_info.h"
51 #endif
53 namespace base {
54 class Value;
57 namespace cc {
58 class Layer;
61 using blink::WebBeginFrameArgs;
62 using blink::WebFloatPoint;
63 using blink::WebRect;
64 using blink::WebSelectionBound;
65 using blink::WebSize;
66 using blink::WebTopControlsState;
68 namespace content {
69 namespace {
71 bool GetSwitchValueAsInt(const base::CommandLine& command_line,
72 const std::string& switch_string,
73 int min_value,
74 int max_value,
75 int* result) {
76 std::string string_value = command_line.GetSwitchValueASCII(switch_string);
77 int int_value;
78 if (base::StringToInt(string_value, &int_value) &&
79 int_value >= min_value && int_value <= max_value) {
80 *result = int_value;
81 return true;
82 } else {
83 LOG(WARNING) << "Failed to parse switch " << switch_string << ": " <<
84 string_value;
85 return false;
89 cc::LayerSelectionBound ConvertWebSelectionBound(
90 const WebSelectionBound& web_bound) {
91 DCHECK(web_bound.layerId);
93 cc::LayerSelectionBound cc_bound;
94 switch (web_bound.type) {
95 case blink::WebSelectionBound::Caret:
96 cc_bound.type = cc::SELECTION_BOUND_CENTER;
97 break;
98 case blink::WebSelectionBound::SelectionLeft:
99 cc_bound.type = cc::SELECTION_BOUND_LEFT;
100 break;
101 case blink::WebSelectionBound::SelectionRight:
102 cc_bound.type = cc::SELECTION_BOUND_RIGHT;
103 break;
105 cc_bound.layer_id = web_bound.layerId;
106 cc_bound.edge_top = gfx::Point(web_bound.edgeTopInLayer);
107 cc_bound.edge_bottom = gfx::Point(web_bound.edgeBottomInLayer);
108 return cc_bound;
111 gfx::Size CalculateDefaultTileSize() {
112 int default_tile_size = 256;
113 #if defined(OS_ANDROID)
114 // TODO(epenner): unify this for all platforms if it
115 // makes sense (http://crbug.com/159524)
117 gfx::DeviceDisplayInfo info;
118 bool real_size_supported = true;
119 int display_width = info.GetPhysicalDisplayWidth();
120 int display_height = info.GetPhysicalDisplayHeight();
121 if (display_width == 0 || display_height == 0) {
122 real_size_supported = false;
123 display_width = info.GetDisplayWidth();
124 display_height = info.GetDisplayHeight();
127 int portrait_width = std::min(display_width, display_height);
128 int landscape_width = std::max(display_width, display_height);
130 if (real_size_supported) {
131 // Maximum HD dimensions should be 768x1280
132 // Maximum FHD dimensions should be 1200x1920
133 if (portrait_width > 768 || landscape_width > 1280)
134 default_tile_size = 384;
135 if (portrait_width > 1200 || landscape_width > 1920)
136 default_tile_size = 512;
138 // Adjust for some resolutions that barely straddle an extra
139 // tile when in portrait mode. This helps worst case scroll/raster
140 // by not needing a full extra tile for each row.
141 if (default_tile_size == 256 && portrait_width == 768)
142 default_tile_size += 32;
143 if (default_tile_size == 384 && portrait_width == 1200)
144 default_tile_size += 32;
145 } else {
146 // We don't know the exact resolution due to screen controls etc.
147 // So this just estimates the values above using tile counts.
148 int numTiles = (display_width * display_height) / (256 * 256);
149 if (numTiles > 16)
150 default_tile_size = 384;
151 if (numTiles >= 40)
152 default_tile_size = 512;
154 #endif
155 return gfx::Size(default_tile_size, default_tile_size);
158 // Check cc::TopControlsState, and blink::WebTopControlsState
159 // are kept in sync.
160 static_assert(int(blink::WebTopControlsBoth) == int(cc::BOTH),
161 "mismatching enums: BOTH");
162 static_assert(int(blink::WebTopControlsHidden) == int(cc::HIDDEN),
163 "mismatching enums: HIDDEN");
164 static_assert(int(blink::WebTopControlsShown) == int(cc::SHOWN),
165 "mismatching enums: SHOWN");
167 static cc::TopControlsState ConvertTopControlsState(
168 WebTopControlsState state) {
169 return static_cast<cc::TopControlsState>(state);
172 } // namespace
174 // static
175 scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
176 RenderWidget* widget,
177 CompositorDependencies* compositor_deps) {
178 scoped_ptr<RenderWidgetCompositor> compositor(
179 new RenderWidgetCompositor(widget, compositor_deps));
180 compositor->Initialize();
181 return compositor;
184 RenderWidgetCompositor::RenderWidgetCompositor(
185 RenderWidget* widget,
186 CompositorDependencies* compositor_deps)
187 : num_failed_recreate_attempts_(0),
188 widget_(widget),
189 compositor_deps_(compositor_deps),
190 weak_factory_(this) {
193 void RenderWidgetCompositor::Initialize() {
194 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
196 cc::LayerTreeSettings settings;
198 // For web contents, layer transforms should scale up the contents of layers
199 // to keep content always crisp when possible.
200 settings.layer_transforms_should_scale_layer_contents = true;
202 settings.throttle_frame_production =
203 !cmd->HasSwitch(switches::kDisableGpuVsync);
204 settings.use_external_begin_frame_source =
205 cmd->HasSwitch(switches::kEnableBeginFrameScheduling);
206 settings.main_frame_before_activation_enabled =
207 cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) &&
208 !cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation);
209 settings.report_overscroll_only_for_scrollable_axes =
210 !compositor_deps_->IsElasticOverscrollEnabled();
211 settings.accelerated_animation_enabled =
212 !cmd->HasSwitch(cc::switches::kDisableThreadedAnimation);
213 settings.use_display_lists = cmd->HasSwitch(switches::kEnableSlimmingPaint);
215 settings.default_tile_size = CalculateDefaultTileSize();
216 if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
217 int tile_width = 0;
218 GetSwitchValueAsInt(*cmd,
219 switches::kDefaultTileWidth,
221 std::numeric_limits<int>::max(),
222 &tile_width);
223 settings.default_tile_size.set_width(tile_width);
225 if (cmd->HasSwitch(switches::kDefaultTileHeight)) {
226 int tile_height = 0;
227 GetSwitchValueAsInt(*cmd,
228 switches::kDefaultTileHeight,
230 std::numeric_limits<int>::max(),
231 &tile_height);
232 settings.default_tile_size.set_height(tile_height);
235 int max_untiled_layer_width = settings.max_untiled_layer_size.width();
236 if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) {
237 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerWidth, 1,
238 std::numeric_limits<int>::max(),
239 &max_untiled_layer_width);
241 int max_untiled_layer_height = settings.max_untiled_layer_size.height();
242 if (cmd->HasSwitch(switches::kMaxUntiledLayerHeight)) {
243 GetSwitchValueAsInt(*cmd, switches::kMaxUntiledLayerHeight, 1,
244 std::numeric_limits<int>::max(),
245 &max_untiled_layer_height);
248 settings.max_untiled_layer_size = gfx::Size(max_untiled_layer_width,
249 max_untiled_layer_height);
251 settings.gpu_rasterization_msaa_sample_count =
252 compositor_deps_->GetGpuRasterizationMSAASampleCount();
253 settings.impl_side_painting = compositor_deps_->IsImplSidePaintingEnabled();
254 settings.gpu_rasterization_forced =
255 compositor_deps_->IsGpuRasterizationForced();
256 settings.gpu_rasterization_enabled =
257 compositor_deps_->IsGpuRasterizationEnabled();
259 if (compositor_deps_->IsThreadedGpuRasterizationEnabled()) {
260 settings.threaded_gpu_rasterization_enabled = true;
261 settings.gpu_rasterization_skewport_target_time_in_seconds = 0.2f;
264 settings.can_use_lcd_text = compositor_deps_->IsLcdTextEnabled();
265 settings.use_distance_field_text =
266 compositor_deps_->IsDistanceFieldTextEnabled();
267 settings.use_zero_copy = compositor_deps_->IsZeroCopyEnabled();
268 settings.use_one_copy = compositor_deps_->IsOneCopyEnabled();
269 settings.enable_elastic_overscroll =
270 compositor_deps_->IsElasticOverscrollEnabled();
271 settings.use_image_texture_target = compositor_deps_->GetImageTextureTarget();
272 settings.gather_pixel_refs = compositor_deps_->IsGatherPixelRefsEnabled();
274 if (cmd->HasSwitch(cc::switches::kTopControlsShowThreshold)) {
275 std::string top_threshold_str =
276 cmd->GetSwitchValueASCII(cc::switches::kTopControlsShowThreshold);
277 double show_threshold;
278 if (base::StringToDouble(top_threshold_str, &show_threshold) &&
279 show_threshold >= 0.f && show_threshold <= 1.f)
280 settings.top_controls_show_threshold = show_threshold;
283 if (cmd->HasSwitch(cc::switches::kTopControlsHideThreshold)) {
284 std::string top_threshold_str =
285 cmd->GetSwitchValueASCII(cc::switches::kTopControlsHideThreshold);
286 double hide_threshold;
287 if (base::StringToDouble(top_threshold_str, &hide_threshold) &&
288 hide_threshold >= 0.f && hide_threshold <= 1.f)
289 settings.top_controls_hide_threshold = hide_threshold;
292 settings.use_pinch_virtual_viewport =
293 cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport);
294 settings.verify_property_trees =
295 cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification);
296 settings.renderer_settings.allow_antialiasing &=
297 !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
298 settings.single_thread_proxy_scheduler =
299 compositor_deps_->UseSingleThreadScheduler();
301 // These flags should be mirrored by UI versions in ui/compositor/.
302 settings.initial_debug_state.show_debug_borders =
303 cmd->HasSwitch(cc::switches::kShowCompositedLayerBorders);
304 settings.initial_debug_state.show_fps_counter =
305 cmd->HasSwitch(cc::switches::kShowFPSCounter);
306 settings.initial_debug_state.show_layer_animation_bounds_rects =
307 cmd->HasSwitch(cc::switches::kShowLayerAnimationBounds);
308 settings.initial_debug_state.show_paint_rects =
309 cmd->HasSwitch(switches::kShowPaintRects);
310 settings.initial_debug_state.show_property_changed_rects =
311 cmd->HasSwitch(cc::switches::kShowPropertyChangedRects);
312 settings.initial_debug_state.show_surface_damage_rects =
313 cmd->HasSwitch(cc::switches::kShowSurfaceDamageRects);
314 settings.initial_debug_state.show_screen_space_rects =
315 cmd->HasSwitch(cc::switches::kShowScreenSpaceRects);
316 settings.initial_debug_state.show_replica_screen_space_rects =
317 cmd->HasSwitch(cc::switches::kShowReplicaScreenSpaceRects);
319 settings.initial_debug_state.SetRecordRenderingStats(
320 cmd->HasSwitch(cc::switches::kEnableGpuBenchmarking));
322 if (cmd->HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) {
323 const int kMinSlowDownScaleFactor = 0;
324 const int kMaxSlowDownScaleFactor = INT_MAX;
325 GetSwitchValueAsInt(
326 *cmd,
327 cc::switches::kSlowDownRasterScaleFactor,
328 kMinSlowDownScaleFactor,
329 kMaxSlowDownScaleFactor,
330 &settings.initial_debug_state.slow_down_raster_scale_factor);
333 if (cmd->HasSwitch(cc::switches::kMaxTilesForInterestArea)) {
334 int max_tiles_for_interest_area;
335 if (GetSwitchValueAsInt(*cmd,
336 cc::switches::kMaxTilesForInterestArea,
337 1, std::numeric_limits<int>::max(),
338 &max_tiles_for_interest_area))
339 settings.max_tiles_for_interest_area = max_tiles_for_interest_area;
342 if (cmd->HasSwitch(cc::switches::kMaxUnusedResourceMemoryUsagePercentage)) {
343 int max_unused_resource_memory_percentage;
344 if (GetSwitchValueAsInt(
345 *cmd,
346 cc::switches::kMaxUnusedResourceMemoryUsagePercentage,
347 0, 100,
348 &max_unused_resource_memory_percentage)) {
349 settings.max_unused_resource_memory_percentage =
350 max_unused_resource_memory_percentage;
354 settings.strict_layer_property_change_checking =
355 cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking);
357 #if defined(OS_ANDROID)
358 SynchronousCompositorFactory* synchronous_compositor_factory =
359 SynchronousCompositorFactory::GetInstance();
361 // We can't use GPU rasterization on low-end devices, because the Ganesh
362 // cache would consume too much memory.
363 if (base::SysInfo::IsLowEndDevice())
364 settings.gpu_rasterization_enabled = false;
365 settings.using_synchronous_renderer_compositor =
366 synchronous_compositor_factory;
367 settings.record_full_layer = widget_->DoesRecordFullLayer();
368 settings.report_overscroll_only_for_scrollable_axes =
369 !synchronous_compositor_factory;
370 settings.max_partial_texture_updates = 0;
371 if (synchronous_compositor_factory) {
372 // Android WebView uses system scrollbars, so make ours invisible.
373 settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR;
374 settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT;
375 } else {
376 settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
377 settings.scrollbar_fade_delay_ms = 300;
378 settings.scrollbar_fade_resize_delay_ms = 2000;
379 settings.scrollbar_fade_duration_ms = 300;
380 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
382 settings.renderer_settings.highp_threshold_min = 2048;
383 // Android WebView handles root layer flings itself.
384 settings.ignore_root_layer_flings =
385 synchronous_compositor_factory;
386 // Memory policy on Android WebView does not depend on whether device is
387 // low end, so always use default policy.
388 bool use_low_memory_policy =
389 base::SysInfo::IsLowEndDevice() && !synchronous_compositor_factory;
390 // RGBA_4444 textures are only enabled for low end devices
391 // and are disabled for Android WebView as it doesn't support the format.
392 settings.renderer_settings.use_rgba_4444_textures = use_low_memory_policy;
393 if (use_low_memory_policy) {
394 // On low-end we want to be very carefull about killing other
395 // apps. So initially we use 50% more memory to avoid flickering
396 // or raster-on-demand.
397 settings.max_memory_for_prepaint_percentage = 67;
398 } else {
399 // On other devices we have increased memory excessively to avoid
400 // raster-on-demand already, so now we reserve 50% _only_ to avoid
401 // raster-on-demand, and use 50% of the memory otherwise.
402 settings.max_memory_for_prepaint_percentage = 50;
404 // Webview does not own the surface so should not clear it.
405 settings.renderer_settings.should_clear_root_render_pass =
406 !synchronous_compositor_factory;
408 // TODO(danakj): Only do this on low end devices.
409 settings.create_low_res_tiling = true;
411 #elif !defined(OS_MACOSX)
412 if (ui::IsOverlayScrollbarEnabled()) {
413 settings.scrollbar_animator = cc::LayerTreeSettings::THINNING;
414 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
415 } else if (cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport)) {
416 // use_pinch_zoom_scrollbars is only true on desktop when non-overlay
417 // scrollbars are in use.
418 settings.use_pinch_zoom_scrollbars = true;
419 settings.scrollbar_animator = cc::LayerTreeSettings::LINEAR_FADE;
420 settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
422 settings.scrollbar_fade_delay_ms = 500;
423 settings.scrollbar_fade_resize_delay_ms = 500;
424 settings.scrollbar_fade_duration_ms = 300;
426 // When pinching in, only show the pinch-viewport overlay scrollbars if the
427 // page scale is at least some threshold away from the minimum. i.e. don't
428 // show the pinch scrollbars when at minimum scale.
429 settings.scrollbar_show_scale_threshold = 1.05f;
430 #endif
432 if (cmd->HasSwitch(switches::kEnableLowResTiling))
433 settings.create_low_res_tiling = true;
434 if (cmd->HasSwitch(switches::kDisableLowResTiling))
435 settings.create_low_res_tiling = false;
437 scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
438 compositor_deps_->GetCompositorImplThreadTaskRunner();
439 scoped_refptr<base::SingleThreadTaskRunner>
440 main_thread_compositor_task_runner =
441 compositor_deps_->GetCompositorMainThreadTaskRunner();
442 cc::SharedBitmapManager* shared_bitmap_manager =
443 compositor_deps_->GetSharedBitmapManager();
444 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
445 compositor_deps_->GetGpuMemoryBufferManager();
446 cc::TaskGraphRunner* task_graph_runner =
447 compositor_deps_->GetTaskGraphRunner();
449 scoped_ptr<cc::BeginFrameSource> external_begin_frame_source;
450 if (settings.use_external_begin_frame_source) {
451 external_begin_frame_source =
452 compositor_deps_->CreateExternalBeginFrameSource(widget_->routing_id());
455 if (compositor_thread_task_runner.get()) {
456 layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
457 this, shared_bitmap_manager, gpu_memory_buffer_manager,
458 task_graph_runner, settings, main_thread_compositor_task_runner,
459 compositor_thread_task_runner, external_begin_frame_source.Pass());
460 } else {
461 layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
462 this, this, shared_bitmap_manager, gpu_memory_buffer_manager,
463 task_graph_runner, settings, main_thread_compositor_task_runner,
464 external_begin_frame_source.Pass());
466 DCHECK(layer_tree_host_);
469 RenderWidgetCompositor::~RenderWidgetCompositor() {}
471 const base::WeakPtr<cc::InputHandler>&
472 RenderWidgetCompositor::GetInputHandler() {
473 return layer_tree_host_->GetInputHandler();
476 bool RenderWidgetCompositor::BeginMainFrameRequested() const {
477 return layer_tree_host_->BeginMainFrameRequested();
480 void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() {
481 layer_tree_host_->SetNeedsDisplayOnAllLayers();
484 void RenderWidgetCompositor::SetRasterizeOnlyVisibleContent() {
485 cc::LayerTreeDebugState current = layer_tree_host_->debug_state();
486 current.rasterize_only_visible_content = true;
487 layer_tree_host_->SetDebugState(current);
490 void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) {
491 layer_tree_host_->SetNeedsRedrawRect(damage_rect);
494 void RenderWidgetCompositor::SetNeedsForcedRedraw() {
495 layer_tree_host_->SetNextCommitForcesRedraw();
496 setNeedsAnimate();
499 scoped_ptr<cc::SwapPromiseMonitor>
500 RenderWidgetCompositor::CreateLatencyInfoSwapPromiseMonitor(
501 ui::LatencyInfo* latency) {
502 return scoped_ptr<cc::SwapPromiseMonitor>(
503 new cc::LatencyInfoSwapPromiseMonitor(
504 latency, layer_tree_host_.get(), NULL));
507 void RenderWidgetCompositor::QueueSwapPromise(
508 scoped_ptr<cc::SwapPromise> swap_promise) {
509 layer_tree_host_->QueueSwapPromise(swap_promise.Pass());
512 int RenderWidgetCompositor::GetLayerTreeId() const {
513 return layer_tree_host_->id();
516 int RenderWidgetCompositor::GetSourceFrameNumber() const {
517 return layer_tree_host_->source_frame_number();
520 void RenderWidgetCompositor::SetNeedsUpdateLayers() {
521 layer_tree_host_->SetNeedsUpdateLayers();
524 void RenderWidgetCompositor::SetNeedsCommit() {
525 layer_tree_host_->SetNeedsCommit();
528 void RenderWidgetCompositor::NotifyInputThrottledUntilCommit() {
529 layer_tree_host_->NotifyInputThrottledUntilCommit();
532 const cc::Layer* RenderWidgetCompositor::GetRootLayer() const {
533 return layer_tree_host_->root_layer();
536 int RenderWidgetCompositor::ScheduleMicroBenchmark(
537 const std::string& name,
538 scoped_ptr<base::Value> value,
539 const base::Callback<void(scoped_ptr<base::Value>)>& callback) {
540 return layer_tree_host_->ScheduleMicroBenchmark(name, value.Pass(), callback);
543 bool RenderWidgetCompositor::SendMessageToMicroBenchmark(
544 int id,
545 scoped_ptr<base::Value> value) {
546 return layer_tree_host_->SendMessageToMicroBenchmark(id, value.Pass());
549 void RenderWidgetCompositor::StartCompositor() {
550 layer_tree_host_->SetLayerTreeHostClientReady();
553 void RenderWidgetCompositor::setRootLayer(const blink::WebLayer& layer) {
554 layer_tree_host_->SetRootLayer(
555 static_cast<const cc_blink::WebLayerImpl*>(&layer)->layer());
558 void RenderWidgetCompositor::clearRootLayer() {
559 layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>());
562 void RenderWidgetCompositor::setViewportSize(
563 const WebSize&,
564 const WebSize& device_viewport_size) {
565 layer_tree_host_->SetViewportSize(device_viewport_size);
568 void RenderWidgetCompositor::setViewportSize(
569 const WebSize& device_viewport_size) {
570 layer_tree_host_->SetViewportSize(device_viewport_size);
573 WebSize RenderWidgetCompositor::layoutViewportSize() const {
574 return layer_tree_host_->device_viewport_size();
577 WebSize RenderWidgetCompositor::deviceViewportSize() const {
578 return layer_tree_host_->device_viewport_size();
581 WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom(
582 const WebFloatPoint& point) const {
583 return point;
586 void RenderWidgetCompositor::setDeviceScaleFactor(float device_scale) {
587 layer_tree_host_->SetDeviceScaleFactor(device_scale);
590 float RenderWidgetCompositor::deviceScaleFactor() const {
591 return layer_tree_host_->device_scale_factor();
594 void RenderWidgetCompositor::setBackgroundColor(blink::WebColor color) {
595 layer_tree_host_->set_background_color(color);
598 void RenderWidgetCompositor::setHasTransparentBackground(bool transparent) {
599 layer_tree_host_->set_has_transparent_background(transparent);
602 void RenderWidgetCompositor::setVisible(bool visible) {
603 layer_tree_host_->SetVisible(visible);
606 void RenderWidgetCompositor::setPageScaleFactorAndLimits(
607 float page_scale_factor, float minimum, float maximum) {
608 layer_tree_host_->SetPageScaleFactorAndLimits(
609 page_scale_factor, minimum, maximum);
612 void RenderWidgetCompositor::startPageScaleAnimation(
613 const blink::WebPoint& destination,
614 bool use_anchor,
615 float new_page_scale,
616 double duration_sec) {
617 base::TimeDelta duration = base::TimeDelta::FromMicroseconds(
618 duration_sec * base::Time::kMicrosecondsPerSecond);
619 layer_tree_host_->StartPageScaleAnimation(
620 gfx::Vector2d(destination.x, destination.y),
621 use_anchor,
622 new_page_scale,
623 duration);
626 void RenderWidgetCompositor::heuristicsForGpuRasterizationUpdated(
627 bool matches_heuristics) {
628 layer_tree_host_->SetHasGpuRasterizationTrigger(matches_heuristics);
631 void RenderWidgetCompositor::setNeedsAnimate() {
632 layer_tree_host_->SetNeedsAnimate();
635 bool RenderWidgetCompositor::commitRequested() const {
636 return layer_tree_host_->CommitRequested();
639 void RenderWidgetCompositor::didStopFlinging() {
640 layer_tree_host_->DidStopFlinging();
643 void RenderWidgetCompositor::registerForAnimations(blink::WebLayer* layer) {
644 cc::Layer* cc_layer = static_cast<cc_blink::WebLayerImpl*>(layer)->layer();
645 cc_layer->layer_animation_controller()->SetAnimationRegistrar(
646 layer_tree_host_->animation_registrar());
649 void RenderWidgetCompositor::registerViewportLayers(
650 const blink::WebLayer* overscrollElasticityLayer,
651 const blink::WebLayer* pageScaleLayer,
652 const blink::WebLayer* innerViewportScrollLayer,
653 const blink::WebLayer* outerViewportScrollLayer) {
654 layer_tree_host_->RegisterViewportLayers(
655 // The scroll elasticity layer will only exist when using pinch virtual
656 // viewports.
657 overscrollElasticityLayer
658 ? static_cast<const cc_blink::WebLayerImpl*>(
659 overscrollElasticityLayer)->layer()
660 : NULL,
661 static_cast<const cc_blink::WebLayerImpl*>(pageScaleLayer)->layer(),
662 static_cast<const cc_blink::WebLayerImpl*>(innerViewportScrollLayer)
663 ->layer(),
664 // The outer viewport layer will only exist when using pinch virtual
665 // viewports.
666 outerViewportScrollLayer
667 ? static_cast<const cc_blink::WebLayerImpl*>(outerViewportScrollLayer)
668 ->layer()
669 : NULL);
672 void RenderWidgetCompositor::clearViewportLayers() {
673 layer_tree_host_->RegisterViewportLayers(
674 scoped_refptr<cc::Layer>(), scoped_refptr<cc::Layer>(),
675 scoped_refptr<cc::Layer>(), scoped_refptr<cc::Layer>());
678 void RenderWidgetCompositor::registerSelection(
679 const blink::WebSelectionBound& start,
680 const blink::WebSelectionBound& end) {
681 layer_tree_host_->RegisterSelection(ConvertWebSelectionBound(start),
682 ConvertWebSelectionBound(end));
685 void RenderWidgetCompositor::clearSelection() {
686 cc::LayerSelectionBound empty_selection;
687 layer_tree_host_->RegisterSelection(empty_selection, empty_selection);
690 void CompositeAndReadbackAsyncCallback(
691 blink::WebCompositeAndReadbackAsyncCallback* callback,
692 scoped_ptr<cc::CopyOutputResult> result) {
693 if (result->HasBitmap()) {
694 scoped_ptr<SkBitmap> result_bitmap = result->TakeBitmap();
695 callback->didCompositeAndReadback(*result_bitmap);
696 } else {
697 callback->didCompositeAndReadback(SkBitmap());
701 void RenderWidgetCompositor::compositeAndReadbackAsync(
702 blink::WebCompositeAndReadbackAsyncCallback* callback) {
703 DCHECK(!temporary_copy_output_request_);
704 temporary_copy_output_request_ =
705 cc::CopyOutputRequest::CreateBitmapRequest(
706 base::Bind(&CompositeAndReadbackAsyncCallback, callback));
707 // Force a commit to happen. The temporary copy output request will
708 // be installed after layout which will happen as a part of the commit, for
709 // widgets that delay the creation of their output surface.
710 bool threaded = !!compositor_deps_->GetCompositorImplThreadTaskRunner().get();
711 if (!threaded &&
712 !layer_tree_host_->settings().single_thread_proxy_scheduler) {
713 layer_tree_host_->Composite(gfx::FrameTime::Now());
714 } else {
715 layer_tree_host_->SetNeedsCommit();
719 void RenderWidgetCompositor::finishAllRendering() {
720 layer_tree_host_->FinishAllRendering();
723 void RenderWidgetCompositor::setDeferCommits(bool defer_commits) {
724 layer_tree_host_->SetDeferCommits(defer_commits);
727 void RenderWidgetCompositor::setShowFPSCounter(bool show) {
728 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state();
729 debug_state.show_fps_counter = show;
730 layer_tree_host_->SetDebugState(debug_state);
733 void RenderWidgetCompositor::setShowPaintRects(bool show) {
734 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state();
735 debug_state.show_paint_rects = show;
736 layer_tree_host_->SetDebugState(debug_state);
739 void RenderWidgetCompositor::setShowDebugBorders(bool show) {
740 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state();
741 debug_state.show_debug_borders = show;
742 layer_tree_host_->SetDebugState(debug_state);
745 void RenderWidgetCompositor::setContinuousPaintingEnabled(bool enabled) {
746 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state();
747 debug_state.continuous_painting = enabled;
748 layer_tree_host_->SetDebugState(debug_state);
751 void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) {
752 cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state();
753 debug_state.show_touch_event_handler_rects = show;
754 debug_state.show_wheel_event_handler_rects = show;
755 debug_state.show_non_fast_scrollable_rects = show;
756 layer_tree_host_->SetDebugState(debug_state);
759 void RenderWidgetCompositor::updateTopControlsState(
760 WebTopControlsState constraints,
761 WebTopControlsState current,
762 bool animate) {
763 layer_tree_host_->UpdateTopControlsState(ConvertTopControlsState(constraints),
764 ConvertTopControlsState(current),
765 animate);
768 void RenderWidgetCompositor::setTopControlsHeight(float height, bool shrink) {
769 layer_tree_host_->SetTopControlsHeight(height, shrink);
772 void RenderWidgetCompositor::setTopControlsShownRatio(float ratio) {
773 layer_tree_host_->SetTopControlsShownRatio(ratio);
776 void RenderWidgetCompositor::WillBeginMainFrame() {
777 widget_->willBeginCompositorFrame();
780 void RenderWidgetCompositor::DidBeginMainFrame() {
783 void RenderWidgetCompositor::BeginMainFrame(const cc::BeginFrameArgs& args) {
784 double frame_time_sec = (args.frame_time - base::TimeTicks()).InSecondsF();
785 double deadline_sec = (args.deadline - base::TimeTicks()).InSecondsF();
786 double interval_sec = args.interval.InSecondsF();
787 WebBeginFrameArgs web_begin_frame_args =
788 WebBeginFrameArgs(frame_time_sec, deadline_sec, interval_sec);
789 compositor_deps_->GetRendererScheduler()->WillBeginFrame(args);
790 widget_->webwidget()->beginFrame(web_begin_frame_args);
793 void RenderWidgetCompositor::BeginMainFrameNotExpectedSoon() {
794 compositor_deps_->GetRendererScheduler()->BeginFrameNotExpectedSoon();
797 void RenderWidgetCompositor::Layout() {
798 widget_->webwidget()->layout();
800 if (temporary_copy_output_request_) {
801 // For WebViewImpl, this will always have a root layer. For other widgets,
802 // the widget may be closed before servicing this request, so ignore it.
803 if (cc::Layer* root_layer = layer_tree_host_->root_layer()) {
804 root_layer->RequestCopyOfOutput(temporary_copy_output_request_.Pass());
805 } else {
806 temporary_copy_output_request_->SendEmptyResult();
807 temporary_copy_output_request_ = nullptr;
812 void RenderWidgetCompositor::ApplyViewportDeltas(
813 const gfx::Vector2dF& inner_delta,
814 const gfx::Vector2dF& outer_delta,
815 const gfx::Vector2dF& elastic_overscroll_delta,
816 float page_scale,
817 float top_controls_delta) {
818 widget_->webwidget()->applyViewportDeltas(
819 inner_delta,
820 outer_delta,
821 elastic_overscroll_delta,
822 page_scale,
823 top_controls_delta);
826 void RenderWidgetCompositor::ApplyViewportDeltas(
827 const gfx::Vector2d& scroll_delta,
828 float page_scale,
829 float top_controls_delta) {
830 widget_->webwidget()->applyViewportDeltas(
831 scroll_delta,
832 page_scale,
833 top_controls_delta);
836 void RenderWidgetCompositor::RequestNewOutputSurface() {
837 // If the host is closing, then no more compositing is possible. This
838 // prevents shutdown races between handling the close message and
839 // the CreateOutputSurface task.
840 if (widget_->host_closing())
841 return;
843 // TODO(robliao): Remove ScopedTracker below once https://crbug.com/466870
844 // is fixed.
845 tracked_objects::ScopedTracker tracking_profile(
846 FROM_HERE_WITH_EXPLICIT_FUNCTION(
847 "466870 RenderWidgetCompositor::RequestNewOutputSurface"));
849 bool fallback =
850 num_failed_recreate_attempts_ >= OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK;
851 scoped_ptr<cc::OutputSurface> surface(widget_->CreateOutputSurface(fallback));
853 if (!surface) {
854 DidFailToInitializeOutputSurface();
855 return;
858 layer_tree_host_->SetOutputSurface(surface.Pass());
861 void RenderWidgetCompositor::DidInitializeOutputSurface() {
862 num_failed_recreate_attempts_ = 0;
865 void RenderWidgetCompositor::DidFailToInitializeOutputSurface() {
866 ++num_failed_recreate_attempts_;
867 // Tolerate a certain number of recreation failures to work around races
868 // in the output-surface-lost machinery.
869 LOG_IF(FATAL, (num_failed_recreate_attempts_ >= MAX_OUTPUT_SURFACE_RETRIES))
870 << "Failed to create a fallback OutputSurface.";
872 base::MessageLoop::current()->PostTask(
873 FROM_HERE, base::Bind(&RenderWidgetCompositor::RequestNewOutputSurface,
874 weak_factory_.GetWeakPtr()));
877 void RenderWidgetCompositor::WillCommit() {
880 void RenderWidgetCompositor::DidCommit() {
881 DCHECK(!temporary_copy_output_request_);
882 widget_->DidCommitCompositorFrame();
883 widget_->didBecomeReadyForAdditionalInput();
884 compositor_deps_->GetRendererScheduler()->DidCommitFrameToCompositor();
887 void RenderWidgetCompositor::DidCommitAndDrawFrame() {
888 widget_->didCommitAndDrawCompositorFrame();
891 void RenderWidgetCompositor::DidCompleteSwapBuffers() {
892 widget_->didCompleteSwapBuffers();
893 bool threaded = !!compositor_deps_->GetCompositorImplThreadTaskRunner().get();
894 if (!threaded)
895 widget_->OnSwapBuffersComplete();
898 void RenderWidgetCompositor::DidCompletePageScaleAnimation() {
899 widget_->DidCompletePageScaleAnimation();
902 void RenderWidgetCompositor::ScheduleAnimation() {
903 widget_->scheduleAnimation();
906 void RenderWidgetCompositor::DidPostSwapBuffers() {
907 widget_->OnSwapBuffersPosted();
910 void RenderWidgetCompositor::DidAbortSwapBuffers() {
911 widget_->OnSwapBuffersAborted();
914 void RenderWidgetCompositor::RateLimitSharedMainThreadContext() {
915 cc::ContextProvider* provider =
916 compositor_deps_->GetSharedMainThreadContextProvider();
917 // provider can be NULL after the GPU process crashed enough times and we
918 // don't want to restart it any more (falling back to software).
919 if (!provider)
920 return;
921 provider->ContextGL()->RateLimitOffscreenContextCHROMIUM();
924 } // namespace content